Event-Driven Architecture Template
with Java, Apache Kafka, and Spring Boot
This article describes the implementation of a Java-based microservice template that follows the principles of Event-Driven Architecture (EDA). Built with Spring Boot and powered by Apache Kafka, the template provides a clean foundation for building scalable and resilient distributed applications, which communicate through events rather than direct service-to-service calls. With a modular structure and clear separation between domain logic, messaging infrastructure, and configuration, it serves as a reusable starting point for modern microservice ecosystems.
Key advantages:
- Loose Coupling: Services communicate through events, reducing direct dependencies and enabling independent evolution.
- Asynchronous Communication: Non-blocking interactions improve responsiveness and overall system resilience.
- Scalability: Producers and consumers can scale independently based on workload and traffic patterns.
- Resilience: Event-driven flows help isolate failures and prevent cascading outages across services.
- Extensibility: New consumers can subscribe to existing events without modifying the producing service.
- Event Replay and Traceability: Kafka's log-based model enables event replay and improves observability of system behavior.
- Developer Productivity: A ready-to-use structure accelerates the development of new event-driven microservices while maintaining consistency.
The goal is to keep the template practical, clean, and easy to adapt, providing a solid foundation for building event-driven microservices.
Table of Contents
Source Code
Source code is available on GitHub:
https://github.com/kamilmazurek/event-driven-architecture-template
You can clone the repository using Git or download it as a ZIP file.
git clone https://github.com/kamilmazurek/event-driven-architecture-templateTo quickly build and start the application, run (see Quickstart for details):
mvnw clean package
docker compose up --buildFor additional options, please see the Build and deployment section.
Customize the source code as needed, rebuild the project, and run the application 🚀.
The repository also contains configuration files and test classes to help you get started quickly and see how it works.
Quickstart
Following steps provide a quick way to get started with the Event-Driven Architecture Template:
1. Ensure a JDK is available to build and run the code. Temurin, based on OpenJDK and available from adoptium.net, can be used for this purpose.
2. The project uses Docker to run Kafka. It is possible to run the template without it, but using Docker is recommended to get started quickly. The following steps assume Docker is installed, so please make sure you have it before proceeding.
3. Get the source code either by cloning the repository with Git or by downloading the ZIP file from Event-Driven Architecture Template repository.
git clone https://github.com/kamilmazurek/event-driven-architecture-template4. Build the application and start it using Docker Compose:
mvnw clean package
docker compose up --buildRebuilds and deployments may accumulate unused Docker images and volumes, consuming additional disk space over time. Therefore, for subsequent rebuilds, you may want to redeploy the application with cleanup of Compose-managed resources:
mvnw clean package
docker compose down --rmi local --volumes && docker compose up --build5. Verify that the application is running by sending a POST request to the Producer service:
curl -i -X POST http://localhost:8080/items -H "Content-Type: application/json" -d '{"name":"Item A"}'6. Check the Consumer by opening:
http://localhost:8081/itemsThe response should contain an item like:
[
{
"id": "bc0ac641-b5f0-4e99-b067-926cead738f9",
"name": "Item A"
}
]7. Customize the source code as needed, rebuild the project, and run the application 🚀.
Motivation
Starting new event-driven microservices often involves repetitive setup. I wanted the ability to start quickly and considered creating a Maven Archetype to automate this, but it felt too costly compared to the benefits. I also tried AI/LLM-based solutions for generating project scaffolding, but they lacked determinism and sometimes produced unreliable results. Instead, to reduce the overhead of repeatedly creating project skeletons, I decided to create this template.
Architecture Overview
Event-Driven Architecture (EDA) is a software design pattern in which components communicate asynchronously by producing and consuming events, rather than invoking each other directly. This approach allows services to operate independently, promotes loose coupling, improves scalability, and makes it easier to extend or modify individual components without impacting the rest of the system. EDA is particularly well-suited for distributed microservices, where responsiveness, resilience, and flexibility are critical.
In this implementation, the architecture is centered around Kafka as the communication backbone. The image below illustrates the concept used in this project:

