From f59383e06d678ed89716a7c831b727f88a01433d Mon Sep 17 00:00:00 2001 From: Stuti Uniyal Date: Fri, 4 Jul 2025 14:03:51 +0530 Subject: [PATCH 1/2] add base java samples --- base-java/Readme.md | 124 ++++++++++++++++ base-java/pom.xml | 55 ++++++++ .../com/ibm/mq/samples/java/BasicGet.java | 133 ++++++++++++++++++ .../com/ibm/mq/samples/java/BasicPub.java | 128 +++++++++++++++++ .../com/ibm/mq/samples/java/BasicPut.java | 122 ++++++++++++++++ .../com/ibm/mq/samples/java/BasicRequest.java | 123 ++++++++++++++++ .../ibm/mq/samples/java/BasicResponse.java | 121 ++++++++++++++++ .../com/ibm/mq/samples/java/BasicSub.java | 133 ++++++++++++++++++ 8 files changed, 939 insertions(+) create mode 100644 base-java/Readme.md create mode 100644 base-java/pom.xml create mode 100644 base-java/src/main/java/com/ibm/mq/samples/java/BasicGet.java create mode 100644 base-java/src/main/java/com/ibm/mq/samples/java/BasicPub.java create mode 100644 base-java/src/main/java/com/ibm/mq/samples/java/BasicPut.java create mode 100644 base-java/src/main/java/com/ibm/mq/samples/java/BasicRequest.java create mode 100644 base-java/src/main/java/com/ibm/mq/samples/java/BasicResponse.java create mode 100644 base-java/src/main/java/com/ibm/mq/samples/java/BasicSub.java diff --git a/base-java/Readme.md b/base-java/Readme.md new file mode 100644 index 00000000..3fd7bb90 --- /dev/null +++ b/base-java/Readme.md @@ -0,0 +1,124 @@ +# IBM MQ Base Java Samples + +This project provides a set of base Java samples for interacting with IBM MQ using the IBM MQ classes for Java (non-JMS). These include basic examples for put/get, publish/subscribe, and request/response messaging patterns. + +## Samples Included + +Each sample is located under: + +``` +src/main/java/com/ibm/mq/samples/java/ +``` + +- `BasicPut.java` – Puts a message onto a queue +- `BasicGet.java` – Gets a message from a queue +- `BasicPub.java` – Publishes a message to a topic +- `BasicSub.java` – Subscribes and receives messages from a topic +- `BasicRequest.java` – Sends a message with a dynamic reply-to queue +- `BasicResponse.java` – Responds to requests received from a queue + +## Prerequisites + +- Java 8 or higher +- Apache Maven +- IBM MQ installed and running (locally or remotely) + +## Project Setup + +This is a standard Maven project. All dependencies and build instructions are managed through `pom.xml`. + +### Building the Project + +To build the project and download dependencies: + +```bash +mvn clean package +``` +## Running the Samples + +Ensure that your environment configuration file (`env.json`) is properly set up. Example: + +```json +{ + "MQ_ENDPOINTS": [ + { + "QMGR": "QM1", + "HOST": "localhost", + "PORT": 1414, + "CHANNEL": "DEV.APP.SVRCONN", + "APP_USER": "app", + "APP_PASSWORD": "passw0rd", + "QUEUE_NAME": "DEV.QUEUE.1", + "BACKOUT_QUEUE": "DEV.QUEUE.2", + "MODEL_QUEUE_NAME": "DEV.APP.MODEL.QUEUE", + "DYNAMIC_QUEUE_PREFIX": "APP.REPLIES.*", + "TOPIC_NAME": "dev/" + } + ] +} +``` +## Using a CCDT File + +Instead of manually specifying connection parameters in `env.json`, you can use a **Client Channel Definition Table (CCDT)** JSON file to define connection configurations. This is useful when connecting to IBM MQ instances in cloud or enterprise environments. + +Set the environment variable `MQCCDTURL` to point to the CCDT file: + +```bash +export MQCCDTURL=file:/absolute/path/to/ccdt.json +``` + +> **Note (Windows):** Use `set` instead of `export`: +> +> ```cmd +> set MQCCDTURL=file:C:\path\to\ccdt.json +> ``` + +The sample will detect `MQCCDTURL` and automatically use it for connection settings. When `MQCCDTURL` is set and starts with `file://`, the program prioritizes CCDT-based configuration and skips `host`, `channel`, and `port` in `env.json`. + +Make sure your CCDT file defines the appropriate connection information such as **channel name**, **queue manager**, and **connection name list**. + + +## Run Instructions + +### Put/Get + +```bash +mvn exec:java -Dexec.mainClass="com.ibm.mq.samples.java.BasicPut" -Dexec.args="env.json" +mvn exec:java -Dexec.mainClass="com.ibm.mq.samples.java.BasicGet" -Dexec.args="env.json" +``` + +### Publish/Subscribe + +In the **first terminal (subscriber)**: + +```bash +mvn exec:java -Dexec.mainClass="com.ibm.mq.samples.java.BasicSub" -Dexec.args="env.json" +``` + +In the **second terminal (publisher)**: + +```bash +mvn exec:java -Dexec.mainClass="com.ibm.mq.samples.java.BasicPub" -Dexec.args="env.json" +``` + +### Request/Response + +In the **first terminal (response)**: + +```bash +mvn exec:java -Dexec.mainClass="com.ibm.mq.samples.java.BasicResponse" -Dexec.args="env.json" +``` + +In the **second terminal (request)**: + +```bash +mvn exec:java -Dexec.mainClass="com.ibm.mq.samples.java.BasicRequest" -Dexec.args="env.json" +``` + +## Notes + +- The environment can be configured using either `env.json` or a CCDT file via the `MQCCDTURL` environment variable. +- Each sample reads from the provided `env.json` to extract connection information for the queue manager. +- Samples like `BasicResponse` and `BasicSub` are long-running and wait for messages indefinitely until stopped. +- Make sure all relevant queues and topics are pre-created in your IBM MQ queue manager. + diff --git a/base-java/pom.xml b/base-java/pom.xml new file mode 100644 index 00000000..7932c5d4 --- /dev/null +++ b/base-java/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + + com.ibm.mq.samples + mq-java-base-consumer + 1.0.0 + jar + + + 1.8 + 1.8 + + + + + + com.ibm.mq + com.ibm.mq.allclient + 9.4.3.0 + + + + + org.json + json + 20240303 + + + + + + + maven-compiler-plugin + 3.8.1 + + 1.8 + + + + + + + + + + + + + + + + diff --git a/base-java/src/main/java/com/ibm/mq/samples/java/BasicGet.java b/base-java/src/main/java/com/ibm/mq/samples/java/BasicGet.java new file mode 100644 index 00000000..e7a77783 --- /dev/null +++ b/base-java/src/main/java/com/ibm/mq/samples/java/BasicGet.java @@ -0,0 +1,133 @@ +package com.ibm.mq.samples.java; + +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; +import org.json.*; + +import java.io.FileReader; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Hashtable; + +public class BasicGet { + + private static class MQDetails { + String QMGR; + String QUEUE_NAME; + String HOST; + String PORT; + String CHANNEL; + String USER; + String PASSWORD; + String KEY_REPOSITORY; + String CIPHER; + } + + private static JSONArray endpoints; + + public static void main(String[] args) { + loadEnv("env.json"); + + for (int i = 0; i < endpoints.length(); i++) { + System.out.println("Processing endpoint " + i); + JSONObject point = endpoints.getJSONObject(i); + MQDetails details = buildMQDetails(point); + processEndpoint(details); + } + + System.out.println("Sample MQ GET application ending"); + } + + private static void loadEnv(String path) { + try { + String content = new String(Files.readAllBytes(Paths.get(path))); + JSONObject env = new JSONObject(content); + endpoints = env.getJSONArray("MQ_ENDPOINTS"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static MQDetails buildMQDetails(JSONObject endpoint) { + MQDetails mq = new MQDetails(); + mq.QMGR = endpoint.getString("QMGR"); + mq.QUEUE_NAME = endpoint.getString("QUEUE_NAME"); + mq.HOST = endpoint.getString("HOST"); + mq.PORT = String.valueOf(endpoint.getInt("PORT")); + mq.CHANNEL = endpoint.getString("CHANNEL"); + mq.USER = endpoint.getString("APP_USER"); + mq.PASSWORD = endpoint.getString("APP_PASSWORD"); + mq.KEY_REPOSITORY = endpoint.optString("KEY_REPOSITORY", ""); + mq.CIPHER = endpoint.optString("CIPHER", ""); + return mq; + } + + private static void processEndpoint(MQDetails details) { + MQQueueManager qMgr = null; + MQQueue queue = null; + + try { + Hashtable props = new Hashtable<>(); + String ccdtUrl = System.getenv("MQCCDTURL"); + + if (ccdtUrl != null && ccdtUrl.startsWith("file://")) { + String ccdtPath = ccdtUrl.replace("file://", ""); + System.setProperty("MQCCDTURL", ccdtPath); + System.out.println("Using CCDT at: " + ccdtPath); + } else { + props.put(MQConstants.HOST_NAME_PROPERTY, details.HOST); + props.put(MQConstants.PORT_PROPERTY, Integer.parseInt(details.PORT)); + props.put(MQConstants.CHANNEL_PROPERTY, details.CHANNEL); + } + + props.put(MQConstants.USER_ID_PROPERTY, details.USER); + props.put(MQConstants.PASSWORD_PROPERTY, details.PASSWORD); + props.put(MQConstants.TRANSPORT_PROPERTY, MQConstants.TRANSPORT_MQSERIES_CLIENT); + + if (!details.KEY_REPOSITORY.isEmpty()) { + props.put(MQConstants.SSL_CIPHER_SUITE_PROPERTY, details.CIPHER); + System.setProperty("com.ibm.mq.ssl.keyStore", details.KEY_REPOSITORY); + System.setProperty("com.ibm.mq.ssl.keyStorePassword", ""); + } + + qMgr = new MQQueueManager(details.QMGR, props); + System.out.println("Connected to queue manager: " + details.QMGR); + + int openOptions = MQConstants.MQOO_INPUT_AS_Q_DEF; + queue = qMgr.accessQueue(details.QUEUE_NAME, openOptions); + + boolean keepReading = true; + while (keepReading) { + MQMessage msg = new MQMessage(); + MQGetMessageOptions gmo = new MQGetMessageOptions(); + gmo.options = MQConstants.MQGMO_NO_WAIT | + MQConstants.MQGMO_CONVERT | + MQConstants.MQGMO_FAIL_IF_QUIESCING; + + try { + queue.get(msg, gmo); + String str = msg.readStringOfByteLength(msg.getDataLength()); + System.out.println("Received message: " + str); + } catch (MQException mqe) { + if (mqe.reasonCode == MQConstants.MQRC_NO_MSG_AVAILABLE) { + keepReading = false; + System.out.println("No more messages."); + } else { + System.err.println("Error retrieving message: " + mqe); + keepReading = false; + } + } + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (queue != null) queue.close(); + if (qMgr != null) qMgr.disconnect(); + } catch (MQException me) { + me.printStackTrace(); + } + } + } +} diff --git a/base-java/src/main/java/com/ibm/mq/samples/java/BasicPub.java b/base-java/src/main/java/com/ibm/mq/samples/java/BasicPub.java new file mode 100644 index 00000000..d0748ba7 --- /dev/null +++ b/base-java/src/main/java/com/ibm/mq/samples/java/BasicPub.java @@ -0,0 +1,128 @@ +package com.ibm.mq.samples.java; +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; +import org.json.*; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Hashtable; + +public class BasicPub { + + private static class MQDetails { + String QMGR; + String TOPIC_NAME; + String HOST; + String PORT; + String CHANNEL; + String USER; + String PASSWORD; + String KEY_REPOSITORY; + String CIPHER; + } + + private static MQDetails mqDetails; + + public static void main(String[] args) { + loadEnv("env.json"); + publishToTopic(mqDetails); + System.out.println("Sample MQ PUB application ending"); + } + + private static void loadEnv(String path) { + try { + String content = new String(Files.readAllBytes(Paths.get(path))); + JSONObject env = new JSONObject(content); + JSONObject endpoint = env.getJSONArray("MQ_ENDPOINTS").getJSONObject(0); + + mqDetails = new MQDetails(); + mqDetails.QMGR = endpoint.getString("QMGR"); + mqDetails.TOPIC_NAME = endpoint.getString("TOPIC_NAME"); + mqDetails.HOST = endpoint.getString("HOST"); + mqDetails.PORT = String.valueOf(endpoint.getInt("PORT")); + mqDetails.CHANNEL = endpoint.getString("CHANNEL"); + mqDetails.USER = endpoint.getString("APP_USER"); + mqDetails.PASSWORD = endpoint.getString("APP_PASSWORD"); + mqDetails.KEY_REPOSITORY = endpoint.optString("KEY_REPOSITORY", ""); + mqDetails.CIPHER = endpoint.optString("CIPHER", ""); + + + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void publishToTopic(MQDetails d) { + MQQueueManager qMgr = null; + MQTopic topic = null; + + try { + Hashtable props = new Hashtable<>(); + + String ccdtUrl = System.getenv("MQCCDTURL"); + if (ccdtUrl != null && ccdtUrl.startsWith("file://")) { + String ccdtPath = ccdtUrl.replace("file://", ""); + System.setProperty("MQCCDTURL", ccdtPath); + System.out.println("Using CCDT at: " + ccdtPath); + } else { + props.put(MQConstants.HOST_NAME_PROPERTY, d.HOST); + props.put(MQConstants.PORT_PROPERTY, Integer.parseInt(d.PORT)); + props.put(MQConstants.CHANNEL_PROPERTY, d.CHANNEL); + } + + props.put(MQConstants.USER_ID_PROPERTY, d.USER); + props.put(MQConstants.PASSWORD_PROPERTY, d.PASSWORD); + props.put(MQConstants.TRANSPORT_PROPERTY, MQConstants.TRANSPORT_MQSERIES_CLIENT); + + if (!d.KEY_REPOSITORY.isEmpty()) { + props.put(MQConstants.SSL_CIPHER_SUITE_PROPERTY, d.CIPHER); + System.setProperty("com.ibm.mq.ssl.keyStore", d.KEY_REPOSITORY); + System.setProperty("com.ibm.mq.ssl.keyStorePassword", ""); + } + + qMgr = new MQQueueManager(d.QMGR, props); + System.out.println("Connected to queue manager: " + d.QMGR); + + // Access using topic object name, not just string + topic = qMgr.accessTopic( + d.TOPIC_NAME, + null, // Topic Object defined in MQ + MQConstants.MQTOPIC_OPEN_AS_PUBLICATION, + MQConstants.MQOO_OUTPUT + ); + + MQMessage msg = new MQMessage(); + msg.format = MQConstants.MQFMT_STRING; + + String payload = "{\"Greeting\": \"Hello from Java publisher at " + java.time.Instant.now() + "\"}"; + msg.writeString(payload); + + MQPutMessageOptions pmo = new MQPutMessageOptions(); + pmo.options = MQConstants.MQPMO_NO_SYNCPOINT | + MQConstants.MQPMO_NEW_MSG_ID | + MQConstants.MQPMO_NEW_CORREL_ID | + MQConstants.MQPMO_WARN_IF_NO_SUBS_MATCHED; + + topic.put(msg, pmo); + + //System.out.println("Published message to topic object: DEV.BASE.TOPIC"); + System.out.println("Message content: " + payload); + + } catch (MQException mqe) { + if (mqe.reasonCode == MQConstants.MQRC_NO_SUBS_MATCHED) { + System.out.println("Warning: No subscribers matched the topic."); + } else { + mqe.printStackTrace(); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (topic != null) topic.close(); + if (qMgr != null) qMgr.disconnect(); + } catch (MQException me) { + me.printStackTrace(); + } + } + } +} diff --git a/base-java/src/main/java/com/ibm/mq/samples/java/BasicPut.java b/base-java/src/main/java/com/ibm/mq/samples/java/BasicPut.java new file mode 100644 index 00000000..c87bcb0a --- /dev/null +++ b/base-java/src/main/java/com/ibm/mq/samples/java/BasicPut.java @@ -0,0 +1,122 @@ +package com.ibm.mq.samples.java; +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; +import org.json.*; + +import java.io.FileReader; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Hashtable; + +public class BasicPut { + + private static class MQDetails { + String QMGR; + String QUEUE_NAME; + String HOST; + String PORT; + String CHANNEL; + String USER; + String PASSWORD; + String KEY_REPOSITORY; + String CIPHER; + } + + private static JSONArray endpoints; + + public static void main(String[] args) { + loadEnv("env.json"); + + for (int i = 0; i < endpoints.length(); i++) { + System.out.println("Processing endpoint " + i); + JSONObject point = endpoints.getJSONObject(i); + MQDetails details = buildMQDetails(point); + processEndpoint(details); + } + + System.out.println("Sample MQ PUT application ending"); + System.exit(0); + } + + private static void loadEnv(String path) { + try { + String content = new String(Files.readAllBytes(Paths.get(path))); + JSONObject env = new JSONObject(content); + endpoints = env.getJSONArray("MQ_ENDPOINTS"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static MQDetails buildMQDetails(JSONObject endpoint) { + MQDetails mq = new MQDetails(); + mq.QMGR = endpoint.getString("QMGR"); + mq.QUEUE_NAME = endpoint.getString("QUEUE_NAME"); + mq.HOST = endpoint.getString("HOST"); + mq.PORT = String.valueOf(endpoint.getInt("PORT")); + mq.CHANNEL = endpoint.getString("CHANNEL"); + mq.USER = endpoint.getString("APP_USER"); + mq.PASSWORD = endpoint.getString("APP_PASSWORD"); + mq.KEY_REPOSITORY = endpoint.optString("KEY_REPOSITORY", ""); + mq.CIPHER = endpoint.optString("CIPHER", ""); + return mq; + } + + private static void processEndpoint(MQDetails details) { + MQQueueManager qMgr = null; + MQQueue queue = null; + + try { + Hashtable props = new Hashtable<>(); + String ccdtUrl = System.getenv("MQCCDTURL"); + + if (ccdtUrl != null && ccdtUrl.startsWith("file://")) { + String ccdtPath = ccdtUrl.replace("file://", ""); + System.setProperty("MQCCDTURL", ccdtPath); + System.out.println("Using CCDT at: " + ccdtPath); + } else { + props.put(MQConstants.HOST_NAME_PROPERTY, details.HOST); + props.put(MQConstants.PORT_PROPERTY, Integer.parseInt(details.PORT)); + props.put(MQConstants.CHANNEL_PROPERTY, details.CHANNEL); + } + + props.put(MQConstants.USER_ID_PROPERTY, details.USER); + props.put(MQConstants.PASSWORD_PROPERTY, details.PASSWORD); + props.put(MQConstants.TRANSPORT_PROPERTY, MQConstants.TRANSPORT_MQSERIES_CLIENT); + + if (!details.KEY_REPOSITORY.isEmpty()) { + props.put(MQConstants.SSL_CIPHER_SUITE_PROPERTY, details.CIPHER); + System.setProperty("com.ibm.mq.ssl.keyStore", details.KEY_REPOSITORY); + System.setProperty("com.ibm.mq.ssl.keyStorePassword", ""); + } + + qMgr = new MQQueueManager(details.QMGR, props); + System.out.println("Connected to queue manager: " + details.QMGR); + + int openOptions = MQConstants.MQOO_OUTPUT; + queue = qMgr.accessQueue(details.QUEUE_NAME, openOptions); + + MQMessage msg = new MQMessage(); + msg.format = MQConstants.MQFMT_STRING; + + // Hardcoded message body for simplicity + String payload = "{\"greeting\": \"Hello from BasicPut.java\"}"; + msg.writeString(payload); + + MQPutMessageOptions pmo = new MQPutMessageOptions(); + queue.put(msg, pmo); + + System.out.println("Message put successfully: " + payload); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (queue != null) queue.close(); + if (qMgr != null) qMgr.disconnect(); + } catch (MQException me) { + me.printStackTrace(); + } + } + } +} diff --git a/base-java/src/main/java/com/ibm/mq/samples/java/BasicRequest.java b/base-java/src/main/java/com/ibm/mq/samples/java/BasicRequest.java new file mode 100644 index 00000000..3b458cab --- /dev/null +++ b/base-java/src/main/java/com/ibm/mq/samples/java/BasicRequest.java @@ -0,0 +1,123 @@ +package com.ibm.mq.samples.java; +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; +import org.json.JSONObject; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.Instant; +import java.util.Hashtable; + +public class BasicRequest { + + static class MQDetails { + String QMGR; + String HOST; + int PORT; + String CHANNEL; + String APP_USER; + String APP_PASSWORD; + String QUEUE_NAME; + String MODEL_QUEUE_NAME; + String DYNAMIC_QUEUE_PREFIX; + } + + static MQDetails mqDetails; + + public static void main(String[] args) { + loadEnv("env.json"); + sendRequestAndReceiveReply(mqDetails); + System.out.println("Sample MQ requester application ending"); + } + + private static void loadEnv(String path) { + try { + String content = new String(Files.readAllBytes(Paths.get(path))); + JSONObject endpoint = new JSONObject(content) + .getJSONArray("MQ_ENDPOINTS").getJSONObject(0); + + mqDetails = new MQDetails(); + mqDetails.QMGR = endpoint.getString("QMGR"); + mqDetails.HOST = endpoint.getString("HOST"); + mqDetails.PORT = endpoint.getInt("PORT"); + mqDetails.CHANNEL = endpoint.getString("CHANNEL"); + mqDetails.APP_USER = endpoint.getString("APP_USER"); + mqDetails.APP_PASSWORD = endpoint.getString("APP_PASSWORD"); + mqDetails.QUEUE_NAME = endpoint.getString("QUEUE_NAME"); + mqDetails.MODEL_QUEUE_NAME = endpoint.getString("MODEL_QUEUE_NAME"); + mqDetails.DYNAMIC_QUEUE_PREFIX = endpoint.getString("DYNAMIC_QUEUE_PREFIX"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void sendRequestAndReceiveReply(MQDetails d) { + MQQueueManager qMgr = null; + MQQueue requestQueue = null; + MQQueue replyQueue = null; + + try { + Hashtable props = new Hashtable<>(); + props.put(MQConstants.HOST_NAME_PROPERTY, d.HOST); + props.put(MQConstants.PORT_PROPERTY, d.PORT); + props.put(MQConstants.CHANNEL_PROPERTY, d.CHANNEL); + props.put(MQConstants.USER_ID_PROPERTY, d.APP_USER); + props.put(MQConstants.PASSWORD_PROPERTY, d.APP_PASSWORD); + props.put(MQConstants.TRANSPORT_PROPERTY, MQConstants.TRANSPORT_MQSERIES_CLIENT); + + qMgr = new MQQueueManager(d.QMGR, props); + System.out.println("Connected to queue manager: " + d.QMGR); + + replyQueue = qMgr.accessQueue( + d.MODEL_QUEUE_NAME, + MQConstants.MQOO_INPUT_EXCLUSIVE, + null, + d.DYNAMIC_QUEUE_PREFIX, + null + ); + String dynamicReplyQueueName = replyQueue.getName(); + System.out.println("Opened dynamic reply-to queue: " + dynamicReplyQueueName); + + requestQueue = qMgr.accessQueue(d.QUEUE_NAME, MQConstants.MQOO_OUTPUT); + + MQMessage request = new MQMessage(); + request.format = MQConstants.MQFMT_STRING; + request.replyToQueueName = dynamicReplyQueueName; + request.messageType = MQConstants.MQMT_REQUEST; + + String payload = "{\"Greeting\": \"Hello from Java Requester at " + Instant.now() + "\"}"; + request.writeString(payload); + + MQPutMessageOptions pmo = new MQPutMessageOptions(); + pmo.options = MQConstants.MQPMO_NO_SYNCPOINT; + + requestQueue.put(request, pmo); + System.out.println("Sent request message to queue: " + d.QUEUE_NAME); + System.out.println("Waiting for reply on: " + dynamicReplyQueueName); + + MQMessage response = new MQMessage(); + MQGetMessageOptions gmo = new MQGetMessageOptions(); + gmo.options = MQConstants.MQGMO_WAIT | MQConstants.MQGMO_CONVERT; + gmo.waitInterval = 10000; + + replyQueue.get(response, gmo); + String replyText = response.readStringOfByteLength(response.getDataLength()); + System.out.println("Received reply: " + replyText); + + } catch (MQException mqe) { + System.err.println("MQ Error - Completion Code: " + mqe.completionCode + + " Reason Code: " + mqe.reasonCode); + mqe.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (requestQueue != null) requestQueue.close(); + if (replyQueue != null) replyQueue.close(); + if (qMgr != null) qMgr.disconnect(); + } catch (MQException e) { + e.printStackTrace(); + } + } + } +} diff --git a/base-java/src/main/java/com/ibm/mq/samples/java/BasicResponse.java b/base-java/src/main/java/com/ibm/mq/samples/java/BasicResponse.java new file mode 100644 index 00000000..81234635 --- /dev/null +++ b/base-java/src/main/java/com/ibm/mq/samples/java/BasicResponse.java @@ -0,0 +1,121 @@ +package com.ibm.mq.samples.java; +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; +import org.json.JSONObject; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Hashtable; + +public class BasicResponse { + + static class MQDetails { + String QMGR; + String HOST; + int PORT; + String CHANNEL; + String APP_USER; + String APP_PASSWORD; + String QUEUE_NAME; + } + + static MQDetails mqDetails; + + public static void main(String[] args) { + loadEnv("env.json"); + listenAndRespond(mqDetails); + System.out.println("Sample MQ responder application ending"); + } + + private static void loadEnv(String path) { + try { + String content = new String(Files.readAllBytes(Paths.get(path))); + JSONObject endpoint = new JSONObject(content) + .getJSONArray("MQ_ENDPOINTS").getJSONObject(0); + + mqDetails = new MQDetails(); + mqDetails.QMGR = endpoint.getString("QMGR"); + mqDetails.HOST = endpoint.getString("HOST"); + mqDetails.PORT = endpoint.getInt("PORT"); + mqDetails.CHANNEL = endpoint.getString("CHANNEL"); + mqDetails.APP_USER = endpoint.getString("APP_USER"); + mqDetails.APP_PASSWORD = endpoint.getString("APP_PASSWORD"); + mqDetails.QUEUE_NAME = endpoint.getString("QUEUE_NAME"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void listenAndRespond(MQDetails d) { + MQQueueManager qMgr = null; + MQQueue requestQueue = null; + + try { + Hashtable props = new Hashtable<>(); + props.put(MQConstants.HOST_NAME_PROPERTY, d.HOST); + props.put(MQConstants.PORT_PROPERTY, d.PORT); + props.put(MQConstants.CHANNEL_PROPERTY, d.CHANNEL); + props.put(MQConstants.USER_ID_PROPERTY, d.APP_USER); + props.put(MQConstants.PASSWORD_PROPERTY, d.APP_PASSWORD); + props.put(MQConstants.TRANSPORT_PROPERTY, MQConstants.TRANSPORT_MQSERIES_CLIENT); + + qMgr = new MQQueueManager(d.QMGR, props); + System.out.println("Connected to queue manager: " + d.QMGR); + + requestQueue = qMgr.accessQueue( + d.QUEUE_NAME, + MQConstants.MQOO_INPUT_AS_Q_DEF | MQConstants.MQOO_OUTPUT + ); + + MQGetMessageOptions gmo = new MQGetMessageOptions(); + gmo.options = MQConstants.MQGMO_WAIT | MQConstants.MQGMO_CONVERT; + gmo.waitInterval = 10000; + + while (true) { + MQMessage request = new MQMessage(); + try { + requestQueue.get(request, gmo); + String msgText = request.readStringOfByteLength(request.getDataLength()); + System.out.println("Received request: " + msgText); + + String replyToQueueName = request.replyToQueueName; + if (replyToQueueName != null && !replyToQueueName.isEmpty()) { + MQQueue replyQueue = qMgr.accessQueue(replyToQueueName, MQConstants.MQOO_OUTPUT); + + MQMessage reply = new MQMessage(); + reply.format = MQConstants.MQFMT_STRING; + reply.correlationId = request.messageId; + + JSONObject replyJson = new JSONObject(); + replyJson.put("Response", "Hello from Java Responder!"); + reply.writeString(replyJson.toString()); + + MQPutMessageOptions pmo = new MQPutMessageOptions(); + pmo.options = MQConstants.MQPMO_NO_SYNCPOINT; + + replyQueue.put(reply, pmo); + System.out.println("Sent reply to: " + replyToQueueName); + replyQueue.close(); + } + } catch (MQException mqe) { + if (mqe.reasonCode == MQConstants.MQRC_NO_MSG_AVAILABLE) { + System.out.println("No message received. Exiting."); + break; + } else { + throw mqe; + } + } + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (requestQueue != null) requestQueue.close(); + if (qMgr != null) qMgr.disconnect(); + } catch (MQException e) { + e.printStackTrace(); + } + } + } +} diff --git a/base-java/src/main/java/com/ibm/mq/samples/java/BasicSub.java b/base-java/src/main/java/com/ibm/mq/samples/java/BasicSub.java new file mode 100644 index 00000000..b517a6b1 --- /dev/null +++ b/base-java/src/main/java/com/ibm/mq/samples/java/BasicSub.java @@ -0,0 +1,133 @@ +package com.ibm.mq.samples.java; +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; +import org.json.*; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Hashtable; + +public class BasicSub { + + private static class MQDetails { + String QMGR; + String SUB_NAME; + String QUEUE_NAME; + String HOST; + String PORT; + String CHANNEL; + String USER; + String PASSWORD; + String KEY_REPOSITORY; + String CIPHER; + } + + private static MQDetails mqDetails; + + public static void main(String[] args) { + loadEnv("env.json"); + subscribeToQueue(mqDetails); + System.out.println("Sample MQ durable SUB application ending"); + } + + private static void loadEnv(String path) { + try { + String content = new String(Files.readAllBytes(Paths.get(path))); + JSONObject env = new JSONObject(content); + JSONObject endpoint = env.getJSONArray("MQ_ENDPOINTS").getJSONObject(0); + + mqDetails = new MQDetails(); + mqDetails.QMGR = endpoint.getString("QMGR"); + mqDetails.SUB_NAME = endpoint.getString("SUB_NAME"); + mqDetails.QUEUE_NAME = endpoint.getString("QUEUE_NAME"); // ✅ Fix + mqDetails.HOST = endpoint.getString("HOST"); + mqDetails.PORT = String.valueOf(endpoint.getInt("PORT")); + mqDetails.CHANNEL = endpoint.getString("CHANNEL"); + mqDetails.USER = endpoint.getString("APP_USER"); + mqDetails.PASSWORD = endpoint.getString("APP_PASSWORD"); + mqDetails.KEY_REPOSITORY = endpoint.optString("KEY_REPOSITORY", ""); + mqDetails.CIPHER = endpoint.optString("CIPHER", ""); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void subscribeToQueue(MQDetails d) { + MQQueueManager qMgr = null; + MQQueue queue = null; + + try { + Hashtable props = new Hashtable<>(); + + String ccdtUrl = System.getenv("MQCCDTURL"); + if (ccdtUrl != null && ccdtUrl.startsWith("file://")) { + String ccdtPath = ccdtUrl.replace("file://", ""); + System.setProperty("MQCCDTURL", ccdtPath); + System.out.println("Using CCDT at: " + ccdtPath); + } else { + props.put(MQConstants.HOST_NAME_PROPERTY, d.HOST); + props.put(MQConstants.PORT_PROPERTY, Integer.parseInt(d.PORT)); + props.put(MQConstants.CHANNEL_PROPERTY, d.CHANNEL); + } + + props.put(MQConstants.USER_ID_PROPERTY, d.USER); + props.put(MQConstants.PASSWORD_PROPERTY, d.PASSWORD); + props.put(MQConstants.TRANSPORT_PROPERTY, MQConstants.TRANSPORT_MQSERIES_CLIENT); + + if (!d.KEY_REPOSITORY.isEmpty()) { + props.put(MQConstants.SSL_CIPHER_SUITE_PROPERTY, d.CIPHER); + System.setProperty("com.ibm.mq.ssl.keyStore", d.KEY_REPOSITORY); + System.setProperty("com.ibm.mq.ssl.keyStorePassword", ""); + } + + qMgr = new MQQueueManager(d.QMGR, props); + System.out.println("Connected to queue manager: " + d.QMGR); + + int openOptions = MQConstants.MQOO_INPUT_AS_Q_DEF | MQConstants.MQOO_FAIL_IF_QUIESCING; + queue = qMgr.accessQueue(d.QUEUE_NAME, openOptions); + + receiveMessages(queue); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (queue != null) queue.close(); + if (qMgr != null) qMgr.disconnect(); + } catch (MQException e) { + e.printStackTrace(); + } + } + } + + private static void receiveMessages(MQQueue queue) { + try { + MQMessage msg = new MQMessage(); + MQGetMessageOptions gmo = new MQGetMessageOptions(); + gmo.options = MQConstants.MQGMO_NO_SYNCPOINT | + MQConstants.MQGMO_WAIT | + MQConstants.MQGMO_CONVERT | + MQConstants.MQGMO_FAIL_IF_QUIESCING; + gmo.waitInterval = 10000; + + System.out.println("Waiting for messages from durable subscription queue..."); + while (true) { + msg.clearMessage(); + try { + queue.get(msg, gmo); + String received = msg.readStringOfByteLength(msg.getDataLength()); + System.out.println("Received: " + received); + } catch (MQException mqe) { + if (mqe.reasonCode == MQConstants.MQRC_NO_MSG_AVAILABLE) { + System.out.println("No messages. Exiting."); + break; + } else { + throw mqe; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} From 6a413051afa878877e61cd8ac8fa28d43ae66658 Mon Sep 17 00:00:00 2001 From: Stuti Uniyal Date: Fri, 4 Jul 2025 14:14:00 +0530 Subject: [PATCH 2/2] updated readme --- base-java/Readme.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/base-java/Readme.md b/base-java/Readme.md index 3fd7bb90..b889cb9d 100644 --- a/base-java/Readme.md +++ b/base-java/Readme.md @@ -114,7 +114,25 @@ In the **second terminal (request)**: ```bash mvn exec:java -Dexec.mainClass="com.ibm.mq.samples.java.BasicRequest" -Dexec.args="env.json" ``` +### Terminal 1: Run the Request Sample +1. **Compile** the `BasicRequest.java` file using the required JAR dependencies. +2. **Run** the `BasicRequest` class. +3. The requester sends a message and waits for a response. +4. If `REPLY_QUEUE_NAME` is set, that queue is used for replies; otherwise, a temporary queue is created. +5. Optionally, set the `REQUEST_MESSAGE_EXPIRY` environment variable to define how long the request is valid. + +--- + +### Terminal 2: Run the Response Sample + +1. **Compile** the `BasicResponse.java` file with the same JAR dependencies. +2. **Run** the `BasicResponse` class. +3. The responder listens on a queue, processes incoming messages, and sends replies to the specified reply-to queue. +4. It continues running until manually stopped or it times out. +5. You can set the `RESPONDER_INACTIVITY_TIMEOUT` environment variable to control how long it waits for new messages before exiting. + +--- ## Notes - The environment can be configured using either `env.json` or a CCDT file via the `MQCCDTURL` environment variable.