Part 1 of this three-part series described the different Java™ environments that IBM® CICS® provides:
- The traditional pooled JVM, where only one CICS-based Java transaction runs in a JVM at a time.
- The CICS JVM server environment, where multiple Java program requests can be dispatched to the same JVM at the same time.
Here are the CICS-provided Java environments that use the JVM server (but can't be mixed into a single JVM server):
- The OSGi-based environment, which provides the OSGi dynamic module system with functionality such as dynamically adding and removing Java classes to the JVM, providing the OSGi registry, exposing
only the interfaces to your Java module instead of all classes in the module, and specifying module dependencies to almost eliminate typical
ClassNotFoundproblems. - The Axis2 open-source Web service engine, which lets you expose a POJO quickly and easily using JAX-WS annotations, and write handlers in the Axis2 style.
- CICS Dynamic Scripting, which provides a quick way to develop Web applications using the PHP and Groovy scripting languages. The PHP and Groovy interpreters are implemented in Java, so there is a Java bridge to let you instantiate Java objects and invoke CICS programs
- The OSGi-based environment, which provides the OSGi dynamic module system with functionality such as dynamically adding and removing Java classes to the JVM, providing the OSGi registry, exposing
only the interfaces to your Java module instead of all classes in the module, and specifying module dependencies to almost eliminate typical
- CICS Transaction Gateway, which facilitates communications from a Java program running in a non-CICS environment to a CICS TS program.
As you would expect, if you are working with Java classes within a single CICS-based Java program, you work with them as normal: you instantiate the object and invoke the object's methods. However, when your application is coded in Java, but you want to leverage the strengths of the different CICS-provided Java environments, or you want to distribute parts of your Java-based application over multiple CICS regions, using a Java-like approach to transporting Java data objects is preferable to the traditional series-of-bytes field-oriented approach to transporting data. This traditional approach to passing data is needed and performs well if you are using multiple programming languages, which is one of the strengths of CICS.
Part 1 described that the CICS version of a call, the EXEC CICS LINK command, which lets you invoke another program written in the same or a different programming language in a CICS environment. The CICS-architected facilities for passing data between CICS programs are the COMMAREA and channels and containers. The COMMAREA is a block of storage up to 32 KB, while a container is a named block of storage with no size limit. Containers are grouped into a channel, which can be passed from one CICS program to another. The COMMAREA, and channels and containers are mutually exclusive -- a program can receive data using only one of the two techniques at a time. When you LINK from program A to program B, program A can pass a COMMAREA or a channel, but not both.
Part 1 stated that if a CICS-based application in only written in Java, and you need to move from one CICS Java environment to another, it is simpler to stay in a Java paradigm and pass Java data objects between the CICS-based Java environments. You can do that by serializing a Java data object into a CICS container, passing the container to another Java program running in a different CICS Java environment, and then deserializing the object in the target Java program.
You could also pass data in a series-of-bytes, field-oriented structure, but passing Java data objects between the CICS-provided Java environments lets you leverage the strengths of the different CICS-provided Java environments, and also lets you avoid:
- Creating a COBOL copybook layout for the data to be passed from between Java programs
- Running utilities to create a Java data object from the COBOL copybook
- The need for the Java programmer to understand COBOL
- The need to maintain the required COBOL copybooks in your source repository
- The need to perform production turnover on the COBOL copybook
- The need to update the COBOL copybook if the contents of the passed data changes (and the need to go through the subsequent repository updates and production turnover)
Using an object-oriented façade on top of CICS
This article shows you how to use CICS data-passing facilities to pass Java data objects between Java programs running in the CICS-provided Java environments. You can provide an object-oriented façade on top of CICS data passing facilities to create a Java-oriented way to pass Java data objects. At the bottom of this article, you can download a sample class that implements a façade, and it can be used as-is or as the basis of your own façade implementation. When passing Java data objects from an originating Java program running in one CICS-provided Java environment to a different CICS-provided Java environment, a façade enables you to pass Java data objects using code like this:
String abc = "Some information to Pass";
Employee emp = new Employee("John Doe");
DDW_CicsObjectTransporter transporter =
new DDW_CicsObjectTransporter();
transporter.addObject("abc",abc)
.addObject("emp",emp)
.execute("TARGET");
// and after the program return
String errorString = (String)transporter.getObject("error");
If (errorString != null) {
processError();
} else {
Manager newManager = (Manager)transporter.getObject("mgr");
// process/display Manager object that was returned
}
|
Here is some sample code for the responding Java program to return data using the facade:
DDW_CicsObjectTransporter transporter = new DDW_CicsObjectTransporter();
Employee emp = (Employee)transporter.getObject("emp");
// work with employee object
transporter.removeObject("abc"); // can remove object in the transporter
Manger mgr = new Manger("Joe Bloggs");
transporter.addObject("mgr",mgr); // add new or changed objects
return;
|
The Java classes included with this article provide a façade that enables the above interactions. You may be able to use these classes as-is in your environment, but please read the rest of the article to understand what these classes do and how they may affect application performance.
This article series describes CICS Java environments available up through CICS TS V4.2. It is intended for Java programmers developing programs for CICS, but will also be beneficial to CICS application programmers who are starting to use Java as well as CICS systems programmers.
Passing Java data objects between CICS-provided Java environments requires serialization of the Java data object. The concepts of object serialization are well understood by most Java programmers, and there are several good articles on Java object serialization as well as several examples of the Java code for object serialization on the Internet. Therefore this article will only mention some highlights of Java object serialization, and these highlights will help if you read some of the articles on Java object serialization.
To serialize your object to a byte array, look at the writeObject() method of the ObjectOuputStream. To deserialize your object from a byte array, look at the readObject() method of the ObjectInputStream.
For an object to be serialized, it must implement the java.io.Serializable interface. Java objects such as String and arrays implement this interface, but java.lang.Object (the mother of all objects) does not. Therefore, depending on the inheritance structure of the objects you want to pass, you may need to have your objects implement the Serializable interface. You can implement multiple interfaces in a single Java object so this shouldn't present a problem. Even if your object implements the Serializable interface, it doesn't mean that everything your object references can be serialized. You will want to ensure that your object and all objects it references (and the objects they reference) implement Serializable.
You will also need to ensure that the same version of the class exists in the LINKing CICS JVM environment and the LINKed-to CICS JVM environment. As part of implementing the Serializable interface, include a field defined as private static final long with a name of serialVersionUID. As you change your object, you should change the serialVersionUID. When the serialVersionUID is included in the object, the value associated with this field is stored in the serialized object. If there is an attempt to deserialize an object where the local class definition does not agree with the serialVerisionUID in the serialize object, deserialization will fail, with a meaningful error message. Use of the serialVersionUID field will avoid potential out-of-sync situations that may cause unexpected results. Use of the serialVersionUID is a best practice when using object serialization.
The Java data object transporter classes provided with this article verify that you have supplied a serialVersionUID in the object to be passed, but the provided transporter classes do not validate that you have supplied a serialVersionUID field in the objects referenced by the passed object. Therefore you need to verify that referenced objects contain a serialVersionUID field.
In the provided Java class, you can turn off serialVersionUID checking by using the setCheckForSerialVersionUIDBeforeSerialization(false) method.
If your object has special serialization considerations and Java's normal serialization won't work for your object, you can specify how your object is serialized and deserialized by implementing the writeObject() and readObject() methods. These two methods, when implementing the Serializable interface, will be invoked if present during object serialization and deserialization.
Serialization is not trivial and does require CPU cycles. Since applications running in a CICS environment are expected to have fast response time, do not needlessly serialize and deserialize objects. Additionally, you should benchmark the use of serialized Java data objects for your application. The overall affect of serialization in your application will vary depending on the size, complexity, and number of objects being serialized.
Once you have serialized the object to be passed into a byte array, you need to place the byte array into a container associated with a channel. In the receiving Java program you need to get the byte array from a container. To get or put data from or into a container, you must first get a reference to a channel. There are three ways to get a CICS channel reference:
- Access the channel that was passed to you (also known as the current channel) with the following command:
Channel myChannel = Task.getTask().getCurrentChannel();
- Create a channel, which you can then pass to another program, with the following command:
Channel myChannel = Task.getTask().createChannel(THECHANNELNAME);
- Access the current channel or any channel that was created with the specified name at the current CICS link level:
Channel myChannel = Task.getTask().getChannel(THECHANNELNAME);
For the getCurrentChannel() and getChannel() methods, if the myChannel variable is null, the specified channel doesn't exist at this CICS link level, so you will need to create a channel for passing the serialized Java data object.
If you are going to add containers to a channel (pass serialized objects to another Java program in a different CICS Java environment), you could use the current channel, but you should be cautious, because whatever is already in the channel plus the containers you add to the channel will be passed to the target program. If the target program is in a different CICS region, then all container content will be transmitted to the CICS region containing the target program (which could add to application response time). If the containers are passed to a different Java environment within the same CICS region, then passing the container content will be a memory-to-memory transfer.
After you have a reference to a channel, you can use the following code to put data in a container, get data from a container, and delete a container. There are two types of CICS containers -- CHAR and BIT, and you will want to use BIT containers in this case. Both channel and container names can be from 1 to 16 characters.
byte[] myByteArray = "some bytes".getBytes(); // to be passed Container myContainer = myChannel.createContainer(containerName); myContainer.put(myByteArray); // this is a BIT container Container myContainer = myChannel.getContainer(containerName); byte[] myByteArray = myContainer.get() ; // get the byte array from the container myChannel.deleteContainer(containerName); // delete the container |
When working with channels and containers in your CICS-based Java program, various exceptions can be thrown, so place the above code snippets in try/catch blocks.
Invoking another CICS program from a CICS-based Java program
CICS-based Java programs that use other Java programs within the same CICS-provided Java environment should use normal Java techniques -- instantiating an object of the proper type and invoking the appropriate methods on those objects.
Invoking another CICS-based Java program that runs in a CICS-provided Java environment that is different from the current CICS-provided Java environment (or runs in a different CICS-provided Java environment under the control of a different CICS region) requires the equivalent of an EXEC CICS LINK to the other Java program. The Java equivalent of an EXEC CICS LINK command is straightforward, as shown below:
Program aProg = new Program(); aProg.setName(targetProgram); aProg.link(theChannel); |
In the above code snippet, the targetProgram is a variable containing the name of the CICS program to be LINKed to. The link(theChannel) method attempts the LINK, passing the specified channel and all containers in that channel. Place the above code snippet in a try/catch block.
From a theoretical perspective, that's all there is too it -- just serialize the object into a byte array, place the byte array into a container associated with a channel, LINK to the target program, and then deserialize the byte array passed in the container into a data object that can be used by your program.
There are just enough steps that the best approach is to code a set of generic classes to do these steps for you. While researching the concepts presented in this article, we wrote a set of classes that you can use to see the steps and the syntax of the commands, and can extend for your own use. (These Java classes have not been submitted to any official IBM testing and are provided "as-is" to illustrate concepts described in this article.) While the approach described in this article will make life easier for the Java application developer, performance will vary. So if you use the techniques described in this article, benchmark your results to see if your application performs at acceptable levels, or if, instead of using serialized objects, you should convert data from Java data objects to a field-oriented series-of-bytes structure when passing data between your Java programs (in other words, use the traditional CICS data passing technique, which is needed when passing data to CICS-based programs coded in multiple languages and not just in Java).
Using the provided Java classes to pass Java objects between CICS Java programs
When passing Java objects between CICS-based JVM environments, the originating CICS Java environment will be:
- CICS dynamic scripting application
- Axis2-based Web service wrapper program
- CICS Transaction Gateway Java client program
- CICS-based OSGi environment
- CICS-based pooled JVM environment
The target CICS-based JVM environments where the target Java business logic program will be invoked are:
- CICS-based OSGi environment
- CICS-based pooled JVM environment
Again, the CICS-based OSGi environment is the strategic location for Java-based business logic in CICS, because it maximizes the flexibility for your business logic, and enables reuse by letting you expose Java-based business logic using a variety of CICS interoperability options, including Web services, RESTful interface, WebSphere MQ, and CICS dynamic scripting.
The source code for the sample object transporter should help you understand the approach of passing serialized objects in a CICS-provided Java environment. You can use the object transporter provided, or you can enhance the object transporter to accommodate any special requirements.
Passing Java objects from a CICS pooled JVM, OSGi-based JVM, or Axis2 JVM
Passing Java objects from a CICS pooled JVM, OSGi-based JVM, or Axis2-based JVM using the supplied Java class is the same, but how you specify where the supplied Java class resides is different for each environment. The DDW_CicsObjectTransporter object provided with this article lets you LINK to a target Java program named TARGET, passing objects by using the following approach:
String abc = "Some information to Pass";
Employee emp = new Employee("John Doe");
DDW_CicsObjectTransporter transporter =
new DDW_CicsObjectTransporter();
transporter.addObject("abc",abc).
addObject("emp",emp).
execute("TARGET");
// and after the program returns
String errorString = (String)transporter.getObject("error");
If (errorString != null) {
processError();
} else {
Manager newManager = (Manager)transporter.getObject("mgr");
// process/display Manager object that was returned
}
|
In the DDW_CicsObjectTransporter class provided with this article, when responding to the code example above:
- The provided
DDW_CicsObjectTransporterclass (the transporter) uses a channel name ofDDWddwObjTrnsptr. If the transporter was passed a channel of this name or the transporter has already created a channel with this name, then it will be used. Otherwise, the transporter will create a channel namedDDWddwObjTrnsptr. Therefore, if you instantiate a second transporter, it will use the same channel namedDDWddwObjTrnsptr, since one will already exist from the first class instance. - The execute() method will cause a LINK request to the specified program.
- When a
addObject(String containerName, Object obj)method is invoked, theobjis serialized and put it in a container whose name iscontainerName. - The transporter verifies that that object reference by
objcontains a field namedserialVersionUID, but the transporter does not verify that the objects referenced byobjcontain aserialVerisionUIDfield. This check does consume CPU cycles, so if you would like to avoid this check, you can invoketransporter.setCheckForSerialVersionUIDBeforeSerialization(false). - If the
getObject(String containerName)method is invoked, the byte array in the specified container is deserialized and the object is returned. The getObject() method returns an object of type Object, so you must typecast the returned Object into the type of object that you are expecting. - If you invoke the
removeObject(String containerName)method, the transporter will invoke adeleteContainer(containerName)method on theDDWddwObjTrnsptrchannel to remove the container. - The convention when using channels and containers for error situations is to return an error container (with some agreed-upon name) with an indication of what caused the error.
Therefore the TARGET business logic program should add an error object to the transporter if it detects an error situation (such as "customer not found"). The above sample code tests for an error container named
error. If it exists, the request had an error, so you would then process the error. If noerrorcontainer is present, the request was successful. - If the remote transporter in the TARGET program has an error serializing or deserializing, or getting, adding, or removing containers, the remote DDW_CicsObjectTransporter throws an exception
and places an error container named
DDWddwObjTErrorMin the channel. If the local transporter finds this error container, any transporter method request will throw an exception stating the cause of the error in the remote transporter. - Likewise, if the local transporter has a problem serializing or deserializing and object, or getting, adding, or removing containers, the transporter throws an exception stating the cause of the error.
Once any error occurs in the transporter, any transporter method request to the transporter will throw an exception stating the original problem. If you don't like this behavior, you can invoke the
transporter.checkForTransporterErrorsInChannel(false)andtransporter.writeTransporterErrorsToChannel(false)methods. - Some of the error messages provided when native Java deserialization has a problem deserializing objects referenced by other objects do not provide a good indication as to the cause of the error. The transporter can only pass along the information that it is given.
- If you have problems with the transporter, you can use the
transporter.setDebugLevel(9)method to have the transporter write messages to the CSMT Transient Data destination (specify 0 if you don't want debug messages -- the larger the debug number, the more detailed the messages). To write to stdout instead of a TD queue, use:transporter.setPrintToTdQueue(false).
If you would like to send the messages to a TD queue other than CSMT, use:transporter.setTdQueueForPring("NAME").
You can also set the debug level in the transporter constructor to see transporter initialization messages. Use:DDW_CicsObjectTransporter transporter = new.
DDW_CicsObjectTransporter(9);
Your CICS-based Java environment will need access to the DDW_CicsObjectTransporter class contained in the com.ibm.ddw.cics.object.transporter.jar file provided with this article:
- For a CICS-pooled JVM environment, add the JAR file to the
CLASSPATH_SUFFIXvariable in your CICS Java PROGRAM's JVMProfile file (PROGRAMs in a pooled JVM environment and JVMProfile files are described in Part 1 of this series). - For a CICS-provided Axis2 JVM environment, package the
com.ibm.ddw.cics.object.transporterpackage with your application. - For a CICS OSGi-based environment, you can take three different approaches to make the object transporter available to your OSGi bundles:
- Include the source code in the
com.ibm.ddw.cics.object.transporterpackage as one of the packages in your OSGi bundle that uses the transporter. - Add the
com.ibm.ddw.cics.object.transporter.jarfile with your application in your bundle's root directory and specify the JAR file location in the CLASSPATH option of your OSGi bundle manifest. - Place the
com.ibm.ddw.cics.object.transporter.jarfile in a common z/OS UNIX System Services file system location and specify the JAR file location in the CLASSPATH option of OSGi bundle's manifest.
- Include the source code in the
The advantage of Option 3 is that you know that all of your OSGi bundles will access the same version of the object transporter code, but if you are concerned with OSGi bundle portability, consider one of the first two options. When deciding between Option 1 or 2, if you want to look at the object transporter as a black box implementation and not deal with source code, use Option 2.
The com.ibm.ddw.cics.object.transporter package cannot be used as a standalone OSGi bundle, and cannot be included in the OSGI_BUNDLES=
parameter in the OSGi JVMServer's JVMProfile file, since the OSGi visibility rules will cause the object transporter to get a ClassNotFoundException when the object transporter tries to deserialize objects.
You could import every package that will use the object transporter into the object transporter's OSGi bundle, but doing so is impractical because you would constantly have to change the object transporter's
OSGi bundle for every new use of the object transporter. The com.ibm.ddw.cics.object.transporter JAR file includes both source and .class files and is included with this article.
Passing Java objects from a CICS dynamic scripting environment
As indicated above, CICS dynamic scripting provides a PHP and Groovy interpreter implemented in Java, and runs in a CICS JVM server.
A PHP-to-Java bridge lets you instantiate and invoke Java classes and methods. You can also instantiate and invoke Java classes and methods using Groovy.
Therefore DDW_CicsObjectTransporter can be used to pass Java objects from a PHP or Groovy script to a CICS-provided pooled or OSGi-based JVM,
thus letting you write your presentation logic in PHP or Groovy, and keep your Java-based business logic in a CICS-pooled or OSGi-based JVM environment.
Although it is not shown below, you can also use Java as a programming language in your CICS dynamic scripting application. Using the object transporter in a Java program running in
a CICS dynamic scripting environment is similar to the object transporter usage for a CICS-pooled JVM environment, except that the com.ibm.ddw.cics.object.transporter.jar file
must be placed in your CICS dynamic scripting application's lib directory, and a zero resolve performed on your application.
Here is a simple example of using DDW_CicsObjectTransporter from a simple PHP script:
<html>
<head><title>Link to a CICS Java program with objects</title></head>
<body>
<?php
try {
// create some Java objects using the PHP to Java bridge
$someString = "some string";
$myManager = new Java('com.ddw.transporter.test.Manager');
$myManager->setManagerName('Roy');
$staffArray = new Java('java.util.ArrayList');
$aStaff = new Java('com.ddw.transporter.test.Staff', "Dennis");
$staffArray->add($aStaff);
$myManager->setStaff($staffArray->toArray());
// transport objects to/from specified CICS Java program
$transporter = new
Java('com.ibm.ddw.cics.object.transporter.DDW_CicsObjectTransporter');
$transporter->addObject("someString", $someString);
$transporter->addObject("myManager", $myManager);
$transporter->execute("PROGRAMB"); // invoke CICS Java program
$responseData = $transporter->getObject("responseData");
echo $responseData;
} catch (Exception $e1) {
echo 'Exception: '.$e1->getMessage();
}
?>
</body>
</html>
|
In the above code example, passing objects is similar to the CICS-provided Axis2, pooled, and OSGi environments.
- You are adding an array of
Staffto aManagerobject, adding theManagerobject to the transporter, and then invoking the CICS Java program namedPROGRAMB. - The try/catch block tests for an exception, but the transporter will only throw a
DDW_CicsObjectTransporterException, so you could have specifically tested for that exception.
To utilize DDW_CicsObjectTransporter in your CICS dynamic scripting application, add com.ibm.ddw.cics.object.transporter.jar
to your application's lib directory and perform a zero resolve.
Receiving Java objects into a CICS-pooled JVM or an OSGi-based JVMServer
You can use the following code with DDW_CicsObjectTransporter to receive Java objects into a CICS-based Java program running in a CICS-pooled JVM or a CICS OSGi-based JVM server:
DDW_CicsObjectTransporter transporter =
new DDW_CicsObjectTransporter();
Employee emp = (Employee)transporter.getObject("emp");
// work with employee object
transporter.removeObject("abc"); // can also remove objects
Manger mgr = new Manger("Joe Bloggs");
transporter.addObject("mgr",mgr); // add new or changed objects
return;
|
In the above code example:
- The provided
DDW_CicsObjectTransporterclass (the transporter) uses a channel name ofDDWddwObjTrnsptr. In this case, since this Java program was invoked from a remote CICS-based Java program by a transporter, the current channel (the channel that was passed to this program) has a name ofDDWddwObjTrnsptr. You can use the transporter'sgetObject(),removeObject(), andaddObject() methods. - Any objects that are added to the transporter will flow back to the LINKing program.
- Although it would be somewhat confusing, you could instantiate a second or third transporter. All transporter instances would use the current channel since it has a name of
DDWddwObjTrnsptr. There would be no conflicts. - Although not shown, you could use the
execute()method to LINK to another Java program in yet another CICS-based Java environment. - The convention when using channels and containers for error situations is to return an error container (with some agreed-upon name) with an indication of what caused the error.
Therefore the LINKed-to program (this program) should add an error container to the channel if an error was encountered. You could add code like this:
String error = "The customer named "+theCustomerName+" was not found");.
transporter.addObject("error", error);
And in the LINKing program you would access the error data like this:String error = (String)transporter.getObject("error");
// null if no ‘error'if (error != null)
{// handle the error here or throw new ApplicationException(error);} - If this transporter has an error serializing or deserializing, or getting, adding, or removing containers, it throws an exception and places an error container named
DDWddwObjTErrorMin the channel. If LINKing program's transporter finds this error container, any requests to that transporter will throw an exception stating the cause of the error in this (the remote) transporter. - If you invoke any methods on this transporter after it has detected a serialization or deserialization problem, it will throw an exception stating the original problem that caused the initial error.
If you don't like this behavior, you can invoke the
transporter.checkForTransporterErrorsInChannel(false)
method and if you don't want to pass transporter errors back to the LINKing program's transporter, invoke thetransporter.writeTransporterErrorsToChannel(false)method. - Some of the error messages provided when native Java deserialization has a problem deserializing objects referenced by other objects do not provide a good indication as to the cause of the error. The transporter can only pass along the information that it is given.
- If you have problems with the transporter, you can use the
transporter.setDebugLevel(9)to have the transporter write messages to the CICS CSMT Transient Data destination. Specify 0 if you don't want debug messages -- the larger the debug number, the more detailed the messages. To write tostdoutinstead of a TD queue, use:transporter.setPrintToTdQueue(false).
If you would like to send the messages to a TD queue other than CSMT, use:transporter.setTdQueueForPring("NAME").
You can also set the debug level in the transporter constructor to see transporter initialization messages. Use:DDW_CicsObjectTransporter transporter = new
DDW_CicsObjectTransporter(9);
Your receiving CICS-based Java environment will need access to the DDW_CicsObjectTransporter class included in the
com.ibm.ddw.cics.object.transporter.jar file provided with this article.
- For a CICS-pooled JVM environment, add the JAR file to the
CLASSPATH_SUFFIXvariable in your CICS Java PROGRAM's JVMProfile file (PROGRAMs in a pooled JVM environment and JVMProfile files are described in Part 1 of this series). - For a CICS OSGi-based environment, you can take three different approaches to make the object transporter available to your OSGi bundles:
- Include the source code in the com.ibm.ddw.cics.object.transporter package as one of the packages in your OSGi bundle that uses the transporter.
- Add the com.ibm.ddw.cics.object.transporter.jar file with your application (in your bundle's root directory) and specify the JAR file's location in the CLASSPATH option of your OSGi bundle manifest.
- Place the com.ibm.ddw.cics.object.transporter.jar file in a common z/OS UNIX System Services file system location and specify the JAR file's location in the CLASSPATH option of OSGi bundle's manifest.
The advantage of Option 3 is that you know that all of your OSGi bundles will access the same version of the object transporter code, but if you are concerned with OSGi bundle portability, consider one of the first two options. When deciding between Option 1 or 2, if you want to look at the object transporter as a black box implementation and not deal with source code, use Option 2.
The com.ibm.ddw.cics.object.transporter package cannot be used as a standalone OSGi bundle, and cannot be included in the OSGI_BUNDLES=
parameter in the OSGi JVMServer's JVMProfile file, since the OSGi visibility rules will cause the object transporter to get a ClassNotFoundException when the object transporter tries to deserialize objects.
You could import every package that will use the object transporter into the object transporter's OSGi bundle, but doing so is impractical because you would constantly have to change the object transporter's
OSGi bundle for every new use of the object transporter. The com.ibm.ddw.cics.object.transporter JAR file includes both source and .class files and is included with this article.
One of the first comments from the subject matter experts who reviewed this article concerned performance. There is a cost to serialize and deserialize objects. When using the provided object transporter, you should benchmark your application early in the development life cycle to verify that your application has the performance characteristics you need. Although passing data between CICS-based Java programs using the traditional field-oriented series-of-bytes approach requires you to run additional utilities and know some details of a procedural language such as COBOL or PL/I, this traditional field-oriented series-of-bytes approach to passing data may perform better.
Error checking was added to the sample transporter provided with this article and most of the error checking is enabled by default. To improve the performance of the provided transporter sample code, you can use the methods listed below to disable some of the error checking. Also, by default, when version mismatch errors are detected, a warning is issued and the transporter continues to function. If you would like the transporter to become disabled if a remote transporter at a different level is detected, use the setStopTransporterActivityIfLocalRemoteVersionsDifferent(true) method.
setCheckForTransporterErrorsInChannel(false); // Don't check for errors from previous requests setCheckForSerialVersionUIDBeforeSerialization(false); // Don't take time to check for serialVersionUID field on objects to be serialized setCheckTheTransporterLevelWithWhichWeAreCommunicating(false); // Don't take time to check if local and remote transporter are at same level |
As indicated before, only use the object transporter when moving between CICS-based Java environments. When staying within a single CICS-based Java environment, use normal Java programming, instantiating objects and invoking methods.
The DDW_CicsObjectTransporter class is intended to implement a technique familiar to the Java application programmer, and to make passing objects simple. Since the object transporter is so easy to use for a Java application programmer, it will be very easy to get really sloppy. If you pass objects that contain more information than you need to pass, or the objects you pass reference other objects that don't need to be passed, you will be wasting time serializing data needlessly and will be transferring extra data needlessly; both of which will increase your response time needlessly.
Debugging object passing issues
You can set the debug message level on the object transporters using an int field with a value of 1 to 9 as an argument to the constructor, or by using the
transporter.setDebugLevel(5) method. The higher the number, the more detailed the messages are. If you want the messages to go to stdout, invoke
transporter.setPrintToTdQueue(false), or else the message will go to the CSMT transient data destination. If you want to change the destination, invoke
transporter.setTdQueueForPrint("ABCD").
You can also set the debug level in the transporter constructor to see transporter initialization messages. Use:
DDW_CicsObjectTransporter transporter = new
.
DDW_CicsObjectTransporter(9);
It is typical in a large CICS environment to distribute your application requests across multiple CICS regions for availability and scalability. CICS normally performs workload distribution on a by-program basis. Since techniques described in the article provide an easy way to pass objects to a CICS-based Java program, you could use these Java object passing techniques and still have CICS perform workload distribution of your Java programs.
One of the strengths of CICS is its ability to interoperate with business logic written in several different programming languages. The techniques in this article assume that you need to pass data between two CICS-based Java program running in two different CICS-provided Java environments. Since languages other than Java do not understand serialized Java objects, you cannot use the object transporter approach to interoperate with an Assembler, C, C++, COBOL, or PL/I CICS program. Within a CICS environment, to interoperate between Java and Assembler, COBOL, or PL/I, you must move data into a format that can be understood by the Assembler, COBOL, or PL/I program -- a field-oriented series-of-bytes format.
For a discussion of the pros and cons or the detailed aspects of object serialization (either native Java serialization or some of the available open-source serialization/deserialization routines), see the appropriate Java documentation.
This article described the steps for passing Java data objects between Java programs running in the different CICS Java environments that CICS provides:
- Serialize the Java data object into a byte array.
- Place the byte array into a CICS container associated with a channel.
- Invoke the equivalent to the EXEC CICS LINK command to pass the channel holding the containers whose content is the serialized Java data objects
- In the LINKed-to program, get the byte array from the CICS container and deserialize the byte array into a usable Java data object.
Finally, the article described the provided Java classes that implement the techniques described in the article. These Java classes have not been submitted to any official IBM testing and are provided "as-is" solely to illustrate the concepts described in this article. The techniques described in this article will make life easier for the Java application developer, and as in any environment, performance will vary. If you use these techniques, benchmark your results to determine if your application performs at acceptable levels, or whether, instead of using serialized objects, you should convert data from Java data objects to a field-oriented series-of-bytes structure when passing data between your Java programs.
Part 3 will show you how to pass Java data objects from a CICS Transaction Gateway Java client program to a CICS Transaction Server Java environment.
The author would like to thank the following IBM colleagues for their help in reviewing this article and providing suggestions for content and improvement:
- Steve Fowlkes, Certified IT Specialist, CICS Technical Support, IBM USA
- Leigh Compton, Certified IT Specialist, CICS Advanced Technical Skills Team, IBM USA
- Mark Cocker, CICS Technical Strategy and Planning, IBM UK
- Phil Wakelin, CICS Technical Strategy and Planning, Java and Access to CICS, IBM UK
| Description | Name | Size | Download method |
|---|---|---|---|
| Code sample | com.ibm.ddw.cics.object.transporter.zip | 28 KB | HTTP |
Information about download methods
- CICS resources
- CICS information centers
Information centers for all CICS products and tools, including CICS Transaction Gateway and CICS Transaction Server. - CICS family product page
Product descriptions, product news, training information, support information, and more. - CICS Transaction Gateway product page
Product descriptions, product news, training information, support information, and more. - CICS Services
IBM has a comprehensive range of services to help you plan, design, upgrade, secure, manage, and implement CICS solutions within your organization. IBM CICS Services can help you lower your costs, maximize your investment in CICS, and increase your competitive advantage. - IBM Redbook: Introduction to CICS dynamic scripting
The CICS Transaction Server Feature Pack for Dynamic Scripting integrates WebSphere sMash into the CICS TS V4.1 run time, helping you reduce the time and cost of CICS application development. The Feature Pack provides a robust, managed environment for a wide range of situational applications, enabling PHP and Groovy developers to create reports, dashboards, and widgets, integrate CICS assets into mash-ups, and much more. - IBM Redbook: Developing connector applications for CICS
Learn how to develop client applications that connect to CICS using CICS Transaction Gateway. - Additional CICS Redbooks
IBM Redbooks covering basic to advanced topics related to CICS - developerWorks article: Exploiting the J2EE Connector Architecture
Integrating CICS and WebSphere Application Server using XA global transactions -- This article shows you how to use J2EE Connector Architecture (JCA) and CICS Transaction Gateway to provide transactional integration of CICS applications and J2EE components deployed within WebSphere Application Server. - developerWorks article: Exploiting CICS channels and containers from Java clients
Beyond the 32KB COMMAREA limit -- This article shows you how to use channels and containers in CICS, and includes step-by-step coding examples to use the ECIRequest class, together with CICS and Java client samples for use as a standalone Java client.
- CICS information centers
- Additional resources for this article
- More information on Axis2
- More information on Java
- More information on OSGi
- More information on Project Zero
- More information on IBM Rational Application Developer
- IBM Press book: Getting started with IBM WebSphere sMash
- WebSphere resources
- developerWorks WebSphere developer resources
Technical information and resources for developers who use WebSphere products. developerWorks WebSphere provides product downloads, how-to information, support resources, and a free technical library of more than 2000 technical articles, tutorials, best practices, IBM Redbooks, and online product manuals. - developerWorks WebSphere application integration developer resources
How-to articles, downloads, tutorials, education, product info, and other resources to help you build WebSphere application integration and business integration solutions. - Most popular WebSphere trial downloads
No-charge trial downloads for key WebSphere products. - WebSphere forums
Product-specific forums where you can get answers to your technical questions and share your expertise with other WebSphere users. - WebSphere on-demand demos
Download and watch these self-running demos, and learn how WebSphere products and technologies can help your company respond to the rapidly changing and increasingly complex business environment. - developerWorks WebSphere weekly newsletter
The developerWorks newsletter gives you the latest articles and information only on those topics that interest you. In addition to WebSphere, you can select from Java, Linux, Open source, Rational, SOA, Web services, and other topics. Subscribe now and design your custom mailing. - WebSphere-related books from IBM Press
Convenient online ordering through Barnes & Noble. - WebSphere-related events
Conferences, trade shows, Webcasts, and other events around the world of interest to WebSphere developers.
- developerWorks WebSphere developer resources
- developerWorks resources
- Trial downloads for IBM software products
No-charge trial downloads for selected IBM® DB2®, Lotus®, Rational®, Tivoli®, and WebSphere® products. - developerWorks blogs
Join a conversation with developerWorks users and authors, and IBM editors and developers. - developerWorks cloud computing resources
Access the IBM or Amazon EC2 cloud, test an IBM cloud computing product in a sandbox, see demos of cloud computing products and services, read cloud articles, and access other cloud resources. - developerWorks tech briefings
Free technical sessions by IBM experts to accelerate your learning curve and help you succeed in your most challenging software projects. Sessions range from one-hour virtual briefings to half-day and full-day live sessions in cities worldwide. - developerWorks podcasts
Listen to interesting and offbeat interviews and discussions with software innovators. - developerWorks on Twitter
Check out recent Twitter messages and URLs. - IBM Education Assistant
A collection of multimedia educational modules that will help you better understand IBM software products and use them more effectively to meet your business requirements.
- Trial downloads for IBM software products

Dennis Weiand is a Client Technical Specialist for CICS, Web, and Java on the IBM Technical Sales team based in Dallas, TX. You can contact Dennis at dweiand@us.ibm.com.




