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).

To use the JMP support for synchronous program switch, the JMS API (jms.jar) file must be on your classpath. The JMS API is included in the Java SDK. Alternatively, you can order IMS Enterprise Suite V3.2, which includes the JMS API.

You must create an OTMA destination descriptor with the type IMSTRAN to use this function.

Restrictions:
  • 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.

  1. Create an IMS JMP application object.
  2. Create an IMSQueueConnectionFactory.
    The connection factory and application objects are reusable.
  3. Get an IMS message queue reference.
  4. Create input and output message objects.
  5. Configure the timeout and response area size of your connection factory and create a connection.
  6. From the connection, create a JMS queue session.
  7. Configure the queue session object with the name of your IMSTRAN OTMA destination descriptor and create a JMS queue requestor.
  8. Create a BytesMessage object for the ICAL call input message area.
    For synchronous program switch requests, only BytesMessage is supported.
  9. Configure the message object with the target tran code, message length information, and input data.
  10. Submit the ICAL call.
  11. Retrieve the output message, parse the response message length information, and get the output message data.
  12. 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();
		}
	}

}