[#modules]
= Modules

:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
:page-partial:

In Apache Isis we use Spring link:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html[@Configuration]s to define a module, consisting of a set of domain services and domain objects (entities, view models and mixins).
Spring's link:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Import.html[@Import] is used to express a dependency between each "configuration" module.

TIP: See Spring documentation on link:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-annotation-config[annotation-based container configuration], link:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-classpath-scanning[classpath scanning] and link:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-java[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 xref:overview.adoc#modules[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 xref:vw:exceldownload:about.adoc[Excel extension] module has several submodules, one of which is its applib.
This:

* has a Maven
** groupId = `org.apache.isis.extensions`
** artifactId = `isis-extensions-excel-applib`

* in the applib, has a top-level package of `org.apache.isis.extensions.excel.applib`

* defines a Spring configuration module called `IsisModuleExtExcelApplib`, that is simply:
+
[source,java]
----
@Configuration
@ComponentScan                                  // <.>
public class IsisModuleExtExcelApplib {
}
----
<.> the link:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html[@ComponentScan] indicates that the classpath should be scanned for domain services, entities and xref:testing:fixtures:about.adoc[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 link:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Import.html[@Import] in the `@Configuration` module.

We can see this for example in the `testing` module of the Excel library (artifactId of `isis-extensions-excel-testing`), where:



[plantuml]
.Testing submodule depends upon Applib submodule
----
include::docs:resources:partial$plantuml-stereotypes.puml[]

package excel-applib {
}
package excel-testing {
}

"excel-applib" <.- "excel-testing"
----

Therefore:

* in the testing module's `pom.xml`, we see:
+
[source,xml]
----
<dependency>
    <groupId>org.apache.isis.extensions</groupId>
    <artifactId>isis-extensions-excel-applib</artifactId>
</dependency>
----

* and in the testing module's `IsisModuleExtExcelTesting` we see:
+
[source,java]
----
@Configuration
@Import({                                           // <.>
    IsisModuleExtExcelApplib.class
})
@ComponentScan
public class IsisModuleExtExcelTesting {
}
----
<.> The link:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Import.html[@Import] annotation declares the dependency.

NOTE: 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:

[source,java]
----
package com.mycompany.modules.customer;
...

@Configuration                                  // <.>
@Import({
    IsisModuleExtExcelApplib.class       // <.>
})
@ComponentScan                                  // <.>
public class CustomerModule {}
----
<.> this is a module
<.> dependency on the Excel module (more precisely, its "applib")
<.> 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 Isis provides a convenience `@Module` annotation, which is meta-annotated with both.
The above example could therefore be rewritten as:

[source,java]
----
package com.mycompany.modules.customer;
...
import org.apache.isis.applib.annotation.Module;

@Module
@Import({
    IsisModuleExtExcelApplib.class
})
public class CustomerModule {}
----