Event-Driven Architecture Template concept diagram
The main parts of this template include:
- Producer
- Publishes domain events to Kafka topic when business actions occur.
- Converts internal domain changes into events that other services can consume.
- Consumer
- Subscribes to the Kafka topic and processes events asynchronously.
- Encapsulates business logic triggered by incoming events while remaining decoupled from the producer.
- Model
- Defines the event payloads and domain objects shared between producer and consumer.
- Ensures consistent data structure and serialization across services.
- Broker (Apache Kafka)
- Serves as the messaging backbone and distributed event log, storing events as an ordered sequence.
- Provides partitioned storage with configurable durability (e.g., replication, acknowledgments).
- Enables event replay, retention policies, and scalable consumption by multiple consumers.
- Supports decoupled communication between producers and consumers.
- Supporting Components
- Spring Boot Actuator for health checks.
This template focuses on simplicity and clarity, providing a solid starting point for building event-driven microservices. While it currently supports a single producer and consumer, the structure is designed to be easily extended with additional services, topics, or event flows as your system grows.
By following Event-Driven Architecture principles, the design ensures asynchronous communication, loose coupling, and clear separation of concerns, helping developers create scalable, resilient, and maintainable microservices.
Apache Kafka as the Event Backbone
Apache Kafka is a distributed event-streaming platform commonly used as a message broker in event-driven architectures. Instead of directly coupling services through synchronous calls, Kafka allows services to communicate asynchronously by publishing and consuming events. This decoupling improves scalability, reliability, and flexibility in modern microservice systems.
At its core, Kafka works as a distributed commit log where records are written sequentially and stored for a configurable period of time. Each record represents a message containing a key, value, timestamp, and metadata describing its position in the log.
In event-driven systems, these records typically carry event data describing something that happened in the domain. For example, a record might represent an ItemCreated event produced when a new item is created in the system. Services acting as producers publish events to Kafka topics, while consumers subscribe to those topics and process them independently.
As a result, the key components include:
- Producer - a service that publishes events to a Kafka topic
- Consumer - a service that subscribes to a topic and processes incoming events
- Broker - a Kafka server that receives events from producers, stores them, and serves them to consumers
- Topic - a categorized stream of events
- Partition - a subdivision of a topic, important for parallel processing and scalability
Apache Kafka is designed for high throughput and distributed scalability. Additionally, events written to Kafka are persisted to disk and may be replicated across brokers, to improve durability and fault tolerance. These capabilities make Kafka particularly well suited for event-driven architectures:
- Durable event storage - records are persisted and can be replayed by consumers
- Horizontal scalability - topics can be partitioned across multiple brokers
- High throughput - designed to handle millions of records efficiently
- Loose coupling - producers and consumers can evolve independently
- Event replay - consumers can reprocess events by resetting offsets
With these features, Kafka can be used not only as a broker, but also as an event backbone for microservice ecosystems.
When to Use Event-Driven Architecture
Event-Driven Architecture (EDA) organizes a system around the production, detection, and reaction to events. Instead of tightly coupling components through direct calls, different parts of the system communicate by emitting and consuming events. This approach promotes loose coupling, scalability, and responsiveness, making it easier to evolve and extend your application over time.
This architecture is particularly effective for systems that must handle asynchronous workflows or high volumes of distributed interactions. It works well in environments where multiple services or modules need to react to changes independently, such as processing orders, updating analytics, sending notifications, or integrating with external systems. It may also be a strong fit for systems that require high scalability and resilience. Additionally, by decoupling producers from consumers, teams can develop, deploy, and scale components independently, which improves flexibility and supports continuous delivery.
However, an Event-Driven Architecture introduces additional complexity. Managing event consistency, tracing flows across services, handling failures, and ensuring reliable delivery requires careful design and tooling. For smaller applications, systems with simple request-response flows, or projects with tight deadlines, this added complexity may outweigh the benefits. In such cases, a Hexagonal Architecture can provide a more straightforward and maintainable approach, while a Layered Architecture may be suitable if an even simpler structure is desired.
Ultimately, choose Event-Driven Architecture when your system must be highly scalable, reactive, and loosely coupled. When implemented thoughtfully, it enables resilient, extensible systems that can evolve naturally as new consumers, integrations, and business capabilities emerge.
Technology Stack
Event-Driven Architecture Template is built using Java and Spring Boot, providing a solid foundation for developing modular and production-ready microservices. The application follows an event-driven approach where services communicate asynchronously through a message broker rather than direct calls. This ensures loose coupling and independent scalability of components.
Apache Kafka is used as the central event streaming platform, enabling reliable, high throughput communication between producers and consumers. Kafka allows services to publish events and react to them independently, which aligns naturally with the principles of Event-Driven Architecture. Spring for Apache Kafka simplifies integration, configuration, and message handling within the Spring ecosystem.
Testing is a first-class concern in this stack. Unit tests focus on individual components such as event producers, consumers, and domain services, while integration tests verify message flow and interaction with Kafka. Maven Surefire and Failsafe plugins are preconfigured to ensure smooth execution of both unit and integration tests during the build process.
Here is an overview of the technology stack:
- Language & Framework
- Java 21: Modern Java version used to implement the application.
- Spring Boot: Framework for building standalone, production-ready Spring applications.
- Spring for Apache Kafka: Simplifies Kafka integration and event listener configuration.
- Messaging
- Apache Kafka: Distributed event streaming platform enabling asynchronous communication between services.
- Testing
- JUnit: Framework for writing unit tests in Java.
- REST Assured: Library for testing REST endpoints.
- Mockito: Mocking framework for isolating components during unit tests.
- Testcontainers: Runs real infrastructure dependencies (e.g. Apache Kafka) in Docker containers for reliable integration testing.
- Allure Report: Generates detailed and readable test reports.
- Build & Deployment
- Apache Maven: Manages dependencies, builds, and test execution.
- Docker: Packages applications into containers for consistent deployment.
This stack was selected to support asynchronous communication, scalability, and resilience. It balances simplicity for local development with the robustness required for real-world event driven systems, providing a strong foundation for building reactive and extensible microservices.
How It Works
This implementation follows Event-Driven Architecture (EDA) principles, allowing services to communicate asynchronously through Apache Kafka. It uses the Spring Framework, where components are managed as Spring Beans, supporting clean dependency management and loose coupling.
The system is built around three main components: the Producer, Apache Kafka, and the Consumer, each with a clearly defined responsibility. This separation enables independent scaling, loose coupling, and reliable event processing.
This template is designed to be easy to adapt. Rather than modeling a complex business domain, it provides a straightforward example that demonstrates how event-driven communication works. The flow is presented below.
Producer
Incoming requests are handled by the controller, which serves as the entry point for API calls. The ItemCreateController is a Spring-managed bean that listens for HTTP POST requests at the /items endpoint. It delegates creation logic to the ItemService, which encapsulates business logic and publishes events to Kafka.
@RestController
@RequestMapping("/items")
@RequiredArgsConstructor
public class ItemCreateController {
private final ItemService itemService;
@PostMapping
public ResponseEntity<ItemDTO> createItem(@Valid @RequestBody CreateItemDTO createItemDTO) {
var createdItem = itemService.createItem(createItemDTO.name());
return ResponseEntity.status(CREATED).body(ItemDTO.fromItem(createdItem));
}
}The ItemService creates a new Item domain object and produces an ItemCreatedEvent, representing a domain event. Event publishing is delegated to the ItemEventPublisher.
@Slf4j
@Service
@RequiredArgsConstructor
public class ItemService {
private final ItemEventPublisher publisher;
public Item createItem(String name) {
var item = Item.create(name);
log.info("Created item with id {} and name {}", item.getId(), item.getName());
var event = ItemCreatedEvent.builder().eventId(randomUUID().toString()).item(item).build();
publisher.publish(event);
return item;
}
}This separation keeps the service focused on business rules, while the publisher handles Kafka integration. It also allows new consumers to react to the same event without modifying existing code.
The ItemEventPublisher sends events using a KafkaTemplate. Each event is keyed by the item ID, ensuring ordering guarantees for related messages.
@Slf4j
@Component
@RequiredArgsConstructor
public class ItemEventPublisher {
private final KafkaTemplate<String, ItemCreatedEvent> kafkaTemplate;
public void publish(ItemCreatedEvent event) {
var item = event.getItem();
kafkaTemplate.send(ITEM_CREATED, item.getId(), event);
log.info("Published ItemCreatedEvent {} for item id {} and name {}", event.getEventId(), item.getId(), item.getName());
}
}Once published, the event becomes available in Kafka for any subscribed consumers. This enables multiple independent reactions such as updating projections or triggering workflows.
Consumer
The ItemEventListener subscribes to the ITEM_CREATED topic and processes events using @KafkaListener. It runs within a consumer group, ensuring each event is processed only once per group while allowing horizontal scaling.
@Slf4j
@Component
@RequiredArgsConstructor
public class ItemEventListener {
private final ItemCreatedEventHandler handler;
@KafkaListener(topics = ITEM_CREATED, groupId = "template-consumer")
public void onItemCreated(ItemCreatedEvent event) {
log.info("Received event {}", event.getEventId());
handler.handle(event);
}
}The listener delegates processing to the ItemCreatedEventHandler, which contains the domain-specific logic. In this case, it stores the item in the ItemStore.
@Slf4j
@Service
@RequiredArgsConstructor
public class ItemCreatedEventHandler {
private final ItemStore itemStore;
public void handle(ItemCreatedEvent event) {
var item = event.getItem();
itemStore.add(item);
log.info("Item added to item store: id={}, name={}", item.getId(), item.getName());
}
}Responsibilities are clearly separated:
- The listener handles Kafka event consumption.
- The handler contains business logic.
- The store manages data persistence.
This design supports scalable and loosely coupled workflows. New handlers can be introduced without modifying producers or existing consumers.
The system also provides a read model via the ItemReadController, which exposes the current state of stored items.
@RestController
@RequestMapping("/items")
@RequiredArgsConstructor
public class ItemReadController {
private final ItemStore itemStore;
@GetMapping
public ResponseEntity<List<ItemDTO>> getItems() {
return ResponseEntity.ok(itemStore.getAll().stream().map(ItemDTO::fromItem).toList());
}
}This follows a common pattern in event-driven systems: writes are event-based, while reads are served from asynchronously updated projections. This improves performance and scalability.
End-to-End Flow
Client → Producer → Kafka → Consumer → StoreThe flow starts with a POST request:
curl -i -X POST http://localhost:8080/items -H "Content-Type: application/json" -d '{"name":"Item A"}'The processing steps are:
- Client sends an
HTTP POSTrequest. - Controller receives the request.
- Service creates the item and publishes an event.
- Kafka stores the event in a topic.
- Consumer receives the event.
- Listener delegates processing to the handler.
- Handler updates the store.
To verify the result, the client queries the consumer:
http://localhost:8081/items- Client sends an
HTTP GETrequest. - Controller reads data from the store.
- Response is returned to the client.
This demonstrates a full event-driven workflow using Spring Boot and Kafka, with clear separation of responsibilities and asynchronous communication.
Build and Deployment
The project is built with Apache Maven. A standard build compiles the project, runs both unit and integration tests, and installs the generated JAR files into the local Maven repository:
mvnw clean installIntegration tests executed during the build connect to an instance of Apache Kafka, which is automatically started in Docker using Testcontainers.
If Docker is not available, or you prefer not to start the Kafka container during the build, it is possible to skip integration tests (however, this is not recommended):
mvnw clean install -DskipITsRunning the Application Locally
To run the application locally, an Apache Kafka instance is required. You can install and run Kafka manually or connect to an existing remote instance. For development and testing purposes, running Kafka in Docker is often the most convenient approach.
The project includes a Docker Compose configuration that starts Kafka together with the Producer and Consumer services.
The following command can be used to build and start all services:
mvnw clean package
docker compose up --buildThese commands will:
- Build the application
- Build Docker images for the Producer and Consumer
- Start Kafka and both services
Rebuilds and deployments may accumulate unused Docker images and volumes, consuming additional disk space over time. Therefore, for subsequent rebuilds, you may want to redeploy the application with cleanup of Compose-managed resources:
mvnw clean package
docker compose down --rmi local --volumes && docker compose up --buildBy default, the Producer runs on port 8080, and the Consumer runs on port 8081.
You can quickly verify that it works by sending a simple POST request to the Producer:
curl -i -X POST http://localhost:8080/items -H "Content-Type: application/json" -d '{"name":"Item A"}'Then check what items are available in the Consumer store:
http://localhost:8081/itemsBy sending a GET request to this endpoint, or opening it in a browser, you should see the created items, for example:
[
{
"id": "bc0ac641-b5f0-4e99-b067-926cead738f9",
"name": "Item A"
}
]Running Services Step by Step
If you need more control, the following commands allow you to run services step by step. You can start Kafka in Docker and run the Producer and Consumer directly using Spring Boot.
First, run Apache Kafka in Docker:
docker run -p 9092:9092 -p 9093:9093 --name kafka apache/kafka:3.9.1Then start the Producer and Consumer (in separate terminals):
cd producer
mvnw spring-boot:runcd consumer
mvnw spring-boot:runRunning Packaged Applications
Alternatively, you can build the project and run the generated JAR files using Spring Boot. Build the project:
mvnw clean packageThen run Producer and Consumer (in separate terminals):
java -jar producer/target/producer-1.0.0-SNAPSHOT.jarjava -jar consumer/target/consumer-1.0.0-SNAPSHOT.jarBuilding and Running Docker Images Manually
If you prefer not to use Docker Compose, you can build and run each service step by step.
First, package the applications and build the Docker images:
mvnw clean package
docker build -t template/event-driven-template-producer -f producer/Dockerfile ./producer
docker build -t template/event-driven-template-consumer -f consumer/Dockerfile ./consumerThis compiles the applications using Maven and creates Docker images for both the Producer and Consumer services.
To allow the containers to communicate with each other, create a dedicated Docker network:
docker network create event-driven-architecture-template-networkRun the Kafka broker container:
docker run --name kafka \
--network event-driven-architecture-template-network \
-p 9092:9092 \
-e KAFKA_NODE_ID=1 \
-e KAFKA_PROCESS_ROLES=broker,controller \
-e KAFKA_CONTROLLER_QUORUM_VOTERS=1@kafka:9093 \
-e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092 \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \
-e KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=1 \
apache/kafka:3.9.1Start the Producer:
docker run --name event-driven-architecture-template-producer \
--network event-driven-architecture-template-network \
-p 8080:8080 \
-e SPRING_KAFKA_BOOTSTRAP_SERVERS=kafka:9092 \
template/event-driven-architecture-template-producerStart the Consumer:
docker run --name event-driven-architecture-template-consumer \
--network event-driven-architecture-template-network \
-p 8081:8081 \
-e SPRING_KAFKA_BOOTSTRAP_SERVERS=kafka:9092 \
template/event-driven-architecture-template-consumerWith these build and deployment options, you can easily build, test, and run the application locally or in Docker containers. The setup is flexible and can be adapted as your project grows or requirements change.
Events, Topics, and Endpoints
Events, topics, and endpoints are intentionally kept simple, as this project is designed to serve as a template. For this reason, I chose a straightforward item-creation workflow that is easy to understand and clearly illustrates event-driven communication in practice. Consequently, these elements provide a clear and accessible way to see how the system works.
An event represents an occurrence in the system, a meaningful action that has taken place, giving other components the opportunity to react to it asynchronously. In this template, the event is ItemCreatedEvent:
@Data
@Builder
@Jacksonized
public class ItemCreatedEvent {
private final String eventId;
private final Item item;
}This event is created whenever a new item is added. The Producer exposes the following endpoint to create items:
http://localhost:8080/itemsYou can create an item by sending a simple POST request, for example:
curl -i -X POST http://localhost:8080/items -H "Content-Type: application/json" -d '{"name":"Item A"}'The Consumer reacts to the ItemCreatedEvent and stores items in memory. It also provides an endpoint to view the stored items:
http://localhost:8081/itemsBy sending a GET request to this endpoint or opening it in a browser, you can see the created items, for example:
[
{
"id": "bc0ac641-b5f0-4e99-b067-926cead738f9",
"name": "Item A"
}
]Events are sent to Kafka topics. In this example, ItemCreatedEvents are sent to the item-created topic.
If you are running Kafka in Docker, as described in the Build and Deployment section, you can list all topics using the following command:
docker exec kafka /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --listYou can also check the events that have been sent to a topic like this:
docker exec kafka /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic item-created --from-beginningYou should see logs similar to the following, which are continuously updated as new events are received:
{"eventId":"65c9e8c4-b373-4f5a-9af3-bb13d2623fd4","item":{"id":"bc0ac641-b5f0-4e99-b067-926cead738f9","name":"Item A"}}There are also /actuator endpoints that can be useful for monitoring. These are described in the next section: Production-Ready Features.
Production-Ready Features
The template includes a basic setup for Spring Boot Actuator, a library that adds ready-to-use production features to Spring Boot applications. It offers monitoring and health checks that can be customized through configuration. These features make it easy to track the status of the Producer, Consumer, and Kafka connections.
Two key Actuator endpoints are configured in this template:
/actuator, which lists all exposed actuator endpoints:http://localhost:8080/actuatorfor Producerhttp://localhost:8081/actuatorfor Consumer
/actuator/health, which shows the current health status of the application:http://localhost:8080/actuator/healthfor Producerhttp://localhost:8081/actuator/healthfor Consumer
The list of available Actuator endpoints is accessible at the /actuator endpoint. It can be customized by modifying the management.endpoints.web.exposure.include property in application.yaml. For example, to enable the beans endpoint, add it to the configuration:
management:
endpoints:
web:
exposure:
include: health, beansIt is also possible to expose metrics:
management:
endpoints:
web:
exposure:
include: health, beans, metricsThe /actuator/metrics endpoint provides a list of available metrics. For example, the Producer spring.kafka.template metric can be accessed at the following endpoint, provided it has been enabled:
http://localhost:8080/actuator/metrics/spring.kafka.templateThe health status of the application can be checked by sending a request to the /actuator/health endpoint. The response will show the current state of the application, for example:
http://localhost:8080/actuator/health{
"status": "UP"
}To protect sensitive details, the application provides only basic health status by default. If more detailed information is needed, such as disk space usage, it can be enabled by updating the application.yaml file:
management:
endpoint:
health:
show-details: "always"After making this change, the /actuator/health endpoint provides more detailed information. It also enables additional endpoints, such as /actuator/health/kafka, which show the status of Kafka, e.g.:
http://localhost:8080/actuator/health/kafka{
"status": "UP",
"details": {
"clusterId": "5L6g3nShT-eMCtK--X86sw"
}
}Additional details are available in the Spring Boot Actuator documentation:https://docs.spring.io/spring-boot/reference/actuator/endpoints.html
These features make it easier to monitor and manage the application, giving you clear insights into its health and performance across all layers. Proper use of Actuator endpoints can help keep the application reliable and make troubleshooting simpler in both development and production.
Important: In production environments, actuator endpoints should be secured to prevent unauthorized access. It is recommended to restrict access using authentication and authorization mechanisms. Be cautious when enabling detailed health information or sensitive endpoints.
Tests
The project is covered by both unit and integration tests, with the Maven Surefire Plugin and Maven Failsafe Plugin preconfigured to execute them.
Tests are written using JUnit, Mockito, and REST Assured, covering the API layer, business logic, and communication with Apache Kafka.
There are two types of tests implemented in this template:
- Unit tests (
*Test.java) are executed by Surefire and focus on individual components such as services, handlers, and listeners. - Integration tests (
*IntegrationTest.java) are executed by Failsafe and verify how application components work together.
Integration tests use an Apache Kafka instance running in Docker via Testcontainers. Therefore, Docker is required to run these tests.
Both types of tests can be run using:
mvnw clean verifyUnit tests are executed by the Maven Surefire Plugin, for example:
mvnw clean testIntegration tests are executed by the Maven Failsafe Plugin, for example:
mvnw clean integration-testPlease note that this also runs unit tests.
Both types of tests are also executed as part of a standard build:
mvnw clean installAdditionally, the project comes with Allure Report configured, which generates test reports accessible in a browser. To generate and view the reports, the following commands can be used:
mvnw clean verify
mvnw allure:serveThe test report is then opened in the browser. An excerpt from the report is shown below:

Sample Allure Report. For more information about Allure Report, please visit https://allurereport.org
These tests include unit tests, which focus on domain logic and individual components, and integration tests, which verify that both the producer and the consumer interact correctly with external systems. This approach works well with the decoupled, message-driven design of Event-Driven Architecture.
Repositories
The source code for this project is available on GitHub and mirrored on GitLab:
Disclaimer
THIS ARTICLE AND ANY SOFTWARE INCLUDED WITH THIS ARTICLE AND CREATED BY THE ARTICLE'S AUTHOR ARE PROVIDED FOR EDUCATIONAL PURPOSES ONLY.
THE ARTICLE AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ARTICLE, THE SOFTWARE, OR THE USE OR OTHER DEALINGS IN THE ARTICLE OR SOFTWARE.
THIRD-PARTY LIBRARIES REFERENCED OR INCLUDED IN THIS SOFTWARE ARE SUBJECT TO THEIR OWN LICENSES. THIRD-PARTY DOCUMENTATION OR EXTERNAL RESOURCES REFERENCED IN THIS ARTICLE ARE SUBJECT TO THEIR OWN LICENSES AND TERMS.

