diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index cb55666..e0d4582 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -33,5 +33,8 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - - name: Run Tests + - name: Run Tests with Quarkus (default) run: mvn --batch-mode verify coveralls:report -DrepoToken=${{ secrets.COVERALLS_REPO_TOKEN }} + + - name: Run Tests with Spring Boot + run: mvn --batch-mode verify -Pspring \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index bcd08b3..d618908 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,6 +57,7 @@ RUN curl https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/${FLYWAY # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" ENV JAVA_APP_JAR="quarkus-run.jar" + COPY app/quarkus-app/target/quarkus-app/ /deployments/ COPY resources/flyway/db/migration /flyway/sql diff --git a/README.md b/README.md index 7e69492..1429c96 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ Fornecendo toda infraestrutura necessária para o desenvolvedor. O framework é definido pelo profile, sendo que o default é do Quarkus. #### Quarkus + ```bash mvn clean install -Pquarkus # or by default: @@ -97,12 +98,6 @@ mvn clean install #### Spring boot -Nota: O projeto com Spring Boot não está finalizado. No caso o profile do Spring está sem o módulo -de output: `restclient-http-service`, pois o Spring Boot não tem uma implementação para o microprofile-restclient -no caso, o ideal seria a criação de um modulo com o Feign para implementar a porta do use-case: `ProtocolGeneratorClient` -Porém, atualmente para o projeto rodar, essa porta foi implementada como um fake no modulo da app `spring-app` no seguinte package: ` br.com.helpdev.protocolgenerator`. -Mas o módulo de `acceptance-test` irá falhar, pois o mesmo faz um mock desse serviço; - ```bash mvn clean install -Pspring ``` diff --git a/acceptance-test/pom.xml b/acceptance-test/pom.xml index 82f4ccf..ef3b60a 100644 --- a/acceptance-test/pom.xml +++ b/acceptance-test/pom.xml @@ -144,6 +144,11 @@ org.apache.maven.plugins maven-failsafe-plugin ${maven-failsafe-plugin.version} + + + ${project.activeProfiles[0].id} + + diff --git a/acceptance-test/src/test/java/br/com/helpdev/atdd/DefaultContainerStarterTest.java b/acceptance-test/src/test/java/br/com/helpdev/atdd/DefaultContainerStarterTest.java index 6e72f75..17c0250 100644 --- a/acceptance-test/src/test/java/br/com/helpdev/atdd/DefaultContainerStarterTest.java +++ b/acceptance-test/src/test/java/br/com/helpdev/atdd/DefaultContainerStarterTest.java @@ -22,6 +22,8 @@ abstract class DefaultContainerStarterTest { private static final GenericContainer MYSQL_CONTAINER; private static final Network NETWORK = Network.newNetwork(); protected static final WireMockServer MOCK_SERVER; + private static final String PROFILE_ID_SPRING = "spring"; + public static final String PROP_PROFILE_ID = "profileId"; /* Containers are initialized in static block to create only once in test execution */ static { @@ -66,8 +68,10 @@ private static GenericContainer buildAppContainer(final Startable... dependsO .withEnv("MYSQL_PASSWORD", "test") .withEnv("MYSQL_URL", "jdbc:mysql://testdb:" + MySQLContainer.MYSQL_PORT + "/test?autoReconnect=true&useSSL=false") .withExposedPorts(8080) - //TODO: change to: '/actuator/health' if you use spring - .waitingFor(Wait.forHttp("/q/health/ready").forStatusCode(200)) + .waitingFor(System.getProperty(PROP_PROFILE_ID).equals(PROFILE_ID_SPRING) ? + Wait.forHttp("/actuator/health").forStatusCode(200) : + Wait.forHttp("/q/health/ready").forStatusCode(200) + ) .withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger("APP_CONTAINER"))); } diff --git a/adapter/output/feign-http-services/pom.xml b/adapter/output/feign-http-services/pom.xml new file mode 100644 index 0000000..7c4b180 --- /dev/null +++ b/adapter/output/feign-http-services/pom.xml @@ -0,0 +1,95 @@ + + + + modular-architecture + br.com.helpdev + 0.0.4-SNAPSHOT + ../../../pom.xml + + 4.0.0 + + feign-http-services + + + 17 + 17 + **/*Dto.* + **.dto.* + 12.1 + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + javax.ws.rs + javax.ws.rs-api + + + com.fasterxml.jackson.core + jackson-databind + provided + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + io.github.openfeign + feign-jaxrs + ${feign-jaxrs.version} + + + + + br.com.helpdev + use-case + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + org.assertj + assertj-core + test + + + org.slf4j + slf4j-simple + test + + + + \ No newline at end of file diff --git a/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/ProtocolGeneratorClientImpl.java b/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/ProtocolGeneratorClientImpl.java new file mode 100644 index 0000000..4a3e9d2 --- /dev/null +++ b/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/ProtocolGeneratorClientImpl.java @@ -0,0 +1,27 @@ +package br.com.helpdev.output.feign; + + +import br.com.helpdev.output.feign.client.RandomDataApiClient; +import br.com.helpdev.usecase.port.ProtocolGeneratorClient; +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.inject.Named; + +@ApplicationScoped +@Named +public class ProtocolGeneratorClientImpl implements ProtocolGeneratorClient { + + private final RandomDataApiClient randomDataApiClient; + + @Inject + public ProtocolGeneratorClientImpl(final RandomDataApiClient randomDataApiClient) { + this.randomDataApiClient = randomDataApiClient; + } + + @Override + public String generateNewProtocol() { + /* Generate US-SSN to simulate protocol */ + return randomDataApiClient.generate().getValidUsSsn(); + } + +} diff --git a/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/client/RandomDataApiClient.java b/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/client/RandomDataApiClient.java new file mode 100644 index 0000000..fbc5e03 --- /dev/null +++ b/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/client/RandomDataApiClient.java @@ -0,0 +1,14 @@ +package br.com.helpdev.output.feign.client; + +import br.com.helpdev.output.feign.client.dto.RandomIdNumberDto; +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import org.springframework.cloud.openfeign.FeignClient; + +@FeignClient(name = "random-data-api", url = "${random-data-api.url}", path = "/api/id_number/random_id_number") +public interface RandomDataApiClient { + + @GET + @Produces("application/json") + RandomIdNumberDto generate(); +} diff --git a/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/client/dto/RandomIdNumberDto.java b/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/client/dto/RandomIdNumberDto.java new file mode 100644 index 0000000..74be14e --- /dev/null +++ b/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/client/dto/RandomIdNumberDto.java @@ -0,0 +1,14 @@ +package br.com.helpdev.output.feign.client.dto; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class RandomIdNumberDto { + private String id; + private String uid; + private String validUsSsn; + private String invalidUsSsn; +} diff --git a/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/config/FeignContractConfiguration.java b/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/config/FeignContractConfiguration.java new file mode 100644 index 0000000..0bce1bc --- /dev/null +++ b/adapter/output/feign-http-services/src/main/java/br/com/helpdev/output/feign/config/FeignContractConfiguration.java @@ -0,0 +1,21 @@ +package br.com.helpdev.output.feign.config; + +import feign.Contract; +import feign.jaxrs.JAXRSContract; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +@EnableFeignClients( + basePackages = {"br.com.helpdev.output.feign"} +) +public class FeignContractConfiguration { + + @Bean + Contract contract() { + return new JAXRSContract(); + } + +} diff --git a/adapter/output/feign-http-services/src/test/java/br/com/helpdev/output/feign/ProtocolGeneratorClientImplTest.java b/adapter/output/feign-http-services/src/test/java/br/com/helpdev/output/feign/ProtocolGeneratorClientImplTest.java new file mode 100644 index 0000000..4084d54 --- /dev/null +++ b/adapter/output/feign-http-services/src/test/java/br/com/helpdev/output/feign/ProtocolGeneratorClientImplTest.java @@ -0,0 +1,37 @@ +package br.com.helpdev.output.feign; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import br.com.helpdev.output.feign.client.RandomDataApiClient; +import br.com.helpdev.output.feign.client.dto.RandomIdNumberDto; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ProtocolGeneratorClientImplTest { + + @Mock + private RandomDataApiClient randomDataApiClient; + + @InjectMocks + private ProtocolGeneratorClientImpl protocolGeneratorClient; + + @Test + void shouldGeneratedProtocolWithSuccess() { + final var randomIdNumberDto = mock(RandomIdNumberDto.class); + final var expectedProtocol = "xpto"; + + when(randomDataApiClient.generate()).thenReturn(randomIdNumberDto); + when(randomIdNumberDto.getValidUsSsn()).thenReturn(expectedProtocol); + + final var result = protocolGeneratorClient.generateNewProtocol(); + + Assertions.assertThat(result).isEqualTo(expectedProtocol); + } + +} \ No newline at end of file diff --git a/adapter/output/feign-http-services/src/test/java/br/com/helpdev/output/feign/config/FeignContractConfigurationTest.java b/adapter/output/feign-http-services/src/test/java/br/com/helpdev/output/feign/config/FeignContractConfigurationTest.java new file mode 100644 index 0000000..74ee284 --- /dev/null +++ b/adapter/output/feign-http-services/src/test/java/br/com/helpdev/output/feign/config/FeignContractConfigurationTest.java @@ -0,0 +1,24 @@ +package br.com.helpdev.output.feign.config; + +import static org.assertj.core.api.Assertions.assertThat; + +import feign.jaxrs.JAXRSContract; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class FeignContractConfigurationTest { + @InjectMocks + private FeignContractConfiguration feignContractConfiguration; + + @Test + void shouldGeneratedNonNullJaxRsContract() { + final var contract = feignContractConfiguration.contract(); + + assertThat(contract) + .isInstanceOf(JAXRSContract.class) + .isNotNull(); + } +} \ No newline at end of file diff --git a/app/spring-app/pom.xml b/app/spring-app/pom.xml index beefe50..8fdffe7 100644 --- a/app/spring-app/pom.xml +++ b/app/spring-app/pom.xml @@ -58,6 +58,10 @@ ${project.groupId} jpa-mysql-repository + + ${project.groupId} + feign-http-services + ${project.groupId} jaxrs-controller-v1 @@ -79,7 +83,6 @@ io.micrometer micrometer-registry-prometheus - ch.qos.logback logback-core diff --git a/app/spring-app/src/main/java/br/com/helpdev/protocolgenerator/FakeProtocolGenerator.java b/app/spring-app/src/main/java/br/com/helpdev/protocolgenerator/FakeProtocolGenerator.java deleted file mode 100644 index edcf75e..0000000 --- a/app/spring-app/src/main/java/br/com/helpdev/protocolgenerator/FakeProtocolGenerator.java +++ /dev/null @@ -1,16 +0,0 @@ -package br.com.helpdev.protocolgenerator; - -import br.com.helpdev.usecase.port.ProtocolGeneratorClient; -import java.util.Random; -import org.springframework.stereotype.Component; - -@Component -public class FakeProtocolGenerator implements ProtocolGeneratorClient { - - public static final Random RANDOM = new Random(); - - @Override - public String generateNewProtocol() { - return "PROT-" + RANDOM.nextInt(Integer.MAX_VALUE); - } -} diff --git a/app/spring-app/src/main/resources/application.properties b/app/spring-app/src/main/resources/application.properties index 0822a2c..0135f96 100644 --- a/app/spring-app/src/main/resources/application.properties +++ b/app/spring-app/src/main/resources/application.properties @@ -6,3 +6,5 @@ spring.datasource.password=${MYSQL_PASSWORD:pass123} management.metrics.enable.all=true management.endpoints.web.exposure.include=* + +random-data-api.url=${RANDOM_DATA_API_URL:https://random-data-api.com} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7ece6e9..bea2245 100644 --- a/pom.xml +++ b/pom.xml @@ -44,8 +44,7 @@ core/use-case adapter/input/jaxrs-controller-v1 adapter/output/jpa-mysql-repository - - + adapter/output/feign-http-services app/spring-app acceptance-test @@ -149,6 +148,11 @@ restclient-http-services ${project.version} + + ${project.groupId} + feign-http-services + ${project.version} + org.projectlombok lombok