Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/openliberty/guide-maven-multimodules

A guide on how to create a multi-module application with Maven and Open Liberty: https://openliberty.io/guides/maven-multimodules.html
https://github.com/openliberty/guide-maven-multimodules

Last synced: 2 months ago
JSON representation

A guide on how to create a multi-module application with Maven and Open Liberty: https://openliberty.io/guides/maven-multimodules.html

Awesome Lists containing this project

README

        

// Copyright (c) 2017, 2023 IBM Corporation and others.
// Licensed under Creative Commons Attribution-NoDerivatives
// 4.0 International (CC BY-ND 4.0)
// https://creativecommons.org/licenses/by-nd/4.0/
//
// Contributors:
// IBM Corporation
:projectid: maven-multimodules
:page-layout: guide-multipane
:page-duration: 30 minutes
:page-releasedate: 2017-10-04
:page-majorupdateddate: 2021-11-19
:page-description: Learn how to build an application consisting of JAR, WAR, and EAR modules with Maven
:page-related-guides: ['maven-intro']
:page-seo-title: Building a multi-module enterprise Java application with Maven and Open Liberty
:page-seo-description: A getting started tutorial and an example on how to use Maven to build a Java or Jakarta EE application with multiple modules consisting of Java archive (JAR), web archive (WAR), and enterprise archive (EAR) projects.
:page-permalink: /guides/{projectid}
:common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod
:source-highlighter: prettify
:guide-author: Open Liberty
= Creating a multi-module application

[.hidden]
NOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website^].

You will learn how to build an application with multiple modules with Maven and Open Liberty.

// =================================================================================================
// What you'll learn
// =================================================================================================

== What you'll learn

A Jakarta Platform, Enterprise Edition (Jakarta EE) application consists of modules that work together as one entity. An enterprise archive (EAR) is a wrapper for a Jakarta EE application, which consists of web archive (WAR) and Java archive (JAR) files. To deploy or distribute the Jakarta EE application into new environments, all the modules and resources must first be packaged into an EAR file.

In this guide, you will learn how to:

* establish a dependency between a web module and a Java library module,
* 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, and
* use Liberty Maven plug-in to develop a multi-module application in https://openliberty.io/docs/latest/development-mode.html#_run_multi_module_maven_projects_in_dev_mode[dev mode^] without having to prebuild the JAR and WAR files. In dev mode, your changes are automatically picked up by the running Liberty instance.

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
// =================================================================================================

[role=command]
include::{common-includes}/gitclone.adoc[]

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:

1. Add a dependency relationship between the two modules.

2. Assemble the entire application into an EAR file.

3. Aggregate the entire build.

4. 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:

[role=command]
----
cd finish
mvn install
----

To deploy your EAR application on Open Liberty, run the Maven `liberty:run` goal from the finish directory using the `-pl` flag to specify the `ear` project. The `-pl` flag specifies the project where the Maven goal runs.

[role=command]
----
mvn -pl ear liberty:run
----

ifndef::cloud-hosted[]
Once the Liberty instance is running, you can find the application at the following URL: http://localhost:9080/converter/[http://localhost:9080/converter/^]
endif::[]
ifdef::cloud-hosted[]
Once the Liberty instance is running, click the following button to check out your service by visiting the ***/converter*** endpoint.
::startApplication{port="9080" display="external" name="Visit application" route="/converter"}
endif::[]

After you are finished checking out the application, stop the Open Liberty instance by pressing `CTRL+C` in the command-line session where you ran the Liberty. Alternatively, you can run the `liberty:stop` goal using the `-pl ear` flag from the `finish` directory in another command-line session:

[role=command]
----
mvn -pl ear liberty:stop
----

// =================================================================================================
// Adding dependencies between WAR and JAR modules
// =================================================================================================

== 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.
// cloud hosted instructions
ifdef::cloud-hosted[]
```bash
cd /home/project/guide-maven-multimodules/start
```
endif::[]

[role="code_command hotspot", subs="quotes"]
----
#Replace the war/POM file.#
`war/pom.xml`
----
war/pom.xml
[source, xml, linenums, role='code_column']
----
include::finish/war/pom.xml[]
----
The added [hotspot=dependency file=0]`dependency` element is the Java library module that implements the functions that you need for the unit converter.

