Skip to content

doctore/Spring6Microservices

Repository files navigation

Spring6Microservices

Why was this project created?

Basically to know how to create a project using the microservices approach with 6th version of Spring framework. Due to there are several options we can use for different features included in a microservice architecture, the main purpose of this project is explore the most widely used creating a good base we will be able to use in a real one.

The current project is based on previous the one Spring5Microservices.

Elements included in this project

Below is shown a brief introduction to the subprojects included in this one:

Server used to register all microservices included in this project. In this case, using Netflix Eureka each client can simultaneously act as a server, to replicate its status to a connected peer. In other words, a client retrieves a list of all connected peers of a service registry and makes all further requests to any other services through a load-balancing algorithm (Ribbon by default).

Configuration server used by the included microservices to get their required initial values like database configuration, for example. Those configuration values have been added into the project:

As you can see, there is a specific folder for every microservice and the important information is encoded (the next code is part of security-custom-service-dev.yml file):

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/spring6
    username: spring6
    # Using environment variable ENCRYPT_KEY=ENCRYPT_KEY
    # Raw password: spring6
    password: "{cipher}c8e1f3a8e0f5d7246a0dcbe620b97de51b580a1ef16f80ffafd3989920287278"

To increase the security level, in the config-server microservice I have deactivated the decryption in application.yml:

spring:
  cloud:
    config:
      server:
        encrypt:
          # We will send encrypted properties
          enabled: false

Sending the information encrypted and delegating in every microservice the labour of decrypt it. That is the reason to include in their pom.xml files, the dependency:

<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-rsa</artifactId>
   <version>${spring-security-rsa.version}</version>
</dependency>

Using Spring Gateway Server WebFlux, this is the gateway implementation used by the other microservices included in this proof of concept. This module contains a filter to registry every web service invoked, helping to debug each request.

Full integration with Oauth 2.0 + Jwt functionality provided by Spring Authorization Server, used to be able to manage authentication/authorization functionalities through access and refresh tokens. With this microservice working as Oauth 2.0 Server, we will be able to configure the details of every allowed application using the database table: security.oauth2_registered_client.

On the other hand, several customizations have been included to manage the creation of access JWT token and how to append additional information too.

The technologies used are the following ones:

  • Spring Data JDBC to speed up data access, persistence, and management between Java objects and database queries.
  • Flyway as version control of database changes.
  • Lombok to reduce the code development in entities and DTOs.
  • Hazelcast as cache to reduce the invocations to the database.
  • SpringDoc-OpenApi to document the endpoints provided by the microservice using Swagger.

In this microservice, the layer's division is:

  • repository layer used to access to the database.
  • service containing the business logic.

On the other hand, there are other important folders:

  • configuration with several classes used to manage several areas such: security, documentation, database or cache.
  • model to store the entities.

Regarding Flyway, using application.yml the project has been configured to avoid invoking it when this microservice is launched or packaged:

spring:
  flyway:
    enabled: false

So, if you want to manage it manually, you can create a new maven configuration. The next picture displays how to do it using IntelliJ IDEA:

Alt text

All the managed SQL files are located in the folder changelog.

Based on JWT token, this module was created to centralize the management of authentication/authorization functionalities. Its main purpose is provided a completely multi-application platform to generate/manage their own access and refresh tokens (including additional information), choosing between the options defined in TokenType:

  • JWS
  • JWE
  • ENCRYPTED_JWS
  • ENCRYPTED_JWE

The provided algorithms to sign the JWT tokens, that is, to generate JWS or the internal one inside ENCRYPTED_JWS are located in TokenSignatureAlgorithm. On the other hand, the available algorithms selecting JWE or ENCRYPTED_JWE are defined in TokenEncryptionAlgorithm

Every application will be able to manage its own token configuration/generation adding a new row in the database table: security.application_client_details and including/developing a new value in SecurityHandler.

