The repository is under develop
Example of a Java application using the Ports and Adapters Architecture (Hexagonal Architecture) with Domain Driven Design (DDD) to keep the code as simple as possible.
- Hexagonal Architecture and DDD in Java
Use cases and patterns | Example of implementation |
---|---|
Adapter pattern & infrastructure Service | Logger implementation |
Repository pattern | Repository implementation |
Specification pattern | Criteria implementation |
Domain Service | CategoryFinder |
Value Object | Identifier Value Object |
Rich Domain models (Tell don't ask, Avoid anemic domain models) | Article model |
Some clean code patterns (Guard clauses, Named constructors, Self encapsulation) | Identifier |
Application Service | ArticleEraser |
Composition over inheritance | ArticleCreator |
Dependency container (unique instantiation point) | ArticleDependencyContainer |
SRP of SOLID | ArticlePostController |
OCP of SOLID | ArticleCreator |
ISP of SOLID | ArticleRepository |
DIP of SOLID | ArticleByCriteriaFinder (Interface, implementation and instantiation point) |
- Clone this repository:
> git clone https://github.com/DomingoAlvarez99/ddd-example.git
- Download and install:
- Copy the Docker environment variables config file and tune it with your desired values:
> cp .env.dist .env
- Start Docker and bring up the database container
docker-compose up -d postgres
- Configure the users and databases of the backend and Sonarqube containers.
- Common script to generate a database, an user and a schema:
CREATE ROLE ${username} LOGIN PASSWORD '${password}'; CREATE DATABASE ${db}; GRANT CREATE ON DATABASE ${db} TO ${username}; CREATE SCHEMA ${schema}; ALTER ROLE ${username} IN DATABASE ${db} SET search_path TO ${schema};
- Backend
- Create the user, the database and the schema:
- Access to the root db replacing the variables:
> docker exec -it postgres -U ${root_username} ${root_db}
- Run the common script replacing the variables.
- Access to the root db replacing the variables:
- Create the database tables:
- Find the tables:
> find . -path '*/migration/*' -type f
- Access to the database:
> docker exec -it postgres -U ${username} ${db}
- Copy and paste the definition of the tables.
- Find the tables:
- Create the user, the database and the schema:
- SonarQube
- Create the user, the database and the schema:
- Access to the root db replacing the variables:
> docker exec -it postgres -U ${root_username} ${root_db}
- Run the above script replacing the variables.
- Access to the root db replacing the variables:
- Create the user, the database and the schema:
- Bring up the other containers:
> make infrastructure
- Create the topics to publish and consume domain events:
> bash ./kafka_scripts/create-topics.sh domain_events,dead_letter-domain_events
- Add the index pattern
logstash*
in the kibana config.
- Unit: (The name must follow the following pattern
*TestCase
): - Integration (The name must follow the following pattern
*ItTestCase
) - Acceptance: Must have a .feature file linked with a .java file
Before all install the dependencies: > make deps
- Execute the unit tests:
> make unit-test
- Execute all the tests:
> make test
Backend: > make start
TO DO
The logging mechanism uses Logback and logstash-logback-encoder in order to:
- Output the log records through the standard output channel (STDOUT, your terminal).
- Append the log records in JSON format into Logstash.
After that we can:
- Send the log records to an Elasticsearch index.
- And finally visualize them centrally in Kibana.
Jacoco is a Java library that generates reports like code coverage.
SonarQube inspects and evaluates everything that affects our codebase, from minor styling details to critical design errors finding code duplications, bugs, and other issues in the code. It also defines a quality gate, which is a set of measure-based boolean conditions.
SonarQube and JaCoCo are two tools that can be used together:
- Generate the metrics:
> make test
- Send metrics to SonarQube:
mvn sonar:sonar \ -Dsonar.projectKey=${key} \ -Dsonar.host.url=${host} \ -Dsonar.login=${token}
- Do all:
mvn verify sonar:sonar \ -Dsonar.projectKey=${key} \ -Dsonar.host.url=${host} \ -Dsonar.login=${token}
Open Api code generation allows generating a REST API client from a specification (controller definition):
- Download the spec:
> wget -P /generated/swagger-api http://localhost:8080/api-docs -O api-docs.json
- Generate the client:
> mvn clean install -P code-gen
> cd /target/generated-sources-swagger-api
> mvn clean install
After that you can import the client:
<dependency>
<groupId>org.dalvarez.shop</groupId>
<artifactId>${project.artifactId}-api-client</artifactId>
<version>${project.version}</version>
</dependency>
The project uses Maven in order to package the app in a single Jar file that you can execute.
To do this > make deploy
.