git clone https://github.com/openliberty/guide-maven-multimodules.git
cd guide-maven-multimodules
Contents
Tags
Creating a multi-module application
Prerequisites:
You will learn how to build an application with multiple modules with Maven and Open Liberty.
What you’ll learn
A Java Platform, Enterprise Edition (Java EE) application consists of modules that work together as one entity. An enterprise archive (EAR) is a wrapper for a Java EE application, which consists of web archive (WAR) and Java archive (JAR) files. To deploy or distribute the Java EE application into new environments, all the modules and resources must first be packaged into an EAR file.
You will learn how to establish a dependency between a web module and a Java library module. You will use Maven to package the WAR file and the JAR file into an EAR file so that you can run and test the application on Open Liberty.
You will build a unit converter application that converts heights from centimeters into feet and inches. The application will request the user to enter a height value in centimeters. Then, the application processes the input by using functions that are found in the JAR file to return the height value in imperial units.
Getting started
The fastest way to work through this guide is to clone the Git repository and use the projects that are provided inside:
The start
directory contains the starting project that you will build upon.
The finish
directory contains the finished project that you will build.
Access partial implementation of the application from the start
folder. This folder includes a web module in the war
folder, a Java library in the jar
folder, and template files in the ear
folder. However, the Java library and the web module are independent projects, and you will need to complete the following steps to implement the application:
Add a dependency relationship between the two modules.
Assemble the entire application into an EAR file.
Aggregate the entire build.
Test the multi-module application.
Try what you’ll build
The finish
directory in the root of this guide contains the finished application. Give it a try before you proceed.
To try out the application, first go to the finish
directory and run the following Maven goal to build the application:
cd finish mvn install
To deploy your EAR application on an Open Liberty server, run the Maven liberty:run
goal from the ear
directory:
cd ear mvn liberty:run
Once the server is running, you can find the application at the following URL: http://localhost:9080/converter/
After you are finished checking out the application, stop the Open Liberty server by pressing CTRL+C
in the command-line session where you ran the server. Alternatively, you can run the liberty:stop
goal from the finish\ear
directory in another command-line session:
mvn liberty:stop
Adding dependencies between WAR and JAR modules
To use a Java library in your web module, you must add a dependency relationship between the two modules.
As you might have noticed, each module has its own pom.xml
file. Each module has its own pom.xml
file because each module is treated as an independent project. You can rebuild, reuse, and reassemble every module on its own.
Navigate to the start
directory to begin.
Replace the war/POM file.
war/pom.xml
war/pom.xml
1<?xml version='1.0' encoding='utf-8'?>
2<project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5 http://maven.apache.org/xsd/maven-4.0.0.xsd">
6
7 <modelVersion>4.0.0</modelVersion>
8
9 <groupId>io.openliberty.guides</groupId>
10 <artifactId>guide-maven-multimodules-war</artifactId>
11 <packaging>war</packaging>
12 <version>1.0-SNAPSHOT</version>
13 <name>guide-maven-multimodules-war</name>
14 <url>http://maven.apache.org</url>
15
16 <properties>
17 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
19 <maven.compiler.source>1.8</maven.compiler.source>
20 <maven.compiler.target>1.8</maven.compiler.target>
21 </properties>
22
23 <dependencies>
24
25 <!-- Provided dependencies -->
26 <dependency>
27 <groupId>javax.servlet</groupId>
28 <artifactId>javax.servlet-api</artifactId>
29 <version>4.0.1</version>
30 <scope>provided</scope>
31 </dependency>
32 <dependency>
33 <groupId>jakarta.platform</groupId>
34 <artifactId>jakarta.jakartaee-api</artifactId>
35 <version>8.0.0</version>
36 <scope>provided</scope>
37 </dependency>
38 <dependency>
39 <groupId>org.eclipse.microprofile</groupId>
40 <artifactId>microprofile</artifactId>
41 <version>3.3</version>
42 <type>pom</type>
43 <scope>provided</scope>
44 </dependency>
45
46 <!-- tag::dependency[] -->
47 <dependency>
48 <groupId>io.openliberty.guides</groupId>
49 <artifactId>guide-maven-multimodules-jar</artifactId>
50 <version>1.0-SNAPSHOT</version>
51 </dependency>
52 <!-- end::dependency[] -->
53
54 </dependencies>
55
56</project>
The <dependency/>
element is the Java library module that implements the functions that you need for the unit converter.
With this dependency, you can use any functions included in the library in the HeightsBean.java
file of the web module.
Replace theHeightsBean
class.war/src/main/java/io/openliberty/guides/multimodules/web/HeightsBean.java
HeightsBean.java
The getFeet(cm)
invocation was added to the setHeightFeet
method to convert a measurement into feet.
The getInches(cm)
invocation was added to the setHeightInches
method to convert a measurement into inches.
Assembling multiple modules into an EAR file
To deploy the entire application on the Open Liberty server, first package the application. Use the EAR project to assemble multiple modules into an EAR file.
Navigate to the ear
folder and find a template pom.xml
file.
Replace the ear/POM file.
ear/pom.xml
ear/pom.xml
1<?xml version='1.0' encoding='utf-8'?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
3 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4
5 <modelVersion>4.0.0</modelVersion>
6
7 <!-- tag::packaging[] -->
8 <groupId>io.openliberty.guides</groupId>
9 <artifactId>guide-maven-multimodules-ear</artifactId>
10 <version>1.0-SNAPSHOT</version>
11 <!-- tag::packagingType[] -->
12 <packaging>ear</packaging>
13 <!-- end::packagingType[] -->
14 <!-- end::packaging[] -->
15
16 <properties>
17 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
19 <maven.compiler.source>1.8</maven.compiler.source>
20 <maven.compiler.target>1.8</maven.compiler.target>
21 <!-- Liberty configuration -->
22 <liberty.var.default.http.port>9080</liberty.var.default.http.port>
23 <liberty.var.default.https.port>9443</liberty.var.default.https.port>
24 </properties>
25
26 <dependencies>
27 <!-- web and jar modules as dependencies -->
28 <!-- tag::dependencies[] -->
29 <!-- tag::dependency-jar[] -->
30 <dependency>
31 <groupId>io.openliberty.guides</groupId>
32 <artifactId>guide-maven-multimodules-jar</artifactId>
33 <version>1.0-SNAPSHOT</version>
34 <type>jar</type>
35 </dependency>
36 <!-- end::dependency-jar[] -->
37 <!-- tag::dependency-war[] -->
38 <dependency>
39 <groupId>io.openliberty.guides</groupId>
40 <artifactId>guide-maven-multimodules-war</artifactId>
41 <version>1.0-SNAPSHOT</version>
42 <!-- tag::warType[] -->
43 <type>war</type>
44 <!-- end::warType[] -->
45 </dependency>
46 <!-- end::dependency-war[] -->
47 <!-- end::dependencies[] -->
48
49 <!-- For tests -->
50 <dependency>
51 <groupId>org.junit.jupiter</groupId>
52 <artifactId>junit-jupiter</artifactId>
53 <version>5.6.2</version>
54 <scope>test</scope>
55 </dependency>
56 </dependencies>
57
58 <build>
59 <finalName>${project.artifactId}</finalName>
60 <plugins>
61 <!-- tag::maven-ear-plugin[] -->
62 <plugin>
63 <groupId>org.apache.maven.plugins</groupId>
64 <artifactId>maven-ear-plugin</artifactId>
65 <version>3.0.2</version>
66 <configuration>
67 <modules>
68 <!-- tag::jarModule[] -->
69 <jarModule>
70 <groupId>io.openliberty.guides</groupId>
71 <artifactId>guide-maven-multimodules-jar</artifactId>
72 <uri>/guide-maven-multimodules-jar-1.0-SNAPSHOT.jar</uri>
73 </jarModule>
74 <!-- end::jarModule[] -->
75 <!-- tag::webModule[] -->
76 <webModule>
77 <groupId>io.openliberty.guides</groupId>
78 <artifactId>guide-maven-multimodules-war</artifactId>
79 <uri>/guide-maven-multimodules-war-1.0-SNAPSHOT.war</uri>
80 <!-- Set custom context root -->
81 <!-- tag::contextRoot[] -->
82 <contextRoot>/converter</contextRoot>
83 <!-- end::contextRoot[] -->
84 </webModule>
85 <!-- end::webModule[] -->
86 </modules>
87 </configuration>
88 </plugin>
89 <!-- end::maven-ear-plugin[] -->
90
91 <!-- Enable liberty-maven plugin -->
92 <!-- tag::liberty-maven-plugin[] -->
93 <plugin>
94 <groupId>io.openliberty.tools</groupId>
95 <artifactId>liberty-maven-plugin</artifactId>
96 <version>3.2.3</version>
97 </plugin>
98 <!-- end::liberty-maven-plugin[] -->
99
100 <!-- Since the package type is ear,
101 need to run testCompile to compile the tests -->
102 <!-- tag::maven-compiler-plugin[] -->
103 <plugin>
104 <groupId>org.apache.maven.plugins</groupId>
105 <artifactId>maven-compiler-plugin</artifactId>
106 <version>3.8.1</version>
107 <executions>
108 <execution>
109 <phase>test-compile</phase>
110 <!-- tag::testCompile[] -->
111 <goals>
112 <goal>testCompile</goal>
113 </goals>
114 <!-- end::testCompile[] -->
115 </execution>
116 </executions>
117 </plugin>
118 <!-- end::maven-compiler-plugin[] -->
119
120 <!-- Plugin to run integration tests -->
121 <plugin>
122 <groupId>org.apache.maven.plugins</groupId>
123 <artifactId>maven-failsafe-plugin</artifactId>
124 <version>2.22.2</version>
125 <configuration>
126 <systemPropertyVariables>
127 <default.http.port>
128 ${liberty.var.default.http.port}
129 </default.http.port>
130 <default.https.port>
131 ${liberty.var.default.https.port}
132 </default.https.port>
133 <cf.context.root>/converter</cf.context.root>
134 </systemPropertyVariables>
135 </configuration>
136 </plugin>
137 </plugins>
138 </build>
139
140</project>
Set the basic configuration
for the project and set the <packaging/>
element to ear
.
The Java library module
and the web module
were added as dependencies. Specify <type>war</type>
for the web module. If you don’t specify this type for the web module, Maven looks for a JAR file.
The definition and configuration of the maven-ear-plugin
plug-in were added to create an EAR file. Define the <jarModule/>
and <webModule/>
modules to be packaged into the EAR file. To customize the context root of the application, set the <contextRoot>/converter</contextRoot>
element in the <webModule/>
. Otherwise, Maven automatically uses the WAR file artifactId
ID as the context root for the application while generating the application.xml
file.
To download and start an Open Liberty server, use the liberty-maven-plugin
plug-in for Maven. This configuration is provided, and the executions of the plug-in follow the typical phases of a Maven life cycle.
To deploy and run an EAR application on an Open Liberty server, you need to provide a server configuration file.
Create the server configuration file.
ear/src/main/liberty/config/server.xml
server.xml
1<server description="Sample Liberty server">
2
3 <featureManager>
4 <feature>jsp-2.3</feature>
5 </featureManager>
6
7 <variable name="default.http.port" defaultValue="9080" />
8 <variable name="default.https.port" defaultValue="9443" />
9
10 <!-- tag::server[] -->
11 <httpEndpoint host="*" httpPort="${default.http.port}"
12 httpsPort="${default.https.port}" id="defaultHttpEndpoint" />
13
14 <!-- tag::EARdefinition[] -->
15 <enterpriseApplication id="guide-maven-multimodules-ear"
16 location="guide-maven-multimodules-ear.ear"
17 name="guide-maven-multimodules-ear" />
18 <!-- end::EARdefinition[] -->
19 <!-- end::server[] -->
20</server>
You must configure the server.xml
file with the <enterpriseApplication/>
element to specify the location of your EAR application.
Aggregating the entire build
Because you have multiple modules, aggregate the Maven projects to simplify the build process.
Create a parent pom.xml
file under the start
directory to link all of the child modules together. A template is provided for you.
Replace the start/POM file.
pom.xml
start/pom.xml
1<?xml version='1.0' encoding='utf-8'?>
2<project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5 http://maven.apache.org/xsd/maven-4.0.0.xsd">
6
7 <modelVersion>4.0.0</modelVersion>
8
9 <!-- tag::packaging[] -->
10 <!-- tag::groupId[] -->
11 <groupId>io.openliberty.guides</groupId>
12 <!-- end::groupId[] -->
13 <artifactId>guide-maven-multimodules</artifactId>
14 <version>1.0-SNAPSHOT</version>
15 <!-- tag::packagingType[] -->
16 <packaging>pom</packaging>
17 <!-- end::packagingType[] -->
18 <!-- end::packaging[] -->
19
20 <!-- tag::modules[] -->
21 <modules>
22 <module>jar</module>
23 <module>war</module>
24 <module>ear</module>
25 </modules>
26 <!-- end::modules[] -->
27</project>
Set the basic configuration
for the project. Set pom
as the <packaging/>
element of the parent pom.xml
file.
In the parent pom.xml
file, list all of the <modules/>
that you want to aggregate for the application.
Building the modules
By aggregating the build in the previous section, you can run mvn install
once from the start
directory and it will automatically build all your modules. This command creates a JAR file in the jar/target
directory, a WAR file in the war/target
directory, and an EAR file in the ear/target
directory, which contains the JAR and WAR files.
Use the following command to build the entire application from the start
directory:
mvn install
Since the modules are independent, you can re-build them individually by running mvn install
from the corresponding module directory.
Starting the application
To deploy your EAR application on an Open Liberty server, run the Maven liberty:run
goal from the ear
directory:
cd ear mvn liberty:run
Once the server is running, you can find the application at the following URL: http://localhost:9080/converter/
After you are finished checking out the application, stop the Open Liberty server by pressing CTRL+C
in the command-line session where you ran the server. Alternatively, you can run the liberty:stop
goal from the start\ear
directory in another command-line session:
mvn liberty:stop
Testing the multi-module application
To test the multi-module application, add integration tests to the EAR project.
Navigate to the start\ear
directory.
Create the integration test class.
src/test/java/it/io/openliberty/guides/multimodules/IT.java
IT.java
The testIndexPage
tests to check that you can access the landing page.
The testHeightsPage
tests to check that the application can process the input value and calculate the result correctly.
For a Maven EAR project, the testCompile
goal is specified for the maven-compiler-plugin
plug-in in your ear/pom.xml
file so that the test cases are compiled and picked up for execution. Run the following command to compile the test class:
mvn test-compile
ear/pom.xml
1<?xml version='1.0' encoding='utf-8'?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
3 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4
5 <modelVersion>4.0.0</modelVersion>
6
7 <!-- tag::packaging[] -->
8 <groupId>io.openliberty.guides</groupId>
9 <artifactId>guide-maven-multimodules-ear</artifactId>
10 <version>1.0-SNAPSHOT</version>
11 <!-- tag::packagingType[] -->
12 <packaging>ear</packaging>
13 <!-- end::packagingType[] -->
14 <!-- end::packaging[] -->
15
16 <properties>
17 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
19 <maven.compiler.source>1.8</maven.compiler.source>
20 <maven.compiler.target>1.8</maven.compiler.target>
21 <!-- Liberty configuration -->
22 <liberty.var.default.http.port>9080</liberty.var.default.http.port>
23 <liberty.var.default.https.port>9443</liberty.var.default.https.port>
24 </properties>
25
26 <dependencies>
27 <!-- web and jar modules as dependencies -->
28 <!-- tag::dependencies[] -->
29 <!-- tag::dependency-jar[] -->
30 <dependency>
31 <groupId>io.openliberty.guides</groupId>
32 <artifactId>guide-maven-multimodules-jar</artifactId>
33 <version>1.0-SNAPSHOT</version>
34 <type>jar</type>
35 </dependency>
36 <!-- end::dependency-jar[] -->
37 <!-- tag::dependency-war[] -->
38 <dependency>
39 <groupId>io.openliberty.guides</groupId>
40 <artifactId>guide-maven-multimodules-war</artifactId>
41 <version>1.0-SNAPSHOT</version>
42 <!-- tag::warType[] -->
43 <type>war</type>
44 <!-- end::warType[] -->
45 </dependency>
46 <!-- end::dependency-war[] -->
47 <!-- end::dependencies[] -->
48
49 <!-- For tests -->
50 <dependency>
51 <groupId>org.junit.jupiter</groupId>
52 <artifactId>junit-jupiter</artifactId>
53 <version>5.6.2</version>
54 <scope>test</scope>
55 </dependency>
56 </dependencies>
57
58 <build>
59 <finalName>${project.artifactId}</finalName>
60 <plugins>
61 <!-- tag::maven-ear-plugin[] -->
62 <plugin>
63 <groupId>org.apache.maven.plugins</groupId>
64 <artifactId>maven-ear-plugin</artifactId>
65 <version>3.0.2</version>
66 <configuration>
67 <modules>
68 <!-- tag::jarModule[] -->
69 <jarModule>
70 <groupId>io.openliberty.guides</groupId>
71 <artifactId>guide-maven-multimodules-jar</artifactId>
72 <uri>/guide-maven-multimodules-jar-1.0-SNAPSHOT.jar</uri>
73 </jarModule>
74 <!-- end::jarModule[] -->
75 <!-- tag::webModule[] -->
76 <webModule>
77 <groupId>io.openliberty.guides</groupId>
78 <artifactId>guide-maven-multimodules-war</artifactId>
79 <uri>/guide-maven-multimodules-war-1.0-SNAPSHOT.war</uri>
80 <!-- Set custom context root -->
81 <!-- tag::contextRoot[] -->
82 <contextRoot>/converter</contextRoot>
83 <!-- end::contextRoot[] -->
84 </webModule>
85 <!-- end::webModule[] -->
86 </modules>
87 </configuration>
88 </plugin>
89 <!-- end::maven-ear-plugin[] -->
90
91 <!-- Enable liberty-maven plugin -->
92 <!-- tag::liberty-maven-plugin[] -->
93 <plugin>
94 <groupId>io.openliberty.tools</groupId>
95 <artifactId>liberty-maven-plugin</artifactId>
96 <version>3.2.3</version>
97 </plugin>
98 <!-- end::liberty-maven-plugin[] -->
99
100 <!-- Since the package type is ear,
101 need to run testCompile to compile the tests -->
102 <!-- tag::maven-compiler-plugin[] -->
103 <plugin>
104 <groupId>org.apache.maven.plugins</groupId>
105 <artifactId>maven-compiler-plugin</artifactId>
106 <version>3.8.1</version>
107 <executions>
108 <execution>
109 <phase>test-compile</phase>
110 <!-- tag::testCompile[] -->
111 <goals>
112 <goal>testCompile</goal>
113 </goals>
114 <!-- end::testCompile[] -->
115 </execution>
116 </executions>
117 </plugin>
118 <!-- end::maven-compiler-plugin[] -->
119
120 <!-- Plugin to run integration tests -->
121 <plugin>
122 <groupId>org.apache.maven.plugins</groupId>
123 <artifactId>maven-failsafe-plugin</artifactId>
124 <version>2.22.2</version>
125 <configuration>
126 <systemPropertyVariables>
127 <default.http.port>
128 ${liberty.var.default.http.port}
129 </default.http.port>
130 <default.https.port>
131 ${liberty.var.default.https.port}
132 </default.https.port>
133 <cf.context.root>/converter</cf.context.root>
134 </systemPropertyVariables>
135 </configuration>
136 </plugin>
137 </plugins>
138 </build>
139
140</project>
Then, enter the following command to start the server, run the tests, then stop the server:
mvn liberty:start failsafe:integration-test liberty:stop
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.multimodules.IT
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.712 sec - in it.io.openliberty.guides.multimodules.IT
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
Great work! You’re done!
You built and tested a multi-module unit converter application with Maven on Open Liberty.
Guide Attribution
Creating a multi-module application by Open Liberty is licensed under CC BY-ND 4.0
Prerequisites:
Nice work! Where to next?
What did you think of this guide?




Thank you for your feedback!
What could make this guide better?
Raise an issue to share feedback
Create a pull request to contribute to this guide
Need help?
Ask a question on Stack Overflow