The technologies used are the following ones:

  • Hibernate as ORM to deal with the PostgreSQL database.
  • JPA for accessing, persisting, and managing data between Java objects and database.
  • Spring Data JDBC to speed up data access, persistence, and management between Java objects and database for some queries.
  • Flyway as version control of database changes.
  • Lombok to reduce the code development in entities and DTOs.
  • Hazelcast as cache to reduce the invocations to the database.
  • NimbusJoseJwt to work with JWS/JWE tokens.
  • SpringDoc-OpenApi to document the endpoints provided by the microservice using Swagger.
  • Webflux creating a reactive REST Api to manage the authentication/authorization requests.

In this microservice, the layer's division is:

  • application parent folder of the microservice groups whose authentication/authorization is managed by this one.
  • repository layer used to access to the database.
  • service containing the business logic.
  • controller REST Api using Spring Webflux.

On the other hand, there are other important folders:

  • configuration with several classes used to manage several areas such: security, documentation, database, cache, exception handlers, etc.
  • model to store the entities.
  • dto custom objects to contain specific data.
  • util to manage the JWS/JWE functionality.

Regarding Flyway, using application.yml the project has been configured to avoid invoking it when this microservice is launched or packaged:

spring:
  flyway:
    enabled: false

So, if you want to manage it manually, you can create a new maven configuration. The next picture displays how to do it using IntelliJ IDEA:

Alt text

All the managed SQL files are located in the folder changelog.

One order has several order lines and one order line mainly contains: concept, amount and cost. The main purpose of this microservice is the creation of a small one on which I am using the following technologies:

In this microservice, the layer's division is:

  • mapper layer used to access to the database.
  • service containing the business logic.
  • controller REST Api using Spring MVC.

On the other hand, there are other important folders:

  • configuration with several classes used to manage several areas such: security, documentation, database, exception handlers, etc.
  • model to store the entities.
  • dto custom objects to contain specific data.
  • util/converter to translate from models to DTOs and vice versa.

Regarding Flyway, using application.yml the project has been configured to avoid invoking it when this microservice is launched or packaged:

spring:
  flyway:
    enabled: false

So, if you want to manage it manually, you can create a new maven configuration. The next picture displays how to do it using IntelliJ IDEA:

Alt text

All the managed SQL files are located in the folder changelog.

Microservice used to manage invoices and related customers. The main purpose of this microservice is the creation of a small one on which I am using the following technologies:

  • Hibernate as ORM to deal with the PostgreSQL database.
  • JPA for accessing, persisting, and managing data between Java objects and database.
  • Flyway as version control of database changes.
  • Lombok to reduce the code development in entities and DTOs.
  • SpringDoc-OpenApi to document the endpoints provided by the microservice using Swagger.
  • Webflux creating a reactive REST Api to manage the authentication/authorization requests.
  • gRPC client, more information in gRPC communication.
  • Kafka consumer, more information in JMS communication.

In this microservice, the layer's division is:

  • repository layer used to access to the database.
  • service containing the business logic.
  • controller REST Api using Spring Webflux.

On the other hand, there are other important folders:

  • configuration with several classes used to manage several areas such: security, documentation, database, exception handlers, etc.
  • model to store the entities.
  • dto custom objects to contain specific data.
  • util/converter to translate from models to DTOs and vice versa.

Regarding Flyway, using application.yml the project has been configured to avoid invoking it when this microservice is launched or packaged:

spring:
  flyway:
    enabled: false

So, if you want to manage it manually, you can create a new maven configuration. The next picture displays how to do it using IntelliJ IDEA:

Alt text

All the managed SQL files are located in the folder changelog.

Maven project that includes common code used in several microservices, with different useful helper classes like:

Generic Cloneable interface improving provided one. New generic interfaces used to provide common conversion functionality using MapStruct:

And functional programming structures and useful classes like:

  • Either as an alternative to Optional for dealing with possibly missing values.
  • Function improvements.
  • Lazy to manage a lazy evaluated value.
  • PartialFunction unary function where the domain does not necessarily include all values of the type used.
  • Predicate improvements.
  • Try representing a computation that may either result in an exception, or return a successfully computed value.
  • Tuple immutable objects that contains a fixed number of elements (by now up to 9).
  • Validation to validate the given instance.

Maven project that includes common code specifically related with Spring framework, used in several microservices. It contains different useful helper classes like:

