Clean Architecture: Implementation Using Quarkus + Gradle Multi-Project. Part 2

Luis Illera • August 15, 2023

As we venture deeper into our Gradle Multi-Project Clean Architecture journey with Quarkus and Java 17, we find ourselves at a pivotal juncture where our architectural components meet practical implementation. In the last few segments of our blog series, we've been focusing on fine-tuning the entrypoint layer, which serves as the gateway for external interactions with our application.

In this entry, we'll explore the configuration of three distinct modules within the entrypoint layer: entrypoint-api , entrypoint-graphql , and entrypoint-dto . Each module plays a unique role in shaping how external clients communicate with our microservices while adhering to the principles of Clean Architecture.

Let's dive into the specifics of each module and understand how they contribute to a well-structured, modular, and maintainable software system.

Configuring Module: RESTful API Endpoints


This module forms the gateway for external clients to interact with our microservices. By configuring it correctly, we ensure that our application's external interface adheres to the principles of Clean Architecture.

The entrypoint/api module serves as the conduit between external clients and the core business logic of our application. It defines REST endpoints that provide entry points to our microservices, allowing external systems to communicate with our application. Additionally, the entrypoint/api module depends on the entrypoint/dto module, which houses shared Data Transfer Objects (DTOs) to standardize API operations independently of protocols. This separation maintains a clean and organized architecture. Let's delve into the step of effectively configuring this module.

Dependency Setup

The heart of our Clean Architecture approach lies in proper module dependencies. The entrypoint/api module depends on three essential modules: domain/model , business/usecase , and entrypoint/dto . To establish these dependencies and ensure a clear boundary between layers, we use the api configuration in Gradle.

Here's how you can define these dependencies in the build.gradle file of the entrypoint/api module:

apply plugin: 'java-library'
dependencies {
    api project(':domain-model')
    api project(':business-usecase')
    api project(':entrypoint-dto')
    implementation 'io.quarkus:quarkus-resteasy-reactive-jackson'
    // Additional dependencies related to the entrypoint/api module
}

To implement RESTful endpoints in the entrypoint/api module, we harness the power of Quarkus. By applying the java-library plugin and utilizing Quarkus' built-in support for RESTful web services through the io.quarkus:quarkus-resteasy-reactive-jackson dependency, we create a robust and reactive API layer.

Configuring the entrypoint/api module is a pivotal step in our Clean Architecture project. By meticulously setting up dependencies on the domain/model and business/usecase modules, and leveraging Quarkus' capabilities for RESTful endpoints, we construct a solid external interface for our microservices.

Adding the META-INF Folder

Quarkus relies on the presence of the META-INF folder and its beans.xml file to understand how to perform dependency injection. This file serves as a configuration point that tells Quarkus which classes are eligible for injection and how to manage their lifecycles. Fortunately, adding this file is straightforward.

  1. Navigate to the src/main/resources directory within the entrypoint/api module.
  2. Create a folder named META-INF if it doesn't already exist.
  3. Inside the META-INF folder, create an empty file named beans.xml .
src/main/resources
└── META-INF
    └── beans.xml

By adding this simple beans.xml file, you're telling Quarkus to perform dependency injection correctly within the entrypoint/api module.

To deep dive into RESTful Endpoints creation go to Writing rest services with RestEasy Reactive Quarkus guide.

Configuring Module: GraphQL Queries


This module empowers us to define GraphQL schemas and resolvers, offering an additional layer of interaction with our application. By configuring this module effectively, we ensure that our GraphQL API aligns seamlessly with our clean and modular architecture.

The entrypoint/graphql module acts as the gateway for external clients to interact with our microservices using the GraphQL query language. GraphQL empowers clients to request precisely the data they need, reducing over-fetching and under-fetching of data. In addition to the GraphQL functionality, the entrypoint/graphql module depends on three other modules: domain/model , entrypoint/dto , and business/usecase . This intricate web of dependencies facilitates a holistic approach to handling external interactions.

Dependency Setup

The entrypoint/graphql module depends on four critical modules: domain/model , entrypoint/dto , business/usecase , and the Quarkus quarkus-smallrye-graphql extension. To create a clear separation between the layers and ensure that the dependencies are appropriately managed, we utilize the api configuration in Gradle.

Here's how you can define these dependencies in the build.gradle file of the entrypoint/graphql module:

apply plugin: 'java-library'
dependencies {
    api project(':domain-model')
    api project(':entrypoint-dto')
    api project(':business-usecase')
    implementation 'io.quarkus:quarkus-smallrye-graphql'
    // Additional dependencies related to the entrypoint/graphql module
}

To implement GraphQL schemas and resolvers in the entrypoint/graphql module, we embrace the io.quarkus:quarkus-smallrye-graphql dependency. Quarkus provides native support for GraphQL, enabling us to define schema structures and business logic resolvers in a clean and efficient manner.

The entrypoint/graphql module configuration plays a pivotal role in our Clean Architecture project. We construct a powerful GraphQL interface that resonates with modern development practices.

Adding the META-INF Folder

As we did before, we'll include the META-INF folder and its accompanying beans.xml file. Quarkus relies on this configuration to understand how to perform dependency injection accurately. This simple file serves as a directive, informing Quarkus about which classes are eligible for injection and how their lifecycles should be managed.

To deep dive into GraphQL Queries creation go to SmallRye GraphQL Quarkus guide.

Configuring Module: Entrypoint DTO
Enhancing Data Transformation


This module is pivotal in facilitating seamless transformations between our core business domain models and Data Transfer Objects (DTOs). By configuring it effectively, we ensure clean and consistent data interchange while adhering to our modular architecture.

The entrypoint/dto module serves as a bridge between our core business domain models and external interfaces, providing a standardized way of representing data across layers. It's here that we implement the transformations from our core domain models to DTOs, enabling clear and controlled communication with external clients.

Dependency Setup

The entrypoint/dto module is intimately tied to the domain/core module, which houses our core business domain models. This means that the entrypoint/dto module depends solely on the domain/core module for its functionality. This minimalistic dependency structure ensures that transformations are isolated, keeping our architecture modular and free of unnecessary complexities.

Here's how you can define the dependency in the build.gradle file of the entrypoint/ dto   module:

dependencies {
    implementation project(':domain-model')
    implementation 'io.quarkus:quarkus-jackson'
}

In the entrypoint/dto module, we implement the necessary transformation logic between our core domain models and DTOs. Through the integration of the io.quarkus:quarkus-jackson dependency, we elevate our capacity to manage data serialization and deserialization effortlessly. This ensures that data passed between layers remains consistent and conforms to the expectations of external clients. By focusing on this transformation layer, we maintain a clear separation of concerns and prevent data leakage between layers.

The  entrypoint/dto   module plays a crucial role in our Clean Architecture project, enabling consistent and controlled data transformations between core domain models and external interfaces. By limiting its dependency solely to the  domain/core   module, we maintain the principles of modularity and encapsulation.


You can find the code of this section in the branch: steps/3-configuring-entrypoint-modules

By Luis Illera August 16, 2023
Welcome back to our journey through Gradle Multi-Project Clean Architecture with Quarkus and Java 17.
By Luis Illera August 15, 2023
Welcome to the fourth installment of our journey into Clean Architecture with Quarkus and Java 17.
By Luis Illera August 15, 2023
Welcome back to the third installment of our blog post series on Clean Architecture with Quarkus and Java 17. In this chapter, we're diving deep into the heart of our system by configuring the business module group. This pivotal group houses essential interfaces that define the interactions between our application's core logic, external services, and data repositories.