Skip to content

Commit

Permalink
feat: resolv spring build with feign module
Browse files Browse the repository at this point in the history
  • Loading branch information
gbzarelli committed Jan 19, 2023
1 parent f876043 commit bf8ab34
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 28 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
```
Expand Down
5 changes: 5 additions & 0 deletions acceptance-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<profileId>${project.activeProfiles[0].id}</profileId>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
<goals>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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")));
}

Expand Down
95 changes: 95 additions & 0 deletions adapter/output/feign-http-services/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>modular-architecture</artifactId>
<groupId>br.com.helpdev</groupId>
<version>0.0.4-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>feign-http-services</artifactId>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<coverage.exclude.code>**/*Dto.*</coverage.exclude.code>
<mutation.excluded.code>**.dto.*</mutation.excluded.code>
<feign-jaxrs.version>12.1</feign-jaxrs.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
<version>${feign-jaxrs.version}</version>
</dependency>

<!-- Project dependencies-->
<dependency>
<groupId>br.com.helpdev</groupId>
<artifactId>use-case</artifactId>
</dependency>

<!-- Tests dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>

</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -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();
}

}
Original file line number Diff line number Diff line change
@@ -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();
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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();
}

}
Original file line number Diff line number Diff line change
@@ -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);
}

}
Original file line number Diff line number Diff line change
@@ -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();
}
}
5 changes: 4 additions & 1 deletion app/spring-app/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
<groupId>${project.groupId}</groupId>
<artifactId>jpa-mysql-repository</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>feign-http-services</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jaxrs-controller-v1</artifactId>
Expand All @@ -79,7 +83,6 @@
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
Expand Down

This file was deleted.

2 changes: 2 additions & 0 deletions app/spring-app/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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}
8 changes: 6 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@
<module>core/use-case</module>
<module>adapter/input/jaxrs-controller-v1</module>
<module>adapter/output/jpa-mysql-repository</module>
<!--TODO: The restclient don't work in Spring; In this sample, the implementation about ProtocolGeneratorClient is in the spring-app module ( br.com.helpdev.protocolgenerator )-->
<!--<module>adapter/output/restclient-http-services</module>-->
<module>adapter/output/feign-http-services</module>
<module>app/spring-app</module>
<module>acceptance-test</module>
</modules>
Expand Down Expand Up @@ -149,6 +148,11 @@
<artifactId>restclient-http-services</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>feign-http-services</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand Down

0 comments on commit bf8ab34

Please sign in to comment.