Improvements to the functionality provided by default for managing the database:

Wrapper to manage a cache, regardless of the selected implementation:

New validators:

Common DTOs to send/receive authentication, authorization data and/or handle errors invoking endpoints:

grpc-api

Common functionality used by developed gRPC server and client. This one contains:

  • order.proto with the contract which includes defining the gRPC service and the method request and response types using protocol buffers specification.

  • BasicCredential which carries the Basic Authentication that will be propagated from gRPC client to the server in the request metadata with the Authorization key.

  • GrpcErrorHandlerUtil helper class with several methods to manage errors both on gRPC client and server side.

More information about how gRPC server and client uses it in gRPC communication.

With SQL files included in the database, just to expose the initial steps to start working with these microservices.

  • changelog contains all the SQL archives required by the microservices that use Flyway to manage their changes in database.

Communication diagram

In the next picture, you will see a communication diagram of all microservices described above:

Alt text

Previous steps

Due to every microservice has to decrypt the information sent by config-server, some steps are required:

Setting up an encryption key

In this project a symmetric encryption key has been used. The symmetric encryption key is nothing more than a shared secret that's used by the encrypter to encrypt a value and the decrypter to decrypt a value. With the Spring Cloud configuration server developed in config-server, the symmetric encryption key is a string of characters you select that is passed to the service via an operating system environment variable called ENCRYPT_KEY. For those microservices, I have used:

ENCRYPT_KEY=ENCRYPT_KEY



JDK and Oracle JCE

If you are using Oracle JDK instead of OpenJDK, you need to download and install Oracle's Unlimited Strength Java Cryptography Extension (JCE). This isn't available through Maven and must be downloaded from Oracle Corporation. Once you've downloaded the zip files containing the JCE jars, you must do the following:

  • Locate your $JAVA_HOME/jre/lib/security directory

  • Back up the local_policy.jar and US_export_policy.jar files in the $JAVA_HOME/jre/lib/security directory to a different location.

  • Unzip the JCE zip file you downloaded from Oracle

  • Copy the local_policy.jar and US_export_policy.jar to your $JAVA_HOME/jre/lib/security directory.

Problems resolution

If you receive some errors related to encryption like:

IllegalStateException: Cannot decrypt: ...

Please, take a look to the previous steps in this section, maybe one of them is missing. If you still see same error messages, the best way to solve it is changing the cipher values added in the microservices configuration files included in:

Like:

spring:
  datasource:
    # Raw password: spring6
    password: "{cipher}c8e1f3a8e0f5d7246a0dcbe620b97de51b580a1ef16f80ffafd3989920287278"

And something similar in the database table security.application_client_details, in the columns: signature_secret and encryption_secret.

To do it:

Alt text

  • Overwrite current values by the provided ones.

Security services

As you read previously, there are two different microservices you can use to manage the authentication/authorization functionality: security-oauth-service and security-custom-service.

Regarding every microservice, in this section I will explain the web services provided by everyone and how to use them, starting by security-oauth-service.

security-oauth-service endpoints

Before entering in details about this security service, it is important to know that, for every request we have to include the Basic Auth Oauth 2.0 credentials, based on the application configured in the database table: security.oauth2_registered_client.

In the next pictures I will use the predefined one: Spring6Microservices

Alt text

So, the list of web services is the following one:

1. Get the authorization code using PKCE (Proof of Key Code Exchange) approach (1st request), pasting in a browser a request similar to:

http://localhost:8181/security/oauth/authorize?response_type=code&client_id=Spring6Microservices&scope=openid&redirect_uri=http://localhost:8181/security/oauth/authorized&code_challenge=jZae727K08KaOmKSgOaGzww_XVqGr_PKEgIMkjrcbJI&code_challenge_method=S256