Although the [hotspot=parent file=0]`parent/child` structure is not normally needed for multi-module applications, adding it helps us to better organize all of the projects. This structure allows all of the child projects to make use of the plugins that are defined in the parent `pom.xml` file, without having to define them again in the child `pom.xml` files.

// =================================================================================================
// Assembling multiple modules into an EAR file
// =================================================================================================

== Assembling multiple modules into an EAR file

To deploy the entire application on Open Liberty, 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.
[role="code_command hotspot", subs="quotes"]
----
#Replace the ear/POM file.#
`ear/pom.xml`
----
ear/pom.xml
[source, xml, linenums, role='code_column']
----
include::finish/ear/pom.xml[]
----

Set the [hotspot=packaging file=0]`basic configuration` for the project and set the [hotspot=packagingType file=0]`packaging` element to `ear`.

The [hotspot=dependency-jar file=0]`Java library module` and the [hotspot=dependency-war file=0]`web module` were added as dependencies. Specify a type of [hotspot=warType file=0]`war` 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 [hotspot=maven-ear-plugin file=0]`maven-ear-plugin` plug-in were added to create an EAR file. Define the [hotspot=jarModule file=0]`jarModule` and [hotspot=webModule file=0]`webModule` modules to be packaged into the EAR file. To customize the context root of the application, set the [hotspot=contextRoot file=0]`contextRoot` element to [hotspot=contextRoot file=0]`/converter` in the [hotspot=webModule file=0]`webModule`. Otherwise, Maven automatically uses the WAR file `artifactId` ID as the context root for the application while generating the `application.xml` file.

To deploy and run an EAR application on an Open Liberty instance, you need to provide a Liberty's `server.xml` configuration file.

[role="code_command hotspot file=1", subs="quotes"]
----
#Create the Liberty `server.xml` configuration file.#
`ear/src/main/liberty/config/server.xml`
----
server.xml
[source, xml, linenums, role='code_column']
----
include::finish/ear/src/main/liberty/config/server.xml[]
----

You must configure the `server.xml` configuration file with the [hotspot=EARdefinition file=1]`enterpriseApplication` element to specify the location of your EAR application.

// =================================================================================================
// Aggregating the entire build
// =================================================================================================

== Aggregating the entire build

Because you have multiple modules, aggregate the Maven projects to simplify the build process.

Create a parent [hotspot]`pom.xml` file under the `start` directory to link all of the child modules together. A template is provided for you.

[role="code_command hotspot", subs="quotes"]
----
#Replace the start/POM file.#
`pom.xml`
----
start/pom.xml
[source, xml, linenums, role='code_column']
----
include::finish/pom.xml[]
----

Set the [hotspot=packaging file=0]`basic configuration` for the project. Set `pom` as the value for the [hotspot=packagingType file=0]`packaging` element of the parent [hotspot file=0]`pom.xml` file.

In the parent [hotspot file=0]`pom.xml` file, list all of the [hotspot=modules file=0]`modules` that you want to aggregate for the application.

Adding the [hotspot=maven-war-plugin file=0]`maven-war-plugin`, [hotspot=maven-compiler-plugin file=0]`maven-compiler-plugin`, and [hotspot=liberty-maven-plugin file=0]`liberty-maven-plugin` plug-ins allows each child module to inherit the plug-ins, so that you can use the these to develop the modules.

// =================================================================================================
// Developing the application
// =================================================================================================

== Developing the application

You can now develop the application and the different modules together in dev mode by using the Liberty Maven plug-in. To learn more about how to use dev mode with multiple modules, check out the https://github.com/OpenLiberty/ci.maven/blob/main/docs/dev.md#multiple-modules[Documentation^].

Navigate to the `start` directory to begin.
// cloud hosted instructions
ifdef::cloud-hosted[]
```bash
cd /home/project/guide-maven-multimodules/start
```
endif::[]

[role='command']
include::{common-includes}/devmode-lmp33-start.adoc[]

=== Updating the Java classes in different modules

Update the `HeightsBean` class to use the Java library module that implements the functions that you need for the unit converter.

Navigate to the `start` directory.

