Skip to content

Commit

Permalink
Merge pull request #427 from MartinGallauner/intro-spring-boot
Browse files Browse the repository at this point in the history
Intro spring boot
  • Loading branch information
VerisimilitudeX authored Oct 31, 2023
2 parents 138d0b4 + 27b72ae commit e1457d1
Show file tree
Hide file tree
Showing 16 changed files with 315 additions and 0 deletions.
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ plugins {
id 'application'
id("org.openjfx.javafxplugin") version "0.0.13"
id("maven-publish")
id 'java'
id 'org.springframework.boot' version '3.1.4'
id 'io.spring.dependency-management' version '1.1.3'
}

repositories {
Expand All @@ -18,10 +21,16 @@ javafx {
}

dependencies {

compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.30'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.2.0'

// Use JUnit test framework.
testImplementation "org.junit.jupiter:junit-jupiter:${junitVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test'

// This dependency is used by the application.
implementation 'com.google.guava:guava:31.0.1-jre'
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/DNAnalyzer/DNAnalyzerApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package DNAnalyzer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* Main class to run the DNAnalyzer program with a webserver.
*/
@SpringBootApplication
public class DNAnalyzerApplication {

/**
* Main method to run the DNAnalyzer program with a webserver.
*/
public static void main(final String[] args) {
SpringApplication.run(DNAnalyzerApplication.class);
}
}
8 changes: 8 additions & 0 deletions src/main/java/DNAnalyzer/adapter/AnalyseController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package DNAnalyzer.adapter;

/**
* Controller for the analysis of DNA.
*/
public class AnalyseController {

}
52 changes: 52 additions & 0 deletions src/main/java/DNAnalyzer/adapter/ApiKeyController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package DNAnalyzer.adapter;

import DNAnalyzer.core.port.in.GetApiKeyUseCase;
import DNAnalyzer.core.port.in.SetApiKeyUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

/**
* Controller to get and set the API key.
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/api-key")
public class ApiKeyController {

/**
* Contructor of the controller.
*
* @param getApiKeyUseCase the use case to get the API key
* @param setApiKeyUseCase the use case to set the API key
*/
public ApiKeyController(GetApiKeyUseCase getApiKeyUseCase, SetApiKeyUseCase setApiKeyUseCase) {
this.getApiKeyUseCase = getApiKeyUseCase;
this.setApiKeyUseCase = setApiKeyUseCase;
}

private GetApiKeyUseCase getApiKeyUseCase;
private SetApiKeyUseCase setApiKeyUseCase;

/**
* Get the API key.
*
* @return the API key
*/
@GetMapping
public ApiKeyResponse getApiKey() {
String apiKey = getApiKeyUseCase.getApiKey();
return new ApiKeyResponse(apiKey);
}

/**
* Set the API key.
*
* @param request the request containing the new API key
* @return the new API key
*/
@PutMapping
public ApiKeyResponse setApiKey(@RequestBody SetApiKeyRequest request) {
String apiKey = setApiKeyUseCase.setApiKey(request.apiKey());
return new ApiKeyResponse(apiKey);
}
}
8 changes: 8 additions & 0 deletions src/main/java/DNAnalyzer/adapter/ApiKeyResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package DNAnalyzer.adapter;

/**
* Response to return the API key.
* @param apiKey the API key.
*/
public record ApiKeyResponse(String apiKey) {
}
8 changes: 8 additions & 0 deletions src/main/java/DNAnalyzer/adapter/SetApiKeyRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package DNAnalyzer.adapter;

/**
* Request to set the API key.
* @param apiKey the API key to set.
*/
public record SetApiKeyRequest(String apiKey) {
}
15 changes: 15 additions & 0 deletions src/main/java/DNAnalyzer/core/ApiKeyMissingException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package DNAnalyzer.core;

/**
* Exception thrown when the API key is missing.
*/
public class ApiKeyMissingException extends RuntimeException {

/**
* Constructor of ApiKeyMissingException.
* @param message the message of the exception.
*/
public ApiKeyMissingException(String message) {
super(message);
}
}
31 changes: 31 additions & 0 deletions src/main/java/DNAnalyzer/core/ApiKeyService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package DNAnalyzer.core;


import DNAnalyzer.core.port.in.GetApiKeyUseCase;
import DNAnalyzer.core.port.in.SetApiKeyUseCase;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
* The purpose of this service is to handle all operations concerning the OpenAI API key.
*/
@Service
public class ApiKeyService implements GetApiKeyUseCase, SetApiKeyUseCase {

@Value("${openai.api.key}")
private String apiKey;

@Override
public String getApiKey() {
if (apiKey == null) {
throw new ApiKeyMissingException("No API-Key defined.");
}
return apiKey;
}

@Override
public String setApiKey(String apiKey) {
this.apiKey = apiKey;
return this.apiKey;
}
}
7 changes: 7 additions & 0 deletions src/main/java/DNAnalyzer/core/port/in/AnalyzeDnaRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package DNAnalyzer.core.port.in;

/**
* The request body holding the parameters for the analyze DNA use case.
*/
public record AnalyzeDnaRequest() {
}
14 changes: 14 additions & 0 deletions src/main/java/DNAnalyzer/core/port/in/AnalyzeDnaUseCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package DNAnalyzer.core.port.in;

/**
* Use case interface to analyze DNA.
*/
public interface AnalyzeDnaUseCase {

/**
* Analyze the DNA.
* @param request the request to analyze the DNA
* @return the result of the analysis
*/
AnalyzeResult analyzeDna(AnalyzeDnaRequest request);
}
7 changes: 7 additions & 0 deletions src/main/java/DNAnalyzer/core/port/in/AnalyzeResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package DNAnalyzer.core.port.in;

/**
* Result of an DNA analysis.
*/
public class AnalyzeResult {
}
13 changes: 13 additions & 0 deletions src/main/java/DNAnalyzer/core/port/in/GetApiKeyUseCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package DNAnalyzer.core.port.in;

/**
* Use case interface to get the API key.
*/
public interface GetApiKeyUseCase {

/**
* Use case to get the set API key.
* @return the api key
*/
String getApiKey();
}
14 changes: 14 additions & 0 deletions src/main/java/DNAnalyzer/core/port/in/SetApiKeyUseCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package DNAnalyzer.core.port.in;

/**
* Use case interface to set the API key.
*/
public interface SetApiKeyUseCase {

/**
* Set the API key for the OpenAI API.
* @param apiKey the new API key.
* @return the api key
*/
String setApiKey(String apiKey);
}
3 changes: 3 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
openai:
api:
key: default
66 changes: 66 additions & 0 deletions src/test/java/DNAnalyzer/adapter/ApiKeyControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package DNAnalyzer.adapter;

import DNAnalyzer.core.port.in.GetApiKeyUseCase;
import DNAnalyzer.core.port.in.SetApiKeyUseCase;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import static org.springframework.http.HttpHeaders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@WebMvcTest(ApiKeyController.class)
class ApiKeyControllerTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private GetApiKeyUseCase getApiKeyUseCase;

@MockBean
private SetApiKeyUseCase setApiKeyUseCase;

@Test
void getApiKey() throws Exception {
when(getApiKeyUseCase.getApiKey()).thenReturn("mock-key");

MvcResult mvcResult = this.mockMvc
.perform(MockMvcRequestBuilders.get("/api-key")
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().is(200))
.andExpect(MockMvcResultMatchers.jsonPath("$.apiKey", is("mock-key")))
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}

@Test
void setApiKey() throws Exception {
when(setApiKeyUseCase.setApiKey(anyString())).thenAnswer(i -> i.getArguments()[0]);

MvcResult mvcResult = this.mockMvc
.perform(MockMvcRequestBuilders.put("/api-key")
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content("{\"apiKey\":\"new-key\"}"))
.andExpect(MockMvcResultMatchers.status().is(200))
.andExpect(MockMvcResultMatchers.jsonPath("$.apiKey", is("new-key")))
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
}
42 changes: 42 additions & 0 deletions src/test/java/DNAnalyzer/core/ApiKeyServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package DNAnalyzer.core;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class ApiKeyServiceTest {

@DisplayName("Get the api key, given it was set before.")
@Test
void testGetApiKey_key_is_set() {
ApiKeyService apiKeyService = new ApiKeyService();
ReflectionTestUtils.setField(apiKeyService, "apiKey", "2134432-mock-key");
String result = apiKeyService.getApiKey();
Assertions.assertThat(result).isEqualTo("2134432-mock-key");
}

@DisplayName("Get api key, verify that an exception is thrown when not set.")
@Test
void testGetApiKey_no_key_is_set() {
ApiKeyService apiKeyService = new ApiKeyService();

Exception exception = assertThrows(ApiKeyMissingException.class, apiKeyService::getApiKey);

assertEquals("No API-Key defined.", exception.getMessage());
}

@DisplayName("Set a new API key.")
@Test
void setApiKey() {
String newKey = "9999999-new-key";

ApiKeyService apiKeyService = new ApiKeyService();
String result = apiKeyService.setApiKey(newKey);

Assertions.assertThat(result).isEqualTo("9999999-new-key");
}
}

0 comments on commit e1457d1

Please sign in to comment.