diff --git a/Java-MQ/README.md b/Java-MQ/README.md new file mode 100644 index 00000000..85ca2f7d --- /dev/null +++ b/Java-MQ/README.md @@ -0,0 +1,148 @@ +# IBM Java-MQ 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 queue (persisted publish) +- `BasicSub.java` – Subscribes and receives messages from a queue +- `BasicRequest.java` – Sends a message with a dynamic reply-to queue +- `BasicResponse.java` – Responds to requests received from a queue +- `BasicProducer.java` – Produces a message to a queue (used by request wrappers) +- `BasicConsumer.java` – Consumes a message from a queue (used by request/response logic) +- `MQDetails.java` – POJO to hold MQ connection configuration +- `SampleEnvSetter.java` – Utility to parse `env.json` and load MQ endpoint configurations +- Wrapper Classes (used internally for iterating over endpoints): + - `BasicPutWrapper.java` + - `BasicGetWrapper.java` + - `BasicPubWrapper.java` + - `BasicSubWrapper.java` + - `BasicRequestWrapper.java` + - `BasicResponseWrapper.java` + +> **Note**: Wrapper classes are utility helpers and should not be run directly. + +## 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. + +## 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 + +All samples should be run using the following format: + +```bash +mvn exec:java \ + -Dexec.mainClass="com.ibm.mq.samples.java." \ + -Dexec.args="-Dcom.ibm.mq.cfg.jmqiDisableAsyncThreads=true" \ + -Dexec.jvmArgs="-DENV_FILE=./env.json" +``` + +### Put + +```bash +mvn exec:java \ + -Dexec.mainClass="com.ibm.mq.samples.java.BasicPut" \ + -Dexec.args="-Dcom.ibm.mq.cfg.jmqiDisableAsyncThreads=true" \ + -Dexec.jvmArgs="-DENV_FILE=./env.json" +``` +### Get + +```bash +mvn exec:java \ + -Dexec.mainClass="com.ibm.mq.samples.java.BasicGet" \ + -Dexec.args="-Dcom.ibm.mq.cfg.jmqiDisableAsyncThreads=true" \ + -Dexec.jvmArgs="-DENV_FILE=./env.json" +``` + +### Publish/Subscribe + +**First terminal (subscriber):** + +```bash +mvn exec:java \ + -Dexec.mainClass="com.ibm.mq.samples.java.BasicSub" \ + -Dexec.args="-Dcom.ibm.mq.cfg.jmqiDisableAsyncThreads=true" \ + -Dexec.jvmArgs="-DENV_FILE=./env.json" +``` + +**Second terminal (publisher):** + +```bash +mvn exec:java \ + -Dexec.mainClass="com.ibm.mq.samples.java.BasicPub" \ + -Dexec.args="-Dcom.ibm.mq.cfg.jmqiDisableAsyncThreads=true" \ + -Dexec.jvmArgs="-DENV_FILE=./env.json" +``` + +### Request/Response + +**First terminal (response):** + +```bash +mvn exec:java \ + -Dexec.mainClass="com.ibm.mq.samples.java.BasicResponse" \ + -Dexec.args="-Dcom.ibm.mq.cfg.jmqiDisableAsyncThreads=true" \ + -Dexec.jvmArgs="-DENV_FILE=./env.json" +``` + +**Second terminal (request):** + +```bash +mvn exec:java \ + -Dexec.mainClass="com.ibm.mq.samples.java.BasicRequest" \ + -Dexec.args="-Dcom.ibm.mq.cfg.jmqiDisableAsyncThreads=true" \ + -Dexec.jvmArgs="-DENV_FILE=./env.json" +``` + +## Notes + +- The environment can be configured using either `env.json` or a CCDT file via the `MQCCDTURL` environment variable. +- Samples like `BasicResponse` and `BasicSub` are long-running and wait for messages until terminated or a timeout occurs. +- **Wrapper classes** are designed to iterate over all endpoints in `env.json`, but are not meant to be executed directly from the command line. +- Make sure all relevant queues and topics are pre-created in your IBM MQ queue manager. diff --git a/Java-MQ/pom.xml b/Java-MQ/pom.xml new file mode 100644 index 00000000..d8a8e2bb --- /dev/null +++ b/Java-MQ/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + com.ibm.mq.samples + base-mq-java + 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/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicConsumer.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicConsumer.java new file mode 100644 index 00000000..7073be53 --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicConsumer.java @@ -0,0 +1,69 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; + +import java.io.IOException; +import java.util.Hashtable; + +public class BasicConsumer { + + public static final String CONSUMER_GET = "queue"; + public static final String CONSUMER_SUB = "topic"; + public static final String CONSUMER_REQUEST = "model_queue"; + + public Boolean getMessage(MQDetails details, Hashtable props, MQQueue queue, String mode) { + + MQMessage msg = new MQMessage(); + MQGetMessageOptions gmo = new MQGetMessageOptions(); + + if (mode.equals(CONSUMER_GET)) { + gmo.options = MQConstants.MQGMO_NO_WAIT | + MQConstants.MQGMO_CONVERT | + MQConstants.MQGMO_FAIL_IF_QUIESCING; + } else if (mode.equals(CONSUMER_SUB)) { + gmo.options = MQConstants.MQGMO_NO_SYNCPOINT | + MQConstants.MQGMO_WAIT | + MQConstants.MQGMO_CONVERT | + MQConstants.MQGMO_FAIL_IF_QUIESCING; + gmo.waitInterval = 10000; + } else if (mode.equals(CONSUMER_REQUEST)) { + gmo.options = MQConstants.MQGMO_WAIT | MQConstants.MQGMO_CONVERT; + gmo.waitInterval = 10000; + } + + 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) { + System.out.println("No more messages."); + return false; + } else { + System.err.println("Error retrieving message: " + mqe); + return false; + } + } catch (IOException e) { + e.printStackTrace(); + return false; + } + + return true; + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicConsumerWrapper.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicConsumerWrapper.java new file mode 100644 index 00000000..93d382d5 --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicConsumerWrapper.java @@ -0,0 +1,73 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import com.ibm.mq.constants.MQConstants; + +import java.util.Hashtable; + +import com.ibm.mq.*; + +public class BasicConsumerWrapper { + + MQQueueManager qMgr = null; + MQQueue queue = null; + + public void sendMessage() { + + SampleEnvSetter envSetter = new SampleEnvSetter(); + envSetter.setEnvValues(); + + // iterate for every endpoint in env.json + int length = envSetter.getDetails().size(); + System.out.println(length); + + for (int i = 0; i < length; i++) { + MQDetails details = envSetter.getDetails().get(i); + Hashtable props = envSetter.getProps().get(i); + System.out.println("Wrapper: "+props); + + System.out.println("Wrapper QMGR: "+props); + try { + qMgr = new MQQueueManager(details.getQMGR(), props); + System.out.println("Connected to queue manager: " + details.getQMGR()); + + int openOptions = MQConstants.MQOO_INPUT_AS_Q_DEF; + queue = qMgr.accessQueue(details.getQUEUE_NAME(), openOptions); + + System.out.println("Wrapper Queue: "+queue); + + boolean keepReading = true; + BasicConsumer bc = new BasicConsumer(); + while (keepReading) { + keepReading = bc.getMessage(details, props, queue,BasicConsumer.CONSUMER_GET); + } + } 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/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicGet.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicGet.java new file mode 100644 index 00000000..5e8a0062 --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicGet.java @@ -0,0 +1,25 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +public class BasicGet { + + public static void main(String[] args) { + BasicConsumerWrapper wrapper = new BasicConsumerWrapper(); + wrapper.sendMessage(); + } + +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicProducer.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicProducer.java new file mode 100644 index 00000000..50a93a4a --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicProducer.java @@ -0,0 +1,85 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; + +import java.io.IOException; +import java.util.Hashtable; + +public class BasicProducer { + + public static final String PRODUCER_PUT = "queue"; + public static final String PRODUCER_PUBLISH = "topic"; + public static final String PRODUCER_RESPONSE = "model_queue"; + + public Boolean putMessage(MQDetails details, Hashtable props, MQDestination destination, String mode, String message, String replyToQueueName) { + + MQMessage mqMessage = new MQMessage(); + MQPutMessageOptions pmo = new MQPutMessageOptions(); + + try { + // Write the payload + mqMessage.writeString(message); + + // Set common message properties + mqMessage.format = MQConstants.MQFMT_STRING; + + switch (mode) { + case PRODUCER_PUT: + mqMessage.persistence = MQConstants.MQPER_PERSISTENT; + break; + + case PRODUCER_PUBLISH: + mqMessage.persistence = MQConstants.MQPER_PERSISTENT; + break; + + case PRODUCER_RESPONSE: + mqMessage.persistence = MQConstants.MQPER_NOT_PERSISTENT; + if (replyToQueueName != null && !replyToQueueName.isEmpty()) { + mqMessage.replyToQueueName = replyToQueueName; + } + break; + + default: + System.err.println("Invalid producer mode."); + return false; + } + + // Send message + if (destination instanceof MQQueue) { + ((MQQueue) destination).put(mqMessage, pmo); + } else if (destination instanceof MQTopic) { + ((MQTopic) destination).put(mqMessage, pmo); + } else { + System.err.println("Unsupported MQDestination type."); + return false; + } + + System.out.println("Message sent: " + message); + return true; + + } catch (MQException mqe) { + System.err.println("MQException during put: " + mqe.getMessage()); + return false; + + } catch (IOException ioe) { + System.err.println("IOException during put: " + ioe.getMessage()); + return false; + } + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicProducerWrapper.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicProducerWrapper.java new file mode 100644 index 00000000..c79f7c8f --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicProducerWrapper.java @@ -0,0 +1,78 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; + +import java.util.Hashtable; + +public class BasicProducerWrapper { + + MQQueueManager qMgr = null; + MQQueue queue = null; + + public void sendMessage() { + + SampleEnvSetter envSetter = new SampleEnvSetter(); + envSetter.setEnvValues(); + + int length = envSetter.getDetails().size(); + System.out.println("Total MQ endpoints: " + length); + + for (int i = 0; i < length; i++) { + MQDetails details = envSetter.getDetails().get(i); + Hashtable props = envSetter.getProps().get(i); + System.out.println("ProducerWrapper Properties: " + props); + + try { + // Connect to Queue Manager + qMgr = new MQQueueManager(details.getQMGR(), props); + System.out.println("Connected to queue manager: " + details.getQMGR()); + + // Open queue for output + int openOptions = MQConstants.MQOO_OUTPUT | MQConstants.MQOO_FAIL_IF_QUIESCING; + queue = qMgr.accessQueue(details.getQUEUE_NAME(), openOptions); + System.out.println("Opened queue: " + details.getQUEUE_NAME()); + + // Send message + BasicProducer producer = new BasicProducer(); + String sampleMessage = "Hello from BasicProducerWrapper!"; + boolean status = producer.putMessage(details, props, queue, BasicProducer.PRODUCER_PUT, sampleMessage, null); + + if (status) { + System.out.println("Message successfully sent."); + } else { + System.err.println("Message sending failed."); + } + + } catch (Exception e) { + System.err.println("Error during message send:"); + e.printStackTrace(); + } finally { + try { + if (queue != null) + queue.close(); + if (qMgr != null) + qMgr.disconnect(); + } catch (MQException me) { + System.err.println("Error closing MQ resources:"); + me.printStackTrace(); + } + } + } + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPub.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPub.java new file mode 100644 index 00000000..c49d3c46 --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPub.java @@ -0,0 +1,25 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +public class BasicPub { + + public static void main(String[] args) { + BasicPubWrapper wrapper = new BasicPubWrapper(); + wrapper.sendMessage(); + System.out.println("Sample MQ PUB application ending"); + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPubWrapper.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPubWrapper.java new file mode 100644 index 00000000..71248179 --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPubWrapper.java @@ -0,0 +1,82 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; + +import java.time.Instant; +import java.util.Hashtable; + +public class BasicPubWrapper { + + MQQueueManager qMgr = null; + MQQueue queue = null; + + public void sendMessage() { + + SampleEnvSetter envSetter = new SampleEnvSetter(); + envSetter.setEnvValues(); + + int length = envSetter.getDetails().size(); + System.out.println("Total endpoints: " + length); + + for (int i = 0; i < length; i++) { + MQDetails details = envSetter.getDetails().get(i); + Hashtable props = envSetter.getProps().get(i); + + try { + qMgr = new MQQueueManager(details.getQMGR(), props); + System.out.println("Connected to queue manager: " + details.getQMGR()); + + queue = qMgr.accessQueue( + details.getQUEUE_NAME(), + MQConstants.MQOO_OUTPUT | MQConstants.MQOO_FAIL_IF_QUIESCING + ); + + MQMessage msg = new MQMessage(); + msg.format = MQConstants.MQFMT_STRING; + msg.persistence = MQConstants.MQPER_PERSISTENT; + + String payload = "{\"Greeting\": \"Hello from Java publisher at " + 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; + + queue.put(msg, pmo); + + System.out.println("Published message to queue: " + details.getQUEUE_NAME()); + System.out.println("Message content: " + payload); + + } catch (MQException mqe) { + System.err.println("MQ error publishing message: " + mqe.getMessage()); + mqe.printStackTrace(); + } 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/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPut.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPut.java new file mode 100644 index 00000000..0d00637d --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicPut.java @@ -0,0 +1,24 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +public class BasicPut { + + public static void main(String[] args) { + BasicProducerWrapper wrapper = new BasicProducerWrapper(); + wrapper.sendMessage(); + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicRequest.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicRequest.java new file mode 100644 index 00000000..3736550e --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicRequest.java @@ -0,0 +1,24 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; +public class BasicRequest { + + public static void main(String[] args) { + BasicRequestWrapper wrapper = new BasicRequestWrapper(); + wrapper.sendMessage(); + System.exit(0); + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicRequestWrapper.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicRequestWrapper.java new file mode 100644 index 00000000..e7a5d4ae --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicRequestWrapper.java @@ -0,0 +1,93 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import java.time.Instant; +import java.util.Hashtable; + +import com.ibm.mq.constants.MQConstants; + +import com.ibm.mq.*; + +public class BasicRequestWrapper { + + MQQueueManager qMgr = null; + MQQueue queue = null; + + public void sendMessage() { + + SampleEnvSetter envSetter = new SampleEnvSetter(); + envSetter.setEnvValues(); + + // iterate for every endpoint in env.json + int length = envSetter.getDetails().size(); + System.out.println(length); + + for (int i = 0; i < length; i++) { + MQDetails details = envSetter.getDetails().get(i); + Hashtable props = envSetter.getProps().get(i); + try { + qMgr = new MQQueueManager(details.getQMGR(), props); + System.out.println("Connected to queue manager: " + details.getQMGR()); + + MQQueue replyQueue = qMgr.accessQueue( + details.getMODEL_QUEUE_NAME(), + MQConstants.MQOO_INPUT_EXCLUSIVE, + null, + details.getDYNAMIC_QUEUE_PREFIX(), + null); + + String dynamicReplyQueueName = replyQueue.getName(); + System.out.println("Opened dynamic reply-to queue: " + dynamicReplyQueueName); + + MQQueue requestQueue = qMgr.accessQueue(details.getQUEUE_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: " + details.getQUEUE_NAME()); + System.out.println("Waiting for reply on: " + dynamicReplyQueueName); + + boolean keepReading = true; + BasicConsumer bc = new BasicConsumer(); + while (keepReading) { + keepReading = bc.getMessage(details, props, replyQueue, BasicConsumer.CONSUMER_REQUEST); + } + } 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/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicResponse.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicResponse.java new file mode 100644 index 00000000..b4d1d9f1 --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicResponse.java @@ -0,0 +1,25 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +public class BasicResponse { + + public static void main(String[] args) { + BasicResponseWrapper wrapper = new BasicResponseWrapper(); + wrapper.respondToMessages(); + System.exit(0); + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicResponseWrapper.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicResponseWrapper.java new file mode 100644 index 00000000..00bf8386 --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicResponseWrapper.java @@ -0,0 +1,110 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import com.ibm.mq.*; +import com.ibm.mq.constants.MQConstants; + +import java.util.Hashtable; + +public class BasicResponseWrapper { + + MQQueueManager qMgr = null; + MQQueue queue = null; + + public void respondToMessages() { + + SampleEnvSetter envSetter = new SampleEnvSetter(); + envSetter.setEnvValues(); + + int length = envSetter.getDetails().size(); + System.out.println("Total endpoints: " + length); + + for (int i = 0; i < length; i++) { + MQDetails details = envSetter.getDetails().get(i); + Hashtable props = envSetter.getProps().get(i); + + try { + qMgr = new MQQueueManager(details.getQMGR(), props); + System.out.println("Connected to queue manager: " + details.getQMGR()); + + queue = qMgr.accessQueue( + details.getQUEUE_NAME(), + MQConstants.MQOO_INPUT_AS_Q_DEF | MQConstants.MQOO_OUTPUT | MQConstants.MQOO_INQUIRE + ); + + boolean keepRunning = true; + while (keepRunning) { + MQMessage requestMsg = new MQMessage(); + MQGetMessageOptions gmo = new MQGetMessageOptions(); + gmo.options = MQConstants.MQGMO_WAIT | MQConstants.MQGMO_CONVERT; + gmo.waitInterval = 10000; // wait 10 seconds + + try { + queue.get(requestMsg, gmo); + String body = requestMsg.readStringOfByteLength(requestMsg.getDataLength()); + System.out.println("Received request: " + body); + + // Get reply-to queue name + String replyToQueue = requestMsg.replyToQueueName; + if (replyToQueue == null || replyToQueue.isEmpty()) { + System.out.println("No reply-to queue specified. Skipping response."); + continue; + } + + // Create a response message + MQMessage responseMsg = new MQMessage(); + responseMsg.format = MQConstants.MQFMT_STRING; + responseMsg.messageType = MQConstants.MQMT_REPLY; + String replyPayload = "{\"Response\": \"Reply to message: " + body + "\"}"; + responseMsg.writeString(replyPayload); + + MQPutMessageOptions pmo = new MQPutMessageOptions(); + pmo.options = MQConstants.MQPMO_NO_SYNCPOINT; + + // Put the message to the dynamic reply queue + MQQueue replyQueue = qMgr.accessQueue(replyToQueue, MQConstants.MQOO_OUTPUT); + replyQueue.put(responseMsg, pmo); + replyQueue.close(); + + System.out.println("Sent reply to: " + replyToQueue); + System.out.println("Reply payload: " + replyPayload); + + } catch (MQException mqe) { + if (mqe.reasonCode == MQConstants.MQRC_NO_MSG_AVAILABLE) { + System.out.println("No more messages. Exiting..."); + keepRunning = false; + } else { + System.err.println("MQ error getting/putting message: " + mqe.getMessage()); + } + } + } + + } 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/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicSub.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicSub.java new file mode 100644 index 00000000..d602080c --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicSub.java @@ -0,0 +1,24 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +public class BasicSub { + + public static void main(String[] args) { + BasicSubWrapper wrapper = new BasicSubWrapper(); + wrapper.sendMessage(); + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicSubWrapper.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicSubWrapper.java new file mode 100644 index 00000000..46d16f02 --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/BasicSubWrapper.java @@ -0,0 +1,71 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import java.util.Hashtable; + +import com.ibm.mq.MQException; +import com.ibm.mq.constants.MQConstants; + +import com.ibm.mq.*; + +public class BasicSubWrapper { + + MQQueueManager qMgr = null; + MQQueue queue = null; + + public void sendMessage() { + + SampleEnvSetter envSetter = new SampleEnvSetter(); + envSetter.setEnvValues(); + + // iterate for every endpoint in env.json + int length = envSetter.getDetails().size(); + System.out.println(length); + + for (int i = 0; i < length; i++) { + MQDetails details = envSetter.getDetails().get(i); + Hashtable props = envSetter.getProps().get(i); + try { + qMgr = new MQQueueManager(details.getQMGR(), props); + System.out.println("Connected to queue manager: " + details.getQMGR()); + + int openOptions = MQConstants.MQOO_INPUT_AS_Q_DEF; + queue = qMgr.accessQueue(details.getQUEUE_NAME(), openOptions); + + System.out.println("Wrapper Queue: " + queue); + + boolean keepReading = true; + BasicConsumer bc = new BasicConsumer(); + while (keepReading) { + keepReading = bc.getMessage(details, props, queue, BasicConsumer.CONSUMER_SUB); + } + } 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/Java-MQ/src/main/java/com/ibm/mq/samples/java/MQDetails.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/MQDetails.java new file mode 100644 index 00000000..25519e3a --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/MQDetails.java @@ -0,0 +1,101 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import org.json.JSONObject; + +public class MQDetails { + + private String QMGR; + private String QUEUE_NAME; + private String HOST; + private String PORT; + private String CHANNEL; + private String USER; + private String PASSWORD; + private String KEY_REPOSITORY; + private String CIPHER; + private String MODEL_QUEUE_NAME; + private String DYNAMIC_QUEUE_PREFIX; + + public MQDetails buildMQDetails(JSONObject endpoint) { + this.QMGR = endpoint.getString("QMGR"); + this.QUEUE_NAME = endpoint.getString("QUEUE_NAME"); + this.HOST = endpoint.getString("HOST"); + this.PORT = String.valueOf(endpoint.getInt("PORT")); + this.CHANNEL = endpoint.getString("CHANNEL"); + this.USER = endpoint.getString("APP_USER"); + this.PASSWORD = endpoint.getString("APP_PASSWORD"); + this.KEY_REPOSITORY = endpoint.optString("KEY_REPOSITORY", ""); + this.CIPHER = endpoint.optString("CIPHER", ""); + this.MODEL_QUEUE_NAME = endpoint.optString("MODEL_QUEUE_NAME", ""); + this.DYNAMIC_QUEUE_PREFIX = endpoint.optString("DYNAMIC_QUEUE_PREFIX", ""); + + return this; + } + + public String getQMGR() { + return QMGR; + } + + public String getQUEUE_NAME() { + return QUEUE_NAME; + } + + public String getHOST() { + return HOST; + } + + public String getPORT() { + return PORT; + } + + public String getCHANNEL() { + return CHANNEL; + } + + public String getUSER() { + return USER; + } + + public String getPASSWORD() { + return PASSWORD; + } + + public String getKEY_REPOSITORY() { + return KEY_REPOSITORY; + } + + public String getCIPHER() { + return CIPHER; + } + + public String getMODEL_QUEUE_NAME() { + return MODEL_QUEUE_NAME; + } + + public String getDYNAMIC_QUEUE_PREFIX() { + return DYNAMIC_QUEUE_PREFIX; + } + + @Override + public String toString() { + return "MQDetails [QMGR=" + QMGR + ", QUEUE_NAME=" + QUEUE_NAME + ", HOST=" + HOST + ", PORT=" + PORT + + ", CHANNEL=" + CHANNEL + ", USER=" + USER + ", PASSWORD=" + PASSWORD + ", KEY_REPOSITORY=" + + KEY_REPOSITORY + ", CIPHER=" + CIPHER + ", MODEL_QUEUE_NAME=" + MODEL_QUEUE_NAME + + ", DYNAMIC_QUEUE_PREFIX=" + DYNAMIC_QUEUE_PREFIX + "]"; + } +} diff --git a/Java-MQ/src/main/java/com/ibm/mq/samples/java/SampleEnvSetter.java b/Java-MQ/src/main/java/com/ibm/mq/samples/java/SampleEnvSetter.java new file mode 100644 index 00000000..1045248e --- /dev/null +++ b/Java-MQ/src/main/java/com/ibm/mq/samples/java/SampleEnvSetter.java @@ -0,0 +1,108 @@ +/* +* (c) Copyright IBM Corporation 2025 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.ibm.mq.samples.java; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.ibm.mq.constants.MQConstants; + +public class SampleEnvSetter { + + private JSONArray endpoints; + private List details; + private List> props; + + public SampleEnvSetter() { + this.details = new ArrayList<>(); + this.props = new ArrayList<>(); + } + + public void setEnvValues() { + + loadEnv("env.json"); + + for (int i = 0; i < endpoints.length(); i++) { + System.out.println("Processing endpoint " + i); + JSONObject point = endpoints.getJSONObject(i); + MQDetails details = new MQDetails(); + this.details.add(details.buildMQDetails(point)); + this.props.add(getEnvValues(details)); + } + + System.out.println("Sample MQ GET application ending"); + + } + + private void loadEnv(String path) { + try { + String content = new String(Files.readAllBytes(Paths.get(path))); + JSONObject env = new JSONObject(content); + this.endpoints = env.getJSONArray("MQ_ENDPOINTS"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private Hashtable getEnvValues(MQDetails details) { + + System.out.println(details); + + 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.getHOST()); + props.put(MQConstants.PORT_PROPERTY, Integer.parseInt(details.getPORT())); + props.put(MQConstants.CHANNEL_PROPERTY, details.getCHANNEL()); + } + + props.put(MQConstants.USER_ID_PROPERTY, details.getUSER()); + props.put(MQConstants.PASSWORD_PROPERTY, details.getPASSWORD()); + props.put(MQConstants.TRANSPORT_PROPERTY, MQConstants.TRANSPORT_MQSERIES_CLIENT); + + if (!details.getKEY_REPOSITORY().isEmpty()) { + props.put(MQConstants.SSL_CIPHER_SUITE_PROPERTY, details.getCIPHER()); + System.setProperty("com.ibm.mq.ssl.keyStore", details.getKEY_REPOSITORY()); + System.setProperty("com.ibm.mq.ssl.keyStorePassword", ""); + } + return props; + } + + public List getDetails() { + return details; + } + + public List> getProps() { + return props; + } + + @Override + public String toString() { + return "SampleEnvSetter [details=" + details.size() + ", props=" + props.size() + "]"; + } + +} diff --git a/README.md b/README.md index 65fd47ad..b7e21f03 100644 --- a/README.md +++ b/README.md @@ -248,6 +248,7 @@ are set and exported (see language README docs for more info). ### Language based MQI / JMS / XMS samples #### [Node.js](/Node.js/README.md) #### [JMS](/JMS/README.md) +#### [Java-MQ](/Java-MQ/README.md) #### [Python](/Python/README.md) #### [C# .Net](/dotnet/README.md) #### [Go](/Go/README.md) @@ -289,5 +290,4 @@ are set and exported (see language README docs for more info). ### MQ container deployment examples #### [compose](/container/queuemanager/compose/README.md) -#### [compose](/container/queuemanager/terraform-aws/README.md) - +#### [compose](/container/queuemanager/terraform-aws/README.md) \ No newline at end of file