[role="code_command hotspot file=0", subs="quotes"]
----
#Replace the `HeightsBean` class in the `war` directory.#
`war/src/main/java/io/openliberty/guides/multimodules/web/HeightsBean.java`
----
HeightsBean.java
[source, Java, linenums, role='code_column hide_tags=copyright']
----
include::finish/war/src/main/java/io/openliberty/guides/multimodules/web/HeightsBean.java[]
----

The [hotspot=getFeet file=0]`getFeet(cm)` invocation was added to the [hotspot=setHeightFeet file=0]`setHeightFeet` method to convert a measurement into feet.

The [hotspot=getInches file=0]`getInches(cm)` invocation was added to the [hotspot=setHeightInches file=0]`setHeightInches` method to convert a measurement into inches.

ifndef::cloud-hosted[]
You can check out the running application by going to the http://localhost:9080/converter/[http://localhost:9080/converter/^] URL.
endif::[]
ifdef::cloud-hosted[]
Click the following button to check out the running application by visiting the ***/converter*** endpoint:
::startApplication{port="9080" display="external" name="Visit application" route="/converter"}
endif::[]

Now try updating the converter so that it converts heights correctly, rather than returning 0.

[role="code_command hotspot file=1", subs="quotes"]
----
#Replace the `Converter` class in the `jar` directory.#
`jar/src/main/java/io/openliberty/guides/multimodules/lib/Converter.java`
----
Converter.java
[source, Java, linenums, role='code_column hide_tags=copyright']
----
include::finish/jar/src/main/java/io/openliberty/guides/multimodules/lib/Converter.java[]
----

Change the [hotspot=getFeetMethod file=1]`getFeet` method so that it converts from centimetres to feet, and the [hotspot=getInchesMethod file=1]`getInches` method so that it converts from centimetres to inches. Update the `sum`, `diff`, `product` and `quotient` functions so that they add, subtract, multiply, and divide 2 numbers respectively.

ifndef::cloud-hosted[]
Now revisit the application at the http://localhost:9080/converter/[http://localhost:9080/converter/^] URL. Try entering a height in centimetres and see if it converts correctly.
endif::[]
ifdef::cloud-hosted[]
Now revisit the application by visiting the ***/converter*** endpoint:
::startApplication{port="9080" display="external" name="Visit application" route="/converter"}

Try entering a height in centimetres and see if it converts correctly.
endif::[]

=== Testing the multi-module application

To test the multi-module application, add integration tests to the EAR project.

[role="code_command hotspot", subs="quotes"]
----
#Create the integration test class in the `ear` directory.#
`ear/src/test/java/it/io/openliberty/guides/multimodules/IT.java`
----
IT.java
[source, Java, linenums, role='code_column hide_tags=copyright']
----
include::finish/ear/src/test/java/it/io/openliberty/guides/multimodules/IT.java[]
----

The [hotspot=testIndexPage file=0]`testIndexPage` tests to check that you can access the landing page.

The [hotspot=testHeightsPage file=0]`testHeightsPage` tests to check that the application can process the input value and calculate the result correctly.

=== Running the tests

Because you started Open Liberty in dev mode, press the *enter/return* key to run the tests.

You will see the following output:

[source, role="no_copy"]
----
-------------------------------------------------------
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

----

When you are done checking out the service, exit dev mode by pressing `CTRL+C` in the command-line session where you ran the Liberty.

// =================================================================================================
// Building the multi-module application
// =================================================================================================

== Building the multi-module application

You aggregated and developed the application. Now, 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 that contains the JAR and WAR files in the `ear/target` directory.

ifndef::cloud-hosted[]
Run the following command from the start directory to build the entire application:

[role=command]
----
mvn install
----
endif::[]
ifdef::cloud-hosted[]
Run the following commands to navigate to the start directory and build the entire application:
```bash
cd /home/project/guide-maven-multimodules/start
mvn install
```
endif::[]

Since the modules are independent, you can re-build them individually by running `mvn install` from the corresponding `start` directory for each module.

ifndef::cloud-hosted[]
Or, run `mvn -pl install` from the start directory.
endif::[]
ifdef::cloud-hosted[]
Or, run `mvn -pl install` from the start directory.
endif::[]

// =================================================================================================
// Congratulations! You're done!
// =================================================================================================

== Great work! You're done!

You built and tested a multi-module Java application for unit conversion with Maven on Open Liberty.

include::{common-includes}/attribution.adoc[subs="attributes"]