Providing:

  • response_type=code to specify to the authorization server that the client wants to use the authorization code grant type.
  • client_id=Spring6Microservices the client's identifier added in security.oauth2_registered_client.
  • scope=openid indicates which scope the client wants to be granted with this authentication attempt.
  • redirect_uri=http://localhost:8181/security/oauth/authorized specifies the URI to which the authorization server will redirect after a successful authentication. This URI must be one of those previously configured for the current client.
  • code_challenge=jZae727K08KaOmKSgOaGzww_XVqGr_PKEgIMkjrcbJI if using the authorization code enhanced with PKCE (Proof of Key Code Exchange), the hash value of the verifier that must be provided in the second request.
  • code_challenge_method=S256 hashing method has been used to create the challenge from the verifier. In this case, S256 means SHA-256.

The browser will redirect you to the login page:

Alt text

In the previous image I used admin/admin however there is another option: user/user, included in the SQL file security.spring6microservice_user.

We configured a no existing page as redirect_uri for that reason we receive a 404 as response after the successful login however, the Spring Authorization Server returns a valid authorization code we will be able to use in the second request of PKCE (Proof of Key Code Exchange):

Alt text

2. Get the authentication information using PKCE (Proof of Key Code Exchange) approach (2nd request), using above authorization code:

Alt text

Providing:

  • client_id=Spring6Microservices the client's identifier added in security.oauth2_registered_client.
  • redirect_uri=http://localhost:8181/security/oauth/authorized specifies the URI to which the authorization server will redirect after a successful authentication. This URI must be one of those previously configured for the current client.
  • grant_type=authorization_code shows which flow the client uses to request the access token.
  • code=... the value of the authorization code the authorization server provided to the client (returned as code query parameter in the previous request).
  • code_verifier=123456 the verifier based on which the challenge that the client sent at authorization was created (code_challenge & code_challenge_method parameters).

3. Once the access token has expired, return new authentication information using refresh token:

Alt text

4. Get authorization information using access token:

Alt text

5. Revoke the token using the access one:

Alt text

So, if we try to get again its internal information, this is the new response:

Alt text

security-custom-service endpoints

Before entering in details about this security service, it is important to know that, for every request we have to include the Basic Auth credentials, based on the application configured in the database table: security.application_client_details.

In the next pictures I will use the predefined one: Spring6Microservices

Alt text

This microservice provides 2 different authentication flows:

  • Traditional: the request contains the user's credentials and returns the full authentication response.
  • PKCE (Proof of Key Code Exchange) with 2 requests:
    • The first one to send challenge data and receive the authorization code.
    • The second one to send user's credentials, authorization code and verifier and returns the full authentication response.

So, the list of web services is the following one:

1. Get the authentication information using traditional approach:

Alt text

In the previous image I used admin/admin however there is another option: user/user, included in the SQL file security.spring6microservice_user.

2. Get the authorization code using PKCE (Proof of Key Code Exchange) approach (1st request):

Alt text

3. Get the authentication information using PKCE (Proof of Key Code Exchange) approach (2nd request):

Alt text

4. Once the access token has expired, return new authentication information using refresh token:

Alt text

5. Get authorization information using access token:

Alt text

6. Logs out a user related with an application:

Alt text

So, if we try to get again its internal information, this is the new response:

Alt text

The user must complete any of the provided login flows to resubmit new requests.

Rest API documentation

The following microservices have a well-documented Rest API:

Swagger has been used in all cases, however for a better an easier integration with Spring Framework, the library used is:

To facilitate access to this documentation, we can use the gateway-server URL. On that way, using the upper selector: Select a definition, we will be able to choose between all existing microservices.

Using dev profile, the url to access them is http://localhost:5555/swagger-ui/index.html

Alt text

Alt text

Alt text

Alt text

Endpoint definitions

Configured to use the application Bruno, several collections were created to use the provided endpoints. You can them here.

gRPC communication

Besides the REST API developed in:

In this project has been added a gRPC communication channel between:

Both use the same approach to run server and client instances:



Security in gRPC

The internal communication between a microservice and its related security server, that is:

Uses Basic Authentication to include the required credentials:

In the current gRPC development I have followed the same approach:

  • In the gRPC client creating a new BasicCredential instance and adding it in the Authorization header sent to the server, using the method buildCallCredentials of the class GrpcClient.

  • In the gRPC server, the interceptor AuthenticationInterceptor manages required verifications.

Request identifier in gRPC

