Modules
In Apache Causeway we use Spring @Configurations to define a module, consisting of a set of domain services and domain objects (entities, view models and mixins). Spring’s @Import is used to express a dependency between each "configuration" module.
See Spring documentation on annotation-based container configuration, classpath scanning and java-based configuration for much more on this topic. |
By convention, we have one Spring "logical" module in each Maven "physical" module, meaning that Maven itself can be used to enforce acyclic dependencies. (See previous chapter for more discussion on the alternatives).
Thus, there will be a single top-level package corresponding to the module, and this will be aligned with the <groupId>
and <artifactId>
of the Maven module in which it resides.
The framework’s own modules follow this convention. For example, the Excel extension module has several submodules, one of which is its applib. This:
-
has a Maven
-
groupId =
org.apache.causeway.extensions
-
artifactId =
causeway-extensions-excel-applib
-
-
in the applib, has a top-level package of
org.apache.causeway.extensions.excel.applib
-
defines a Spring configuration module called
CausewayModuleExtExcelApplib
, that is simply:@Configuration @ComponentScan (1) public class CausewayModuleExtExcelApplib { }
1 the @ComponentScan indicates that the classpath should be scanned for domain services, entities and fixture scripts.
When there is a dependency, this is expressed in two ways: first, as a "physical" <dependency
in Maven; and second, as a "logical" dependency using @Import in the @Configuration
module.
We can see this for example in the testing
module of the Excel library (artifactId of causeway-extensions-excel-testing
), where:
Therefore:
-
in the testing module’s
pom.xml
, we see:<dependency> <groupId>org.apache.causeway.extensions</groupId> <artifactId>causeway-extensions-excel-applib</artifactId> </dependency>
-
and in the testing module’s
CausewayModuleExtExcelTesting
we see:@Configuration @Import({ (1) CausewayModuleExtExcelApplib.class }) @ComponentScan public class CausewayModuleExtExcelTesting { }
1 The @Import annotation declares the dependency.
unlike Maven, there is no distinction in Spring between production (src/main/java ) and test (src/test/java ) classpath dependencies.
But if the physical classpath dependency is missing, then an incorrectly defined @Import will simply not compile.
|
In our own code, if an application’s customers
module needs to use the aforementioned Excel subdomain model (perhaps to generate a downloadable report), then this would be expressed using:
package com.mycompany.modules.customer;
...
@Configuration (1)
@Import({
CausewayModuleExtExcelApplib.class (2)
})
@ComponentScan (3)
public class CustomerModule {}
1 | this is a module |
2 | dependency on the Excel module (more precisely, its "applib") |
3 | scan for domain services and objects etc under this package (eg a Customer entity or a CustomerRepository domain service). |
Since @Configuration
and @ComponentScan
often appear together, Apache Causeway provides a convenience @Module
annotation, which is meta-annotated with both.
The above example could therefore be rewritten as:
package com.mycompany.modules.customer;
...
import org.apache.causeway.applib.annotation.Module;
@Module
@Import({
CausewayModuleExtExcelApplib.class
})
public class CustomerModule {}