Quarkus multi-module cyclic reference problem

Viewed 41

This is my first project using Quarkus.
I made a multi-module project and in the parent pom I have this module structure:

    <modules>
        <module>domain</module>
        <module>application</module>
        <module>client</module>
    </modules>

In my domain module I have my interfaces that are supposed to be implemented by the application and client modules. So I added the <dependency> in the application and the client modules, for implementing the domain interfaces.
But when I want to add the <dependency> of the application module in my domain it doesn't work and when I build I have this error :

[ERROR] [ERROR] The projects in the reactor contain a cyclic reference: Edge between 'Vertex{label='com.test.name:application:0.0.1-SNAPSHOT'}' and 'Vertex{label='com.test.name:domain:0.0.1-SNAPSHOT'}' introduces to cycle in the graph com.test.name:domain:0.0.1-SNAPSHOT --> com.test.name:application:0.0.1-SNAPSHOT --> com.test.name:domain:0.0.1-SNAPSHOT @ [ERROR] The projects in the reactor contain a cyclic reference: Edge between 'Vertex{label='com.test.name:application:0.0.1-SNAPSHOT'}' and 'Vertex{label='com.test.name:domain:0.0.1-SNAPSHOT'}' introduces to cycle in the graph com.test.name:domain:0.0.1-SNAPSHOT --> com.test.name:application:0.0.1-SNAPSHOT --> com.test.name:domain:0.0.1-SNAPSHOT -> [Help 1]

I need this for dependency injection, my CDI container need to find the implementation to inject it. Does anyone have a solution ?

1 Answers

The way I like to structure my projects is roughly as follows:

  • Modules containing interfaces that are dependencies to other modules, similar to your domain module. They can be as fine or coarse grained as your design dictates. Examples are app-service-interfaces (e.g. interfaces for the business logic), app-dao-interfaces (interfaces for the DAO layer) etc.
  • Modules containing the implementation of a single "interface" module. The implementation modules depend only on interface modules, obviously the one they implement and any other they need. E.g. the module app-service-impl depends and implement the app-service-interfaces module, but also depends on the app-dao-interfaces module because it needs access to the application's datastore facilities. The implementation of app-dao-interfaces could be app-dao-jpa, if I choose to use JPA for the DAO layer. (Sidenote: keeping the interface modules free of dependencies to the actual technology used to implement them allows you to switch implementations easily.)
    • Neither the interface nor the implementation modules depend on the specific environment I intend to deploy on; Quarkus, JEE, Spring, Play, whatever.
  • Finally, a single module, I call it the "assembly" module (term borrowed from our .Net colleagues) that depends on all the implementation modules I intend to deploy plus the specific environment (e.g. Quarkus for this case). This module may contain environment-specific implementations of some components (e.g. Microprofile Config implementation for the component that reads and holds the configuration in a Quarkus environment).

2 final comments:

  • This is a proposal for one possible solution that works for me. I am sure there are plenty of others that work just as well; or this may not work for you for any reason!
  • I have applied this principle in this pet project and have a relevant explanation in this earlier, abandoned incarnation of the same project. Beware, these are just scratch projects :)
Related