From f65ad50de516981048ce9a72b6fb75b104c8b388 Mon Sep 17 00:00:00 2001 From: GuidesBot Date: Thu, 17 Oct 2024 18:40:47 +0000 Subject: [PATCH] Updated by github actions from guide-jms-intro --- .../instructions.md | 1231 +++++++++++++++++ 1 file changed, 1231 insertions(+) create mode 100644 instructions/cloud-hosted-guide-jms-intro/instructions.md diff --git a/instructions/cloud-hosted-guide-jms-intro/instructions.md b/instructions/cloud-hosted-guide-jms-intro/instructions.md new file mode 100644 index 00000000..36d417b9 --- /dev/null +++ b/instructions/cloud-hosted-guide-jms-intro/instructions.md @@ -0,0 +1,1231 @@ +--- +markdown-version: v1 +tool-type: theiadocker +--- +::page{title="Welcome to the Producing and consuming messages in Java microservices guide!"} + +Learn how to produce and consume messages to communicate between Java microservices in a standard way by using the Jakarta Messaging API with the embedded Liberty Messaging Server or an external messaging server, IBM MQ. + +In this guide, you will use a pre-configured environment that runs in containers on the cloud and includes everything that you need to complete the guide. + +This panel contains the step-by-step guide instructions. You can customize these instructions by using the toolbar at the top of this panel. Move between steps by using either the arrows or the buttons at the bottom of this panel. + +The other panel displays the IDE that you will use to create files, edit the code, and run commands. This IDE is based on Visual Studio Code. It includes pre-installed tools and a built-in terminal. + + + +::page{title="What you'll learn"} + +You’ll learn how to communicate between Java web services when one service is producing a continuous stream of asynchronous messages or events to be consumed by other services, rather than just sending and receiving individual requests for data. You will also learn how to use a messaging server and client to manage the production and consumption of the messages by the services. + +In this guide, you will first use the embedded Liberty Messaging Server to manage messages, then you will optionally switch to using an external messaging server to manage the messages, in this case, [IBM MQ](https://www.ibm.com/products/mq). You might use an external messaging server if it is critical that none of the messages is lost if there is a system overload or outage; for example during a bank transfer in a banking application. + +You will learn how to write your Java application using the Jakarta Messaging API which provides a standard way to produce and consume messages in Java application, regardless of which messaging server your application will ultimately use. + +The application in this guide consists of two microservices, ***system*** and ***inventory***. Every 15 seconds, the ***system*** microservice computes and publishes a message that contains the system’s current CPU and memory load usage. The ***inventory*** microservice subscribes to that information at the ***/systems*** REST endpoint so that it can keep an updated list of all the systems and their current system loads. + +You’ll create the ***system*** and ***inventory*** microservices using the Jakarta Messaging API to produce and consume the messages using the embedded Liberty Messaging Server. + +![Application architecture where system and inventory services use the Jakarta Messaging to communicate.](https://raw.githubusercontent.com/OpenLiberty/guide-jms-intro/prod/assets/architecture.png) + + +You will then, optionally, reconfigure the application, without changing the application's Java code, to use an external IBM MQ messaging server instead. + +::page{title="Getting started"} + +To open a new command-line session, +select **Terminal** > **New Terminal** from the menu of the IDE. + +Run the following command to navigate to the **/home/project** directory: + +```bash +cd /home/project +``` + +The fastest way to work through this guide is to clone the [Git repository](https://github.com/openliberty/guide-jms-intro.git) and use the projects that are provided inside: + +```bash +git clone https://github.com/openliberty/guide-jms-intro.git +cd guide-jms-intro +``` + + +The ***start*** directory contains the starting project that you will build upon. + +The ***finish*** directory contains the finished project that you will build. + +### 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 and install the ***models*** module. The ***models*** module contains the ***SystemLoad*** data class for both the ***system*** and ***inventory*** microservices to use. + + +```bash +cd /home/project/guide-jms-intro/finish +mvn -pl models clean install +``` + + +Start the ***inventory*** microservice by running the following command: + +```bash +mvn -pl inventory liberty:run +``` + +Next, open another command-line session, navigate to the ***finish*** directory, and start the ***system*** microservice by using the following command: + + +```bash +cd /home/project/guide-jms-intro/finish +mvn -pl system liberty:run +``` + +When you see the following message, your Liberty instances are ready: +``` +The defaultServer server is ready to run a smarter planet. +``` + + + +Open another command-line session by selecting **Terminal** > **New Terminal** from the menu of the IDE. + + +Visit the ***http\://localhost:9081/health*** URL to confirm that the ***inventory*** microservice is up and running. + + +_To see the output for this URL in the IDE, run the following command at a terminal:_ + +```bash +curl -s http://localhost:9081/health | jq +``` + + + + +When both the liveness and readiness health checks are up, go to the ***http\://localhost:9081/inventory/systems*** URL to access the ***inventory*** microservice. You see the ***systemLoad*** property for all the systems: + + +_To see the output for this URL in the IDE, run the following command at a terminal:_ + +```bash +curl -s http://localhost:9081/inventory/systems | jq +``` + + + +``` +{ + "hostname": , + "systemLoad": 6.037155240703536E-9 +} +``` + + +You can revisit the ***http\://localhost:9081/inventory/systems*** URL after a while, and you will notice the ***systemLoad*** property for the systems changed. + + +_To see the output for this URL in the IDE, run the following command at a terminal:_ + +```bash +curl -s http://localhost:9081/inventory/systems | jq +``` + + + + +After you are finished checking out the application, stop the Liberty instances by pressing `Ctrl+C` in each command-line session where you ran Liberty. Alternatively, you can run the ***liberty:stop*** goal from the ***finish*** directory in another shell session: + + +```bash +cd /home/project/guide-jms-intro/finish +mvn -pl inventory liberty:stop +mvn -pl system liberty:stop +``` + +::page{title="Creating the consumer in the inventory microservice"} + +Navigate to the ***start*** directory to begin. + +```bash +cd /home/project/guide-jms-intro/start +``` + +When you run Open Liberty in [dev mode](https://openliberty.io/docs/latest/development-mode.html), dev mode listens for file changes and automatically recompiles and deploys your updates whenever you save a new change. + +Run the following goal to start the ***inventory*** microservice in dev mode: + +```bash +mvn -pl inventory liberty:dev +``` + +When you see the following message, your Liberty instance is ready in dev mode: + +``` +************************************************************** +* Liberty is running in dev mode. +``` + +Dev mode holds your command-line session to listen for file changes. Open another command-line session to continue, or open the project in your editor. + +The ***inventory*** microservice records in its inventory the recent system load information that it received from potentially multiple instances of the ***system*** microservice. + +Create the ***InventoryQueueListener*** class. + +> Run the following touch command in your terminal +```bash +touch /home/project/guide-jms-intro/start/inventory/src/main/java/io/openliberty/guides/inventory/InventoryQueueListener.java +``` + + +> Then, to open the InventoryQueueListener.java file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/inventory/src/main/java/io/openliberty/guides/inventory/InventoryQueueListener.java, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/inventory/src/main/java/io/openliberty/guides/inventory/InventoryQueueListener.java"} + + + +```java +package io.openliberty.guides.inventory; + +import io.openliberty.guides.models.SystemLoad; +import jakarta.ejb.ActivationConfigProperty; +import jakarta.ejb.MessageDriven; +import jakarta.inject.Inject; +import jakarta.jms.JMSException; +import jakarta.jms.Message; +import jakarta.jms.MessageListener; +import jakarta.jms.TextMessage; + +import java.util.logging.Logger; + +@MessageDriven(activationConfig = { + @ActivationConfigProperty( + propertyName = "destinationLookup", propertyValue = "jms/InventoryQueue"), + @ActivationConfigProperty( + propertyName = "destinationType", propertyValue = "jakarta.jms.Queue") +}) +public class InventoryQueueListener implements MessageListener { + + private static Logger logger = + Logger.getLogger(InventoryQueueListener.class.getName()); + + @Inject + private InventoryManager manager; + + public void onMessage(Message message) { + try { + if (message instanceof TextMessage) { + TextMessage textMessage = (TextMessage) message; + String json = textMessage.getText(); + SystemLoad systemLoad = SystemLoad.fromJson(json); + + String hostname = systemLoad.hostname; + Double recentLoad = systemLoad.recentLoad; + if (manager.getSystem(hostname).isPresent()) { + manager.updateCpuStatus(hostname, recentLoad); + logger.info("Host " + hostname + " was updated: " + recentLoad); + } else { + manager.addSystem(hostname, recentLoad); + logger.info("Host " + hostname + " was added: " + recentLoad); + } + } else { + logger.warning( + "Unsupported Message Type: " + message.getClass().getName()); + } + } catch (JMSException e) { + e.printStackTrace(); + } + } + +} +``` + + +Click the :fa-copy: **copy** button to copy the code and press `Ctrl+V` or `Command+V` in the IDE to add the code to the file. + + +The ***inventory*** microservice receives the messages from the ***system*** microservice. Implement the ***InventoryQueueListener*** class with the ***MessageListener*** interface and annotate with ***@MessageDriven*** to monitor the ***jms/InventoryQueue*** message queue. Implement the ***onMessage()*** method that processes the incoming messages, updates the inventory by using the ***InventoryManager*** bean, and logs the action. Use the ***SystemLoad.fromJson()*** method to convert the JSON message string to the ***SystemLoad*** object. + +Next, configure the ***inventory*** microservice with an embedded messaging server and the [Messaging Server Client](https://openliberty.io/docs/latest/reference/feature/messagingClient-3.0.html) feature. + +Replace the inventory's ***server.xml*** configuration file. + +> To open the server.xml file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/inventory/src/main/liberty/config/server.xml, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/inventory/src/main/liberty/config/server.xml"} + + + +```xml + + + + restfulWS-3.1 + cdi-4.0 + jsonb-3.0 + mpHealth-4.0 + mpConfig-3.1 + messaging-3.1 + messagingServer-3.0 + messagingClient-3.0 + enterpriseBeansLite-4.0 + mdb-4.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + + + +The ***messagingServer*** feature enables a Liberty runtime to host an embedded messaging server to manage messaging destinations. The ***messagingClient*** feature enables applications to connect to a Liberty messaging server and access the messaging destinations hosted on that server through the Jakarta Messaging API that is enabled by the ***messaging*** feature. + +Add the ***wasJmsEndpoint*** element to configure the Liberty runtime to monitor and manage incoming JMS connections from any hosts. Set up the ***messagingEngine*** configuration to ensure that the Liberty runtime can manage incoming message queues more effectively, assigning a reliable and persistent destination for the ***InventoryQueue***. Configure a ***jmsConnectionFactory*** element to use the ***InventoryCM*** connection manager and set properties for the JMS implementation. Define a ***jmsQueue*** element for the ***InventoryQueue*** message queue with its JNDI name and a ***jmsActivationSpec*** element to configure properties, including the queue listener class name and maximum concurrency. + +To learn more about configuration for the ***jmsQueue*** element and ***jmsConnectionFactory*** element, see the [JMS Queue](https://openliberty.io/docs/latest/reference/config/jmsQueue.html) and [JMS Connection Factory](https://openliberty.io/docs/latest/reference/config/jmsConnectionFactory.html) documentation. + + +::page{title="Creating the message producer in the system service "} + +Open another command-line session, navigate to the ***start*** directory, and run the following goal to start the ***system*** microservice in dev mode: + +```bash +cd /home/project/guide-jms-intro/start +``` + +```bash +mvn -pl system liberty:dev +``` + +When you see the following message, your Liberty instance is ready in dev mode: + +``` +************************************************************** +* Liberty is running in dev mode. +``` + +The ***system*** microservice is the producer of the messages that are published to the messaging server as a stream of events. Every 15 seconds, the ***system*** microservice triggers an event that calculates the recent CPU usage for the last minute. + +Create the ***SystemService*** class. + +> Run the following touch command in your terminal +```bash +touch /home/project/guide-jms-intro/start/system/src/main/java/io/openliberty/guides/system/SystemService.java +``` + + +> Then, to open the SystemService.java file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/system/src/main/java/io/openliberty/guides/system/SystemService.java, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/system/src/main/java/io/openliberty/guides/system/SystemService.java"} + + + +```java +package io.openliberty.guides.system; + +import java.lang.management.ManagementFactory; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.logging.Logger; + +import com.sun.management.OperatingSystemMXBean; + +import io.openliberty.guides.models.SystemLoad; +import jakarta.annotation.Resource; +import jakarta.ejb.Schedule; +import jakarta.ejb.Singleton; +import jakarta.inject.Inject; +import jakarta.jms.JMSConnectionFactory; +import jakarta.jms.JMSContext; +import jakarta.jms.Queue; + +@Singleton +public class SystemService { + + private static final OperatingSystemMXBean OS_MEAN = + (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + private static String hostname = null; + + private static Logger logger = Logger.getLogger(SystemService.class.getName()); + + @Inject + @JMSConnectionFactory("InventoryConnectionFactory") + private JMSContext context; + + @Resource(lookup = "jms/InventoryQueue") + private Queue queue; + + private static String getHostname() { + if (hostname == null) { + try { + return InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + return System.getenv("HOSTNAME"); + } + } + return hostname; + } + + @Schedule(second = "*/15", minute = "*", hour = "*", persistent = false) + public void sendSystemLoad() { + SystemLoad systemLoad = new SystemLoad(getHostname(), + Double.valueOf(OS_MEAN.getCpuLoad())); + context.createProducer().send(queue, systemLoad.toString()); + logger.info(systemLoad.toString()); + } +} +``` + + +The ***SystemService*** class contains the ***sendSystemLoad()*** method that calculates the recent system load, creates a ***SystemLoad*** object, and publishes the object as a message to the ***jms/InventoryQueue*** message queue running in the messaging server by using the ***send()*** method. The ***@Schedule*** annotation on the ***sendSystemLoad()*** method sets the frequency at which the system service publishes the calculation to the event stream, ensuring it runs every 15 seconds. + + +Next, configure the ***system*** microservice to access the message queue. + +Replace the system's ***server.xml*** configuration file. + +> To open the server.xml file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/system/src/main/liberty/config/server.xml, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/system/src/main/liberty/config/server.xml"} + + + +```xml + + + + cdi-4.0 + jsonb-3.0 + mpHealth-4.0 + mpConfig-3.1 + messaging-3.1 + messagingClient-3.0 + enterpriseBeansLite-4.0 + mdb-4.0 + + + + + + + + + + + + + + + + + + + + + + + + +``` + + + + +The ***messaging*** and ***messagingClient*** features enable the Liberty runtime to provide the required messaging services. Add a ***connectionManager*** element to handle connections for the messaging server running on the ***inventory*** microservice. Define the ***jmsConnectionFactory*** element to use the ***InventoryCM*** connection manager and set up the required ***remoteServerAddress*** properties. Use the ***jmsQueue*** element to define the inventory message queue. + +In your dev mode console for the ***system*** microservice, type ***r*** and press ***enter/return*** key to restart the Liberty instance so that Liberty reads the configuration changes. When you see the following message, your Liberty instance is ready in dev mode: + +``` +************************************************************** +* Liberty is running in dev mode. +``` + + +::page{title="Running the application"} + +You started the Open Liberty in dev mode at the beginning of the guide, so all the changes were automatically picked up. + +You can find the ***inventory*** microservice at the following URLs: + + + ***http\://localhost:9081/inventory/systems*** + + +_To see the output for this URL in the IDE, run the following command at a terminal:_ + +```bash +curl -s http://localhost:9081/inventory/systems | jq +``` + + + +::page{title="Testing the inventory application"} + +While you can test your application manually, you should rely on automated tests because they trigger a failure whenever a code change introduces a defect. Because the application is a RESTful web service application, you can use JUnit and the RESTful web service Client API to write tests. In testing the functionality of the application, the scopes and dependencies are being tested. + +Create the ***InventoryEndpointIT*** class. + +> Run the following touch command in your terminal +```bash +touch /home/project/guide-jms-intro/start/inventory/src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java +``` + + +> Then, to open the InventoryEndpointIT.java file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/inventory/src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/inventory/src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java"} + + + +```java +package it.io.openliberty.guides.inventory; + +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestMethodOrder; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + + +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class InventoryEndpointIT { + + private static String port; + private static String baseUrl; + private static String hostname; + + private Client client; + + private final String INVENTORY_SYSTEMS = "inventory/systems"; + + @BeforeAll + public static void oneTimeSetup() { + port = System.getProperty("http.port"); + baseUrl = "http://localhost:" + port + "/"; + } + + @BeforeEach + public void setup() { + client = ClientBuilder.newClient(); + } + + @AfterEach + public void teardown() { + client.close(); + } + + + @Test + @Order(1) + public void testGetSystems() { + Response response = this.getResponse(baseUrl + INVENTORY_SYSTEMS); + this.assertResponse(baseUrl, response); + + JsonArray systems = response.readEntity(JsonArray.class); + + boolean hostnameExists = false; + boolean recentLoadExists = false; + for (int n = 0; n < systems.size(); n++) { + hostnameExists = systems.getJsonObject(n) + .get("hostname").toString().isEmpty(); + recentLoadExists = systems.getJsonObject(n) + .get("systemLoad").toString().isEmpty(); + + assertFalse(hostnameExists, "A host was registered, but it was empty"); + assertFalse(recentLoadExists, + "A recent system load was registered, but it was empty"); + if (!hostnameExists && !recentLoadExists) { + String host = systems.getJsonObject(n).get("hostname").toString(); + hostname = host.substring(1, host.length() - 1); + break; + } + } + assertNotNull(hostname, "Hostname should be set by the first test. (1)"); + response.close(); + } + + @Test + @Order(2) + public void testGetSystemsWithHost() { + assertNotNull(hostname, "Hostname should be set by the first test. (2)"); + + Response response = + this.getResponse(baseUrl + INVENTORY_SYSTEMS + "/" + hostname); + this.assertResponse(baseUrl, response); + + JsonObject system = response.readEntity(JsonObject.class); + + String responseHostname = system.getString("hostname"); + Boolean recentLoadExists = system.get("systemLoad").toString().isEmpty(); + + assertEquals(hostname, responseHostname, + "Hostname should match the one from the TestNonEmpty"); + assertFalse(recentLoadExists, "A recent system load should not be empty"); + + response.close(); + } + + @Test + @Order(3) + public void testUnknownHost() { + Response badResponse = + client.target(baseUrl + INVENTORY_SYSTEMS + "/" + "badhostname") + .request(MediaType.APPLICATION_JSON).get(); + + assertEquals(404, badResponse.getStatus(), + "BadResponse expected status: 404. Response code not as expected."); + + String stringObj = badResponse.readEntity(String.class); + assertTrue(stringObj.contains("hostname does not exist."), + "badhostname is not a valid host but it didn't raise an error"); + + badResponse.close(); + } + + private Response getResponse(String url) { + return client.target(url).request().get(); + } + + private void assertResponse(String url, Response response) { + assertEquals(200, response.getStatus(), "Incorrect response code from " + url); + } + +} +``` + + + + +See the following descriptions of the test cases: + +* ***testGetSystems()*** verifies that the hostname and the system load for each system in the inventory are not empty. + +* ***testGetSystemsWithHost()*** verifies that the hostname and system load returned by the ***system*** microservice match the ones stored in the ***inventory*** microservice and ensures they are not empty. + +* ***testUnknownHost()*** verifies that an unknown host or a host that does not expose their JVM system properties is correctly handled as an error. + + +### Running the tests + +Because you started Open Liberty in dev mode, you can run the tests by pressing the ***enter/return*** key from the command-line session where you started dev mode for the ***inventory*** microservice. + +If the tests pass, you see a similar output to the following example: + +``` +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running it.io.openliberty.guides.inventory.InventoryEndpointIT +Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.325 sec - in it.io.openliberty.guides.inventory.InventoryEndpointIT + +Results : + +Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 +``` + +When you are done checking out the application, stop the Liberty instances by pressing `Ctrl+C` in each command-line session where you ran the ***system*** and ***inventory*** microservices. + +::page{title="Using IBM MQ as the messaging server - Optional"} + +The application has been built and tested. In this section, you'll learn how to configure Liberty to use [IBM MQ container](https://github.com/ibm-messaging/mq-container) as the messaging server instead of the embedded Liberty Messaging Server. + + + +Start IBM MQ by running the following command on the command-line session: + +```bash +docker pull icr.io/ibm-messaging/mq:9.4.0.0-r3 + +docker volume create qm1data + +docker run \ +--env LICENSE=accept \ +--env MQ_QMGR_NAME=QM1 \ +--volume qm1data:/mnt/mqm \ +--publish 1414:1414 --publish 9443:9443 \ +--detach \ +--env MQ_APP_PASSWORD=passw0rd \ +--env MQ_ADMIN_PASSWORD=passw0rd \ +--rm \ +--platform linux/amd64 \ +--name QM1 \ +icr.io/ibm-messaging/mq:9.4.0.0-r3 +``` + + +Run the following command to make sure that the IBM MQ container is running: +```bash +docker ps +``` + +Replace the ***pom.xml*** file of the inventory service. + +> To open the pom.xml file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/inventory/pom.xml, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/inventory/pom.xml"} + + + +```xml + + + 4.0.0 + + io.openliberty.guides + guide-jms-intro-inventory + 1.0-SNAPSHOT + war + + + 17 + 17 + UTF-8 + UTF-8 + + 9081 + 9444 + + localhost + 1414 + DEV.APP.SVRCONN + QM1 + app + passw0rd + DEV.QUEUE.1 + + + + + + jakarta.platform + jakarta.jakartaee-api + 10.0.0 + provided + + + org.eclipse.microprofile + microprofile + 6.1 + pom + provided + + + + + io.openliberty.guides + guide-jms-intro-models + 1.0-SNAPSHOT + + + + org.junit.jupiter + junit-jupiter + 5.11.2 + test + + + org.jboss.resteasy + resteasy-client + 6.2.10.Final + test + + + org.jboss.resteasy + resteasy-json-binding-provider + 6.2.10.Final + test + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-war-plugin + 3.4.0 + + pom.xml + + + + + + io.openliberty.tools + liberty-maven-plugin + 3.11.1 + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.1 + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.1 + + + ${liberty.var.http.port} + ${liberty.var.https.port} + + + + + + integration-test + verify + + + + + + + +``` + + + + +Add the ***liberty.var.ibmmq-**** properties for the IBM MQ container. You can change to different values when you deploy the application on a production environment without modifying the Liberty ***server.xml*** configuration file. + + +Replace the ***server.xml*** file of the inventory service. + +> To open the server.xml file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/inventory/src/main/liberty/config/server.xml, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/inventory/src/main/liberty/config/server.xml"} + + + +```xml + + + + restfulWS-3.1 + cdi-4.0 + jsonb-3.0 + mpHealth-4.0 + mpConfig-3.1 + messaging-3.1 + messagingClient-3.0 + messagingServer-3.0 + enterpriseBeansLite-4.0 + mdb-4.0 + + + + + + + + + + + + + + + + + + + + + + + + +``` + + + + +Refine the ***jmsQueue*** and ***jmsActivationSpec*** configurations with the variables for IBM MQ settings. Add the ***resourceAdapter*** element to define the RAR file that provides the IBM MQ classes for Java and JMS. Note that the ***messagingEngine*** and ***jmsConnectionFactory*** configurations are removed from the configuration because they are no longer required. + +Replace the ***pom.xml*** file of the system service. + +> To open the pom.xml file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/system/pom.xml, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/system/pom.xml"} + + + +```xml + + + 4.0.0 + + io.openliberty.guides + guide-jms-intro-system + 1.0-SNAPSHOT + war + + + 17 + 17 + UTF-8 + UTF-8 + + 9082 + 9445 + localhost + 7277 + + localhost + 1414 + DEV.APP.SVRCONN + QM1 + app + passw0rd + DEV.QUEUE.1 + + + + + + jakarta.platform + jakarta.jakartaee-api + 10.0.0 + provided + + + org.eclipse.microprofile + microprofile + 6.1 + pom + provided + + + + io.openliberty.guides + guide-jms-intro-models + 1.0-SNAPSHOT + + + org.slf4j + slf4j-api + 2.0.16 + + + org.slf4j + slf4j-simple + 2.0.16 + + + + org.junit.jupiter + junit-jupiter + 5.11.2 + test + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-war-plugin + 3.4.0 + + pom.xml + + + + + + io.openliberty.tools + liberty-maven-plugin + 3.11.1 + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.1 + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.1 + + + integration-test + + integration-test + + + false + + + + verify + + verify + + + + + + + +``` + + + + +Add the ***liberty.var.ibmmq-**** properties for the IBM MQ container as you did for the ***inventory*** microservice previously. + + +Replace the ***server.xml*** file of the system service. + +> To open the server.xml file in your IDE, select +> **File** > **Open** > guide-jms-intro/start/system/src/main/liberty/config/server.xml, or click the following button + +::openFile{path="/home/project/guide-jms-intro/start/system/src/main/liberty/config/server.xml"} + + + +```xml + + + + cdi-4.0 + jsonb-3.0 + mpHealth-4.0 + mpConfig-3.1 + messaging-3.1 + messagingClient-3.0 + enterpriseBeansLite-4.0 + mdb-4.0 + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + + + +Replace the ***properties.wasJms*** configuration by the ***properties.wmqjmsra*** configuration. All property values are defined in the ***pom.xml*** file that you replaced. Also, modify the ***jmsQueue*** property to set the ***baseQueueName*** value with the ***${ibmmq-inventory-queue-name}*** variable. Add the ***resourceAdapter*** element like you did for the ***inventory*** microservice. + + +Start the ***inventory*** microservice by running the following command in dev mode: + + +```bash +cd /home/project/guide-jms-intro/start +mvn -pl inventory liberty:dev +``` + +Next, open another command-line session, navigate to the ***start*** directory, and start the ***system*** microservice by using the following command: + + +```bash +cd /home/project/guide-jms-intro/start +mvn -pl system liberty:dev +``` + +When you see the following message, your Liberty instances are ready in dev mode: + +``` +The defaultServer server is ready to run a smarter planet. +``` + + +You can access the ***inventory*** microservice by the ***http\://localhost:9081/inventory/systems*** URL. + + +_To see the output for this URL in the IDE, run the following command at a terminal:_ + +```bash +curl -s http://localhost:9081/inventory/systems | jq +``` + + + +In the command shell where ***inventory*** dev mode is running, press ***enter/return*** to run the tests. If the tests pass, you'll see output that is similar to the following example: + +``` +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running it.io.openliberty.guides.inventory.InventoryEndpointIT +Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.325 sec - in it.io.openliberty.guides.inventory.InventoryEndpointIT + +Results : + +Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 +``` + +After you are finished checking out the application, stop the Liberty instances by pressing `Ctrl+C` in the command-line sessions where you ran the ***system*** and ***inventory*** microservices. + +Run the following commands to stop the running IBM MQ container and clean up the ***qm1data*** volume: + +```bash +docker stop QM1 +docker rm QM1 +docker volume remove qm1data +``` + +::page{title="Summary"} + +### Nice Work! + +You just developed a Java cloud-native application that uses Jakarta Messaging to produce and consume messages in Open Liberty. + + + +### Clean up your environment + + +Clean up your online environment so that it is ready to be used with the next guide: + +Delete the ***guide-jms-intro*** project by running the following commands: + +```bash +cd /home/project +rm -fr guide-jms-intro +``` + +### What did you think of this guide? + +We want to hear from you. To provide feedback, click the following link. + +* [Give us feedback](https://openliberty.skillsnetwork.site/thanks-for-completing-our-content?guide-name=Producing%20and%20consuming%20messages%20in%20Java%20microservices&guide-id=cloud-hosted-guide-jms-intro) + +Or, click the **Support/Feedback** button in the IDE and select the **Give feedback** option. Fill in the fields, choose the **General** category, and click the **Post Idea** button. + +### What could make this guide better? + +You can also provide feedback or contribute to this guide from GitHub. +* [Raise an issue to share feedback.](https://github.com/OpenLiberty/guide-jms-intro/issues) +* [Create a pull request to contribute to this guide.](https://github.com/OpenLiberty/guide-jms-intro/pulls) + + + +### Where to next? + +* [Bidirectional communication between services using Jakarta WebSocket](https://openliberty.io/guides/jakarta-websocket.html) + + +### Log out of the session + +Log out of the cloud-hosted guides by selecting **Account** :fa-user: > **Logout** from the Skills Network left-sided menu.