Issuing synchronous program switch requests from a Java dependent region
IMS provides support for synchronous program switch functionality from Java™ message processing (JMP) or Java batch processing (JBP) applications through an IMS implementation of the Java Message Service (JMS).
You must create an OTMA destination descriptor with the type IMSTRAN to use this function.
- The IMS implementation of JMS is limited to supporting the Point-to-Point (PTP) messaging domain only. In addition, support is only provided for non-transacted QueueSession objects with Session.AUTO_ACKNOWLEDGE mode.
- The DFSYIOE0 and DFSMSCE0 exit routines are not called for synchronous program switch requests.
- The target transaction is not part of the RRS commit scope for the initiating application program.
- JBP applications cannot make synchronous program switch requests in a DBCTL environment.
- The target transaction has read-only access to Fast Path Main Storage Databases (MSDBs).
- The target transaction cannot be a conversational transaction.
- Synchronous program switch requests can be used in a shared queues environment only if all of the participating IMS systems have a DBRC MINVERS value of 13.1 or greater.
If the application attempts to call a JMS method that is not supported by IMS or pass an unsupported argument in a JMS method call, the API throws a JMSException.
The following procedure shows the high-level programming flow to implement a synchronous program switch operation from a JMP application.
- Create an IMS JMP application object.
- Create an IMSQueueConnectionFactory. The connection factory and application objects are reusable.
- Get an IMS message queue reference.
- Create input and output message objects.
- Configure the timeout and response area size of your connection factory and create a connection.
- From the connection, create a JMS queue session.
- Configure the queue session object with the name of your IMSTRAN OTMA destination descriptor and create a JMS queue requestor.
- Create a BytesMessage object for the ICAL call input message
area. For synchronous program switch requests, only BytesMessage is supported.
- Configure the message object with the target tran code, message length information, and input data.
- Submit the ICAL call.
- Retrieve the output message, parse the response message length information, and get the output message data.
- Clean up the output message and terminate the application.
This example demonstrates how to make a synchronous program switch request from a JMP application.
import javax.jms.BytesMessage;
import javax.jms.QueueConnection;
import javax.jms.QueueRequestor;
import javax.jms.QueueSession;
import com.ibm.ims.jms.IMSQueueConnectionFactory;
import com.ibm.ims.dli.tm.Application;
import com.ibm.ims.dli.tm.ApplicationFactory;
import com.ibm.ims.dli.tm.IOMessage;
import com.ibm.ims.dli.tm.MessageQueue;
public class SyncCalloutSample
{
private static IOMessage inputMessage = null;
private static IOMessage outputMessage = null;
private static MessageQueue msgQueue = null;
private static Application app = null;
public static void main(String args[])
{
// Create an IMS JMP application
app = ApplicationFactory.createApplication();
// Get the IMS JMS queue connection factory
IMSQueueConnectionFactory jmsConnectionFactory = app.getIMSQueueConnectionFactory();
QueueConnection jmsConnection = null;
QueueSession jmsQueueSession = null;
javax.jms.Queue jmsQueue = null;
QueueRequestor jmsQueueRequestor = null;
try {
// Get a reference to the IMS message queue
msgQueue = app.getMessageQueue();
// Create an input message object
inputMessage = app.getIOMessage("class://MyInputMessage");
// Create an output message object
outputMessage = app.getIOMessage("class://MyOutputMessage");
// Retrieve messages off the queue
while(msgQueue.getUnique(inputMessage)) {
// Setting the JMS settings to issue an ICAL call
// Specify the amount of time to wait for a response
// from an ICAL call. This value corresponds to the
// RSFLD value in the AIB
jmsConnectionFactory.setTimeout(999999);
// Specify the expected size of the response message
// from the ICAL call. This value corresponds to the
// OAUSE value in the AIB
jmsConnectionFactory.setResponseAreaLength(0x00000033);
// Create the JMS queue connection
jmsConnection = jmsConnectionFactory.createQueueConnection();
// Create the JMS queue session
jmsQueueSession = jmsConnection.createQueueSession(false, 1);
// Specify the OTMA Routing descriptor which describes the
// target that the ICAL call will be sent to. This value
// correponse with the RSNM1 value in the AIB
jmsQueue = jmsQueueSession.createQueue("DEST0001");
// Create the JMS queue requestor
jmsQueueRequestor = new QueueRequestor(jmsQueueSession, jmsQueue);
// Build the request area for the ICAL call
// For synchronous program switch a BytesMessage object must be used
BytesMessage sendMsg = jmsQueueSession.createBytesMessage();
// The content of the request area must follow the existing
// format for synchronous program switch:
// LL + ZZ + SWITCH-TO-TRAN + TRAN-INPUT
short ll = 50;
short zz = 0;
sendMsg.writeShort(ll); // Specify the LL value
sendMsg.writeShort(zz); // Specify the ZZ value
// The name of the SWITCH-TO-TRAN is 8 bytes long and encoded in CP1047
// This value must be converted to bytes to be written into the BytesMessage object
String trancode = new String("SWTCHTRN");
sendMsg.writeBytes(trancode.getBytes("Cp1047"));
// Specify the input data for the switch to transaction
sendMsg.writeUTF(inputMessage.getString("MYINPUT"));
// The length of the request area can be retrieved by calling the
// BytesMessage.getBodyLength() method
// This value corresponds to the OALEN value in the AIB
System.out.println("Request Message Length (AIBOALEN): " + sendMsg.getBodyLength());
// Submit the ICAL call
// For synchronous program switch, the reply message will be a BytesMessage object
BytesMessage replyMsg = (BytesMessage)jmsQueueRequestor.request(sendMsg);
// The response message will have the following format
// LL + ZZ + TRAN-OUTPUT
// Retrieve the LL field
replyMsg.readShort();
// Retrieve the ZZ field
replyMsg.readShort();
// Retrieve the output data from the switch to transaction and place it in
// the output message
outputMessage.setString("MYOUTPUT", replyMsg.readUTF());
// Send the output message back to IMS
msgQueue.insert(outputMessage, MessageQueue.DEFAULT_DESTINATION);
}
// Terminate the application and free up any associated resources
app.end();
}
catch(Exception e) {
// Error scenario, free up resources
app.end();
e.printStackTrace();
}
}
}
This example demonstrates how to make a synchronous program switch request from a JBP application.
package testcases.udb.opendb.t2;
import javax.jms.BytesMessage;
import javax.jms.QueueConnection;
import javax.jms.QueueRequestor;
import javax.jms.QueueSession;
import com.ibm.ims.jms.IMSQueueConnectionFactory;
import com.ibm.ims.dli.tm.Application;
import com.ibm.ims.dli.tm.ApplicationFactory;
public class SyncPgmSwitchFromJBPSample {
private static Application app = null;
public static void main(String args[]) {
// Create an IMS JBP application
app = ApplicationFactory.createApplication();
// Get the IMS JMS queue connection factory
IMSQueueConnectionFactory jmsConnectionFactory = app.getIMSQueueConnectionFactory();
QueueConnection jmsConnection = null;
QueueSession jmsQueueSession = null;
javax.jms.Queue jmsQueue = null;
QueueRequestor jmsQueueRequestor = null;
try {
// Setting the JMS settings to issue an ICAL call
// Specify the amount of time to wait for a response from an
// ICAL call. This value corresponds to the RSFLD value in the AIB
jmsConnectionFactory.setTimeout(999999);
// Specify the expected size of the response message from the
// ICAL call. This value corresponds to the OAUSE value in the AIB
int expectedResponseLength = 50;
jmsConnectionFactory.setResponseAreaLength(expectedResponseLength);
// Create the JMS queue connection
jmsConnection = jmsConnectionFactory.createQueueConnection();
// Create the JMS queue session
jmsQueueSession = jmsConnection.createQueueSession(false, 1);
// Specify the OTMA Routing descriptor which describes the
// target that the ICAL call will be sent to. This value
// corresponds with the RSNM1 value in the AIB
jmsQueue = jmsQueueSession.createQueue("MYDEST");
// Create the JMS queue requester
jmsQueueRequestor = new QueueRequestor(jmsQueueSession,
jmsQueue);
// Build the request area for the ICAL call
// For synchronous program switch a BytesMessage object must be used
BytesMessage sendMsg = jmsQueueSession.createBytesMessage();
// The content of the request area must follow the existing
// format for synchronous program switch:
// LL + ZZ + SWITCH-TO-TRAN + TRAN-INPUT
short ll = 50;
short zz = 0;
sendMsg.writeShort(ll); // Specify the LL value
sendMsg.writeShort(zz); // Specify the ZZ value
// The name of the SWITCH-TO-TRAN is 8 bytes long and encoded in CP1047
// This value must be converted to bytes to be written into the
// BytesMessage object
String trancode = new String("SWTCHTRN");
sendMsg.writeBytes(trancode.getBytes("Cp1047"));
// Specify the input data for the switch to transaction
sendMsg.writeUTF("MYINPUT");
// The length of the request area can be retrieved by calling
// the BytesMessage.getBodyLength() method
// This value corresponds to the OALEN value in the AIB
System.out.println("Request Message Length (AIBOALEN): "
+ sendMsg.getBodyLength());
// Submit the ICAL call
// >>-ICAL--aib--request_area--responseArea------<<
// For synchronous program switch, the reply message will be a
// BytesMessage object
BytesMessage replyMsg = (BytesMessage) jmsQueueRequestor
.request(sendMsg);
// The response message will have the following format
// LL + ZZ + TRAN-OUTPUT
// Retrieve the LL field
replyMsg.readShort();
// Retrieve the ZZ field
replyMsg.readShort();
// Retrieve the Data field
byte[] messageBody = new byte[(int) replyMsg.getBodyLength()];
replyMsg.readBytes(messageBody);
// Terminate the application and free up any associated resources
app.end();
} catch (Exception e) {
// Error scenario, free up resources
app.end();
e.printStackTrace();
}
}
}