This project uses Spring tracing through Micrometer tracing for distributed tracing, to simulate the same behaviour two interceptors have been defined:

gRPC example request

Everytime invoice-service returns an invoice details searched by its identifier or code, will send a request to order-service using a gRPC communication channel to get its order and order lines data.

The communication diagram including also the invocation of security-custom-service is the following:

Alt text

So, as I explained you in security-custom-service endpoints, once you have obtained the required JWT access token, you can use it to invoke the web service that uses the developed gRPC channel:

Alt text

JMS communication

Besides the REST API and the gRPC communication, the project works with JMS to send data from order-service to invoice-service. Using Kafka, everytime a new order is created in order-service through its REST API, a new message is sent to invoice-service to insert a new invoice based on the order's information.

Security in JMS

The JMS communication channel uses Basic access authentication with a similar approach to gRPC. In this case,

JMS example request

As I mentioned, everytime a new order is created in order-service through its REST API, a new message is sent to invoice-service to insert a new invoice based on the order's information.

The communication diagram including also the invocation of security-oauth-service is the following:

Alt text

So, as I explained you in security-oauth-service endpoints, once you have obtained the required JWT access token, you can use it to invoke the web service that uses the developed JMS communication channel:

Alt text

If there was no error, you should see 3 new entities in database:

1. A new order: Alt text

2. A new order line: Alt text

3. A new invoice: Alt text

Native images

Native Image is a technology to compile Java code ahead-of-time to a binary – a native executable. A native executable includes only the code required at run time, that is the application classes, standard-library classes, the language runtime, and statically-linked native code from the JDK.

An executable file produced by Native Image has several important advantages, in that it:

  • Uses a fraction of the resources required by the Java Virtual Machine, so is cheaper to run.
  • Starts in milliseconds
  • Delivers peak performance immediately, with no warmup.
  • Can be packaged into a lightweight container image for fast and efficient deployment.

Install and configure GraalVM JDK

Download the required GraalVM JDK from here, in this project I use Java 21. Although there are several options to manage different JDKs such as SDKMAN, I have followed the instructions included in the webpage to install and configure GraalVM JDK in Ubuntu.

In summary, the steps are:

1. Unpack the JDK in /usr/lib/jvm/java-21-graalvm-jdk-amd64 and navigate to /usr/lib/jvm/ to work on the next points.

2. Create a symbolic link that points to the GraalVM JDK 21 directory:

ln -s java-21-graalvm-jdk-amd64 /usr/lib/jvm/java-1.21.0-graalvm-jdk-amd64

3. Prepare a descriptor file providing the information about binaries to the update-alternative utilities, creating the new file .java-1.21.0-openjdk-amd64.jinfo with:

name=java-21-graalvm-amd64
alias=java-1.21.0-graalvm-amd64
priority=2102
section=main

hl java /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/java
hl jpackage /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jpackage
hl keytool /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/keytool
hl rmiregistry /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/rmiregistry
hl jexec /usr/lib/jvm/java-21-graalvm-jdk-amd64/lib/jexec
jdkhl jar /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jar
jdkhl jarsigner /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jarsigner
jdkhl javac /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/javac
jdkhl javadoc /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/javadoc
jdkhl javap /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/javap
jdkhl jcmd /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jcmd
jdkhl jdb /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jdb
jdkhl jdeprscan /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jdeprscan
jdkhl jdeps /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jdeps
jdkhl jfr /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jfr
jdkhl jimage /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jimage
jdkhl jinfo /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jinfo
jdkhl jlink /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jlink
jdkhl jmap /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jmap
jdkhl jmod /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jmod
jdkhl jps /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jps
jdkhl jrunscript /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jrunscript
jdkhl jshell /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jshell
jdkhl jstack /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jstack
jdkhl jstat /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jstat
jdkhl jstatd /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jstatd
jdkhl jwebserver /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jwebserver
jdkhl serialver /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/serialver
jdkhl jhsdb /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jhsdb
jdk jconsole /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/jconsole
jdk native-image /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/native-image
jdk native-image-configure /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/native-image-configure
jdk native-image-inspect /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/native-image-inspect

4. Configure update-alternative to use executables from the GraalVM JDK, creating the new file java-21-graalvm-jdk-amd64_alternatives-install with:

for path in /usr/lib/jvm/java-21-graalvm-jdk-amd64/bin/*; do
    name=$(basename $path)
    update-alternatives --install /usr/bin/$name $name $path 2102 \
    --slave /usr/share/man/man1/$name.1.gz $name.1.gz /usr/lib/jvm/java-21-graalvm-jdk-amd64/man/man1/$name.1
done

update-alternatives --install /usr/bin/jexec jexec /usr/lib/jvm/java-21-graalvm-jdk-amd64/lib/jexec 2102

5. Invoke the new file:

./java-21-graalvm-jdk-amd64_alternatives-install

6. Switch to the brand new GraalVM JDK using the update-java-alternatives:

update-java-alternatives -s java-1.21.0-graalvm-jdk-amd64

If everything went well, then we should watch something like:

java --version
java 21.0.6 2025-01-21 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 21.0.6+8.1 (build 21.0.6+8-LTS-jvmci-23.1-b55)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 21.0.6+8.1 (build 21.0.6+8-LTS-jvmci-23.1-b55, mixed mode, sharing)

security-custom-service native

Once we have configured the GraalVM JDK, the required changes/considerations in security-custom-service are:

1. Create the new application-native.yml file to include the specific configuration for native images.

2. Add the configuration files based on the project's functionality.

To know how to generate all the configuration archives in this microservice, package the project with maven using native profile and invoke:

java -Dspring.aot.enabled=true -agentlib:native-image-agent=config-output-dir=./native-config -jar target/security-custom-service-1.0.0.jar

You can use all the new files located in native-config folder, to include in the project only the required ones.

3. Update pom.xml to add, at least, the native profile. Not all the dependencies are available to work with native images, you can check the list here.

4. Create a new maven configuration to compile the project and generate the native image as executable file:

Alt text

5. Invoke the generated executable archive:

./target/security-custom-service --spring.profiles.active=native

If everything went well, then the application will run smoothly and the endpoints will respond to the request normally. Comparing both options: local and native you will be able to notice an important improvement in the performance:

  • local: more than 6 seconds.

Alt text

  • native: less than 3 seconds.

Alt text

Docker

In addition to launching all the microservices included in this project as normal Java applications locally, all of them have been dockerized. Every one includes a Dockerfile inside with the required configuration and instructions to generate both Docker image and container. On the other hand, new application files with docker profile have been added to Spring6Microservices_ConfigServerData.

There are 2 main types of Dockerfile based on the option to invoke maven install inside the Docker container, this is because some projects contain internal dependencies that have not been uploaded to a public repository like:

Projects with maven install in their DockerFile and do not need to create the jar file previously:

Projects that must create the jar file before building the Docker image:

Once you have created all the Docker images on your local, you should see something similar to:

Alt text

Docker compose

To manage the Docker containers in an easier way, a Docker compose file: compose.yml has been added. It includes the required commands to up and down the project's containers.

The file kafka-compose.yml adds only the required containers to work with the microservices in local, specially:

allowing you to debug and work locally without problems. More information in the section JMS communication.

PostgreSQL configuration in localhost

In this project, the PostgreSQL database has not been dockerized, feel free to do it if you prefer such option instead of using the local one. In this section, I will describe the required steps to allow the connections from Docker to the PostgreSQL database installed in a local computer, in my case, PostgreSQL 16 over Ubuntu (other database versions and/or OS should need similar ones).

  1. Go to the PostgreSQL's folder with configuration files (in my case /etc/postgresql/16/main)

  2. Edit postgresql.conf to listen connections outside localhost:
listen_addresses = '*'
  1. Edit pg_hba.conf to allow connections from Docker containers
# # IPv4 local connections:
host    all             all             172.18.0.0/16           md5   # Docker
host    all             all             172.21.0.0/16           md5   # Docker compose
  1. Restart PostgreSQL service (in my case service postgresql restart).

About

Proof of concept to create microservices using Spring 6 and related technologies

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors