This article is part of a series of IBM® VisualAge® for Java™ CCF to WebSphere® Studio J2C migration articles that describe the typical activities for migrating CCF CICS® ECI, IMS™, or WebSphere MQ into J2C applications. This series includes the following articles:
- CCF to J2C migration: Part 1: CCF application limitations on WebSphere Application Server V5
- CCF to J2C migration: Part 2: Overview of migrating VisualAge for Java CCF applications into WebSphere Studio J2C applications
- CCF to J2C migration: Part 3: Migrating VisualAge for Java CCF CICS-ECI applications into WebSphere Studio J2C CICS-ECI applications
- CCF to J2C migration: Part 4: Migrating VisualAge for Java CCF IMS applications into WebSphere Studio J2C IMS applications
Most of this article is conceptually similar to the previous Part 3 (CICS) and Part 4 (IMS) articles, but has several major differences:
- There is no MQ connector in J2C or WebSphere Studio.
- Instead, the application must be migrated to use the J2EE Java Message Service (JMS).
- Optionally, you can use the same CCF Migration Assistant (CMA)
to migrate Records (but NOT MQ Commands).
(using the CMA record limitations and guidelines). - Or, you can manually re-create your Records and FormatHandler HelperClasses using the WebSphere Studio tools.
- Manually migrate your MQ Commands using the MQ/JMS command limitations and guidelines.
- Manually migrate your MQ application using the application limitations and guidelines.
- Enhance your JMS application to use additional JMS features:
- Such as JNDI lookup of MQ Connections and Queues to avoid using hard-coded values.
- Wrapper your JMS Command as an EJB and export it as a WebSphere Studio J2C/WSIF service.
- Allows other current and/or future WebSphere Studio services to exploit it.
- Possible future use of JMS as a transport under J2C (i.e. a JMS connector).
- If/when industry J2C incorporates it (not a statement of committment by anyone).
VisualAge for Java uses the Common Connector Framework (CCF) to simplify the creation and maintenance of Java applications that access host Enterprise Information Systems (EIS's). These EIS resources are typically Customer Information Control System (CICS) transactions, Information Management System (IMS) transactions, or WebSphere MQ message queues. The VisualAge for Java Enterprise Access Builder (EAB) feature supports this CCF framework by providing tools to create CCF connector objects (Java command and record classes), and applications that use these CCF connector objects.
As the value of the CCF framework became recognized and accepted, IBM submitted it for consideration as an industry standard. After review and modification, it became J2EE Connector Architecture (J2C). While J2C is similar to its predecessor CCF, there are significant differences between the two and migration is not trivial. It is desirable to migrate existing VisualAge for Java CCF applications into WebSphere Studio J2C applications whenever there are J2C equivalents. This article covers three main topics:
- CMA migration of EAB tool generated CCF Records (or WebSphere Studio recreation from CopyBooks), and
- Migration of EAB tool generated CCF MQ Commands into JMS Commands, and
- Migration of developer written MQ applications that use those objects into JMS applications.
Important: If you have fewer than 10 or so CCF IMS commands and records, then the best approach is to just manually regenerate the J2C artifacts within WebSphere Studio, and manually migrate your applications. If you more than 100 or so CCF commands and records, then using this article and the CCF Migration Assistant (CMA) is your easiest migration route to WebSphere Studio J2C. If you have between 10 and 100 CCF commands and records, it is recommended that you read this article and then decide which route to take.
If you are concerned about the details of the following steps, or how much effort they will take, IBM WebSphere Services has a range of migration assistance that customers can purchase:
- On-site training or assistance for WebSphere Application Server V3.5 => V4 => V5 application migration
- On-site assessment of CCF application migration, description of work, and scope of effort
- Installation and familiarization with the CCF Migration Assistant (CMA) program
- Pilot migration of small applications or application components
- Optional migration of larger applications
For further information, contact:
- In North or South America: Mitch Johnson via e-mail at mitchj@us.ibm.com or via phone at 1-919-254-0065.
- In Europe or the Middle East: Richard Johnson via e-mail at richardj@uk.ibm.com or via phone at 44-1962-817714.
- In Asia Pacific: Rick Jones via e-mail at at rick.jones@au1.ibm.com or via phone at 61-2-9478-8219.
Best practice for artifact (services) and application (Web or Java) projects
The VisualAge for Java MQ Adder sample has the generated CCF MQ AdderCommand connector artifact, its ExecuteAdder application, and its ExecuteAdderServer MQ server sample together in one project (since in total there are only nine Java files). It also uses the CCF generated AdderRecord artifact from the CICS-ECI sample project. Your specific VisualAge for Java CCF applications may have only one VisualAge for Java project, or many, depending on how your CCF application VisualAge for Java projects are organized.
During migration to WebSphere Studio is the ideal time to ensure your ongoing project structure follows a simple "best practice." We recommend that you have one or more WebSphere Studio service projects to contain groups of related J2C Services, and one or more Web or Java projects to contain your application (typically, one Web or Java project for each major subsystem of your overall application):
- For example, you might have one WebSphere Studio service project, PersonnelServices, containing a group of services accessing CICS personnel programs and IMS personnel programs.
- In addition, you might have one WebSphere Studio Web project, PersonnelWeb, using the PersonnelServices project, an InventoryWeb project using some other InventoryServices project, and an AdminJava project accessing administration programs via both Services projects.
- Together, the collection of these Services and Web or Java projects make up your overall application.
A little logical organization greatly simplifies long-term understanding and maintenance of these projects.
This article describes how to migrate a CCF MQ application into a JMS application. Please read this section very carefully. This article is very detailed, and contains several options. It is carefully structured into sections, each of which matches blocks of your migration activity. If you find yourself getting lost while reading this article (or migrating your applications), please come back and review this section.
- Set up VisualAge for Java and WebSphere Studio Application Developer, Integration Edition.
- Optional: Following the VisualAge for Java instructions to ensure the MQ Adder sample works (if you are going to migrate it).
- Optional: You might also want to set up a small local MQ server for easier local testing
- Export from VisualAge for Java the CCF Record class artifacts (or the original COBOL CopyBooks) and CCF MQ applications source.
- Import and migrate CCF record artifacts (using WebSphere Studio CMA) into J2C artifacts.
- Option 3A: Use the CCF Migration Assistant (CMA) to migrate CCF records.
- Option 3B: Or, use WebSphere Studio tools (Wizard or BulkImporter) to manually re-create Records plus HelperClasses using the COBOL CopyBooks.
- Create JMS Command artifacts (using the JMS Command coding guidelines).
- Option 4A: Use the simplest Command (hardcoded values for Connections and Queues).
- Option 4B: Or, use a more maintainable JNDI Command (JNDI lookup of administered Connections and Queues).
- Import and manually migrate CCF MQ applications
(using the
CCF MQ to JMS application coding guidelines).
- Use the most CCF compatible CompatibilityMethod style.
- Or, use the new J2C invocation style.
- Deploy and test.
- Life-cycle maintenance of the migrated JMS artifacts and applications.
Step 1. Set up VisualAge for Java and WebSphere Studio
- As described in the
CCF Migration Overview
article, ensure that you have VisualAge for Java V3.5.3 or V4.0 set up
appropriately:
- This system must include your CCF MQ applications and generated MQ artifacts (Commands and Records).
- Optional: The system should also include the CCF MQ
Adder sample (if you wish to migrate it as per this
article).

- Recommended: If you are going to migrate the CCF MQ
Adder sample, we strongly suggest you change the
host MQ server program ExecuteAdderServer so that it
stays running for multiple requests, and catches/handles
Exceptions.
while(args.length>=0) { try { // create a command to get a request message with // op1 and op2 from the ADDER.REQUEST queue the command // waits until a message is available in the queue System.out.println("Getting request message..."); GetRequestCommand getRequest = new GetRequestCommand(); // execute the command getRequest.execute(); // get operands op1 and op2 from the message record received int op1 = getRequest.getOp1(); int op2 = getRequest.getOp2(); System.out.println("Request op1=" + op1 + " op2=" + op2); int res = op1 + op2; // create a command to put the reply message PutReplyCommand putReply = new PutReplyCommand(); // pass the request descriptor from the request to the reply, // to make this reply match the request putReply.setRequestDescriptor(getRequest.getRequestDescriptor()); // write the result into the reply message record putReply.setRes(res); // execute the command System.out.println("Putting reply message, res=" + res); putReply.execute(); } catch (Exception e) { System.out.println("AdderServer Exception="+e.getMessage() ); } }
- As per the CCF Migration Overview article, ensure you have WebSphere Studio Integration Edition, Version 5.0.1.1 set up appropriately:
- Ensure the required FixPack and all required
InterimFixes are installed as shown below:
- Note that version 5.01 plus IF7+8 (or later) are
only required if the CMA is being used.
- Note that version 5.01 plus IF7+8 (or later) are
only required if the CMA is being used.
- Attention: CICS (or IMS) J2C RAR: We will be using the CICS (or IMS) J2C service tools to generate our JMS Records and HelperClasses, so you need to install one (or the other, or both) RARs. This article uses the CICS version, but either can be used. You do not end up using any CICS (or IMS) code or run-time features so do not need to worry that you will somehow require them. You will end up with a pure JMS implementation, but with WebSphere Studio J2C service tool generated Records and HelperClasses!
- Follow the installation instructions in the CICS-ECI sample.

Ensure that all required Resource Adapter(s) (CICS for this article) are installed into the appropriate RAR projects (CicsEci, Ims, and Hod3270 projects are shown below):

- Optional: Ensure that the CCF Migration Assistant (CMA) plug-in is installed:
- The
Overview
article describes how to request and obtain the CMA plug-in.
The CMA plug-in is not part of WebSphere Studio and is not supported -- you cannot call IBM Support and request assistance or report problems related to it. - Please allow one to two weeks for:
- Your e-mail to searle@ca.ibm.com requesting the plug-in.
- Our return e-mail containing the "As-Is" license.
- Your return e-mail stating your agreement.
- Our return e-mail containing the current CMA plug-in (or FTP instructions).
- The above steps are necessary to ensure that you understand the that plug-in is provided "As-Is", and to enable us to send you CMA updates if any become available. The screen capture below shows how your plug-in registry will appear after you have installed the CMA plug-in:
- Optional: You might also want to setup a small local MQ server for easier local testing.
Step 2. Export VisualAge for Java CCF artifacts and CCF applications
You can export the CCF artifact classes (and optional source files), plus the CCF application source (and optional classes) all together in one Java Archive (JAR) file. In fact, this is the easiest approach if you are going to follow the unsupported method of importing the artifacts plus applications into WebSphere Studio, and then editing the source and recompiling everything. As noted in the CCF Migration Overview article, this seems to work for most applications, but it is unsupported as it has not been extensively system tested by IBM, and there may be subtle problems due to the different JDK compiler level, different support libraries, etc.
Note that the XxxxBeanInfo HelperClasses are only used within VisualAge for Java and are not needed during migration
Typically, for the CCF Migration Assistant (CMA) migration processes, you would migrate all your CCF generated Record classes into a JAR.
- The XxxxRecord, XxxxRecordType (XxxxRecordInfo)
classes are needed if you are going to use the CMA program to migrate
your CCF Records.
- Or, the original COBOL CopyBooks will be needed if you are going to manually re-create the Records using the WebSphere Studio tools.
- Source Java files can also be included in the exported JAR, but they will be ignored by the CMA program.
- The MQ XxxxCommand and/or any XxxxBeanInfo artifacts can be included in the exported JAR, but they will be bypassed by the CMA program and a warning to this effect will be written into the CMA log.
- It is cleaner to just export the Record and RecordType (RecordInfo) classes.
If you are migrating the CCF MQ Adder sample, you might export the generated CCF Record classes (from the CICS Adder sample project), and optionally the unused MQ AdderCommand, into a JAR named MQadderClasses. Therefore, to export the Adder artifacts:
- Expand the
com.ibm.ivj.eab.sample.eci.adderpackage and right-click to multi-select the required AdderRecord and AdderRecord files. - Optionally also expand the
com.ibm.ivj.eab.sample.mq.adderpackage and right-click to multi-select the non-migrated AdderCommand file. - Then click Export => JAR file => Next => .class (your can leave .java selected if you wish, the CMA will ignore them).
- In the Jar file field type
C:\CCF\MQadderClasses.jarthen click Finish. The CCF artifacts are exported.
Similarly, for the CCF application migration process, you can select
ExecuteAdder and export its one .java source file into
C:\CCF\MQadderExecute.jar.
Note that for this small sample, you may prefer just to export all the
required .class and .java files together into one
C:\CCF\MQadderEverything.jar. This is the
easiest approach if you want to try the unsupported import, then edit and
rebuild within WebSphere Studio.
That said, we will not be using the host server programs (ExecuteAdderServer, GetRequestCommand, PutReplyCommand) at all since they represent the "Host" enterprise server we are accessing, which is not moving. They could simply be included for completeness.
Not supported: WebSphere Studio source import and rebuild of CCF artifacts and applications
Most CCF applications and CCF artifacts seem to properly rebuild in WebSphere Studio and then run successfully on WebSphere Application Server. This is not tested and not supported because of differences in the Java compiler level, other updated libraries, and system API changes. Therefore, one unsupported approach to short-term CCF application maintenance is to install the CCF connectors into WebSphere Studio and WebSphere Application Server (see the previous limitations article, and note that the actual CCF connectors require run-time licenses for installation and use within WebSphere Application Server), and then to export the EAB-generated CCF artifacts (Java source for generated commands and records) into WebSphere Studio.
The Java source for developer-written VisualAge for Java CCF applications, and the generated CCF artifacts, can be exported as a JAR file and then imported into an WebSphere Studio Java project, the same as for any other Java program. You can then use the default WebSphere Studio Java editor to manually edit them, since they are just Java source files, but WebSphere Studio cannot regenerate any CCF artifacts. For example, assuming that you exported all of the VisualAge for Java MQ Adder files into MQadderEverything.jar, then within WebSphere Studio, follow these steps:
- Create a Java Project. Click File => New => Project
=> Java => Java project => Next, then for
Project Name type
CCFadderMQ, and click Finish to create the Java project. - Import the CCF source:
- Select the CCFadderMQ project, then click File
=> Import => Zip file => Next.
Browse to your
C:\CCF\CCFadderEverything.jar, and click Finish to populate the Java project. - If you had exported the XxxxBeanInfo files (AdderRecordBeanInfo or AdderCommandBeanInfo PutReplyCommandBeanInfo or GetRequestCommandBeanInfo) then you can select them and delete them.
- Select the CCFadderMQ project, then click File
=> Import => Zip file => Next.
Browse to your
- Eliminate errors due to dependencies:
- Your MQ CCF applications need the MQ CCF connector
mqccf.jar to build and run. You could create a
project MqCcf and store it there for shared usage, but
since we only have one CCF MQ project it is easiest just to
import it (as a File system file) into this
CCFadderMQ project.
- Note: The mqccf.jar jar you need was
installed during your VisualAge for Java connector
install (typically into
"
C:\IBM Connectors\classes\mqccf.jar").
- Note: The mqccf.jar jar you need was
installed during your VisualAge for Java connector
install (typically into
"
- Now click the Libraries tab. The mqccf.jar, plus
the WebSphere Application Server run-time 4 main CCF jars
(ccf.jar, eablib.jar, j2ee.jar, recjava.jar),
should all be on the build path. This screen capture shows all
the entries that should be on your build path, and you should
have no compile errors in your Tasks view.

- Your MQ CCF applications need the MQ CCF connector
mqccf.jar to build and run. You could create a
project MqCcf and store it there for shared usage, but
since we only have one CCF MQ project it is easiest just to
import it (as a File system file) into this
CCFadderMQ project.
- Execute - Just right-click the AdderExecute class and select to
Run it. You should have a successful CCFadderMQ execution
in the Console view.
- Note that we chose to keep the 3 MQ host server programs
(ExecuteAdderServer and so on) in this project since
they could also be maintained this way).

- Note that we chose to keep the 3 MQ host server programs
(ExecuteAdderServer and so on) in this project since
they could also be maintained this way).
- Deploy and Test - You could also deploy the re-compiled CCFadderMQ application (plus the required CCF run-time JARs) to a remote workstation, and run it.
Step 3. Migrate CCF records into J2C using CMA (or re-create from CopyBooks)
- Import the CCF artifacts as a File system file (to keep them as a JAR) into the desired Service project:
- Option 3A: For CMA migration, you must import the VisualAge for Java exported Record artifact JAR.
- Option 3B: Or, for WebSphere Studio recreation, you must import the VisualAge for Java (or original) COBOL CopyBooks.
- Migrate these CCF artifacts into J2C artifacts:
- Option 3A: Migrate CCF Records using the CMA program.
- Option 3B: Or, re-create J2C Records and FormatHandler HelperClasses from COBOL CopyBooks.
- Finally, normal ongoing life-cycle maintenance within WebSphere Studio.
1. Option 3A: Import CCF Records JAR into WebSphere Studio Service project
- WebSphere Studio CMA plug-in: Ensure that it was installed during WebSphere Studio Setup.
- WebSphere Studio CICS RAR project: Ensure that it was installed during WebSphere Studio Setup.
- Note that this is only needed to run the WebSphere Studio tools to manually re-create Records (instead of migrating them using CMA).
- Note that this does NOT require any CICS code or run-time in the final JMS application.
- Create the desired J2C Service project:
- Click File => New => Project => Business
Integration => Service Project => Next, and
then for the Project Name type
JMSadderServiceand click Finish. - Import CCF artifact JAR (as a file system file):
- Select your new JMSadderService project, and click File
=> Import => File system => Next.
Browse to your C:\CCF\MQadderClasses.jar file and click
Finish to import and retain it as a JAR.

- Now you can skip down to CMA migrate records.
1. Option 3B: Import COBOL CopyBooks into WebSphere Studio Service project
- Create the desired J2C Service project: Click File => New
=> Project => Business Integration => Service
Project => Next, then for Project Name type
JMSadderServiceand click Finish. - Import the VisualAge for Java (or original) COBOL CopyBook (as
a file system file): Select your new JMSadderService project,
and click File => Import => File system =>
Next. Browse to your
C:\vaj40\eab\samples\com\ibm\ivj\examples\eab\adder\adder.ccp
file and click Finish to import and retain it as a JAR.

- Now you can skip down to WebSphere Studio re-create records.
2. Option 3A - CMA migrate CCF Records into J2C (Service) Records
- Select the MQadderClasses.jar, right-click it, and click Migrate CCF artifacts.
- VisualAge for Java can generate code using several different styles
for accessor methods. However, we will not use the resulting (CICS)
Command so the migration style does not matter. Select the
default shorten names compatibility option radio button and
click Next.

- Again, we will not use the resulting (CICS) Command so the JNDI
option does not matter. Select Do not generate JNDI Name entry,
and click Finish.

- The CMA migration proceeds, and finishes (with a warning dialog)
The warning dialog is because the CCF MQ Command cannot be migrated (there is no J2C MQ connector, hence the Command is invalid and cannot be instantiated or migrated). Always carefully read any error or warning dialogs, but this one is acceptable.
The result is DummyCommand00000, AdderRecord, and AdderRecordFormatHandler Java classes, and WSDL meta-data files, all being created.

At this point there are useful Record plus Format Handler
HelperClasses for the MQ Adder program, but the
"DummyCommand00000" is only for CICS and is not useful to us
(we need to manually create a JMS Command in the next
Create JMS Command section). You can delete
the 3 WSDL files (since they are only useful for creating CICS
Service Proxies), and the DummyCommand00000 file, but first look at
it and notice that all its methods are suitable only for a J2C style
Service Proxy (which it is, a CICS one), and the execute method
contents are entirely J2C specific. 
2. Option 3B: Use WebSphere Studio to re-create J2C Records from COBOL CopyBooks
Note: If you used the previous section to CMA migrate CCF Records (instead of WebSphere Studio tools to re-create the Records skip to Step 4. Commands
You must have exported the original COBOL (or C) host record CopyBooks from VisualAge for Java, or you must copy them down again from the host server. Then, you can use the WebSphere Studio tools to process them and create J2C (Service) Records and FormatHandler HelperClasses (as if you were creating a CICS or IMS Service). Unfortunately, the resulting AdderCommand files are not useful to us.
The basic steps to re-create the Records as J2C (Service) artifacts are:
- Create a CICS (or IMS) J2C Service Proxy for a (Dummy) Command.
- Add one (or more) new Operations to it.
- During the new Operation creation, specify the CopyBooks to be used for input and/or output.
- Be careful to select the correct platform, encoding, etc.
- Delete the unnecessary (Dummy) Command and WSDL files.
- Keep the Records and FormatHandler HelperClasses (that's why we did this).
The following instructions are sufficient for the Adder example - they are not intended as an explanation of the details of WebSphere Studio tools (for that, refer to the WebSphere Studio documentation and samples).
- We will use the same JMSadderService Service project we created in the previous "Import" section.
- Note: If you ran the CMA program to migrate the MQ
Adder artifacts in the last section, then delete the
entire "
com.ibm.ivj..." tree in the JMSadderService project. - Create a Java package to hold our new J2C artifacts by clicking
File => New => Package and then for
Name type
com.ibm.studio.sample.jms.adderand click Finish. We are now ready to create our J2C artifacts.
- Create a CICS Service Proxy by clicking File => New
=> Business Integration => Service built from ...
=> Next => CICS ECI => Next >
(Connection Properties) Next and then for Package type
com.ibm.studio.sample.jms.adderand for Interface Name typeAdder, then click Finish. - When the Service Proxy is created, it opens in the WSDL Editor.
- We need to add an Operation (with a CopyBook) into
it before it is useful.

- Create a new operation within the AdderCICSECIBinding.wsdl
Editor by clicking Bindings (tab) => Available operations
=> New and for Operation name type
adderOperation, then click Next (Binding properties) => Next => Input message => Import. - Import the original host COBOL CopyBook JMSadderservice\adder.ccp
=> Next and select DFHCOMMAREA. Then, for XSD
type name type
AdderRecordand click Finish => Use input message for output => Next => Finish. - Important:If your MQ message is a TextMessage, which most are (rather than a ByteMessage), then just accept the default encodings and MQ will automatically convert the Text as it goes to/from different platforms (i.e. from Windows ASCII to zOS EBCDIC, etc).
- Don't forget to close the editor window (AdderCICSECIBinding.wsdl).
- Generate the Record and FormatHandler HelperClasses by
clicking AdderCICSECIService.wsdl => Enterprise Services
=> Generate HelperClasses. The result is our desired
HelperClasses.
The various WSDL files are CICS specific and are not useful to us. They would normally be deleted at this time. However, we will use them just to demonstrate the resulting (CICS) ServiceProxy Command generation.
This might be very useful to us in the future if the industry J2C standard incorporates JMS as a transport below it (as it is discussing doing), and if WebSphere Studio then adds JMS connectors to its Service Proxy tools. Note that this is NOT an IBM committment nor statement of direction - it is just a note about where the J2C industy standard may be going.
- (Optional) CICS Service Proxy Command generation demonstration.
In the JMSadderService project, click
AdderCICSECIService.wsdl => Enterprise Services
=> Generate Service Proxy. For Class Name type
AdderCommand.java, then click Command bean => newOperation => Finish. - The result is a CICS Command which is almost identital to what the CMA program generated in the previous Option #1 CMA migration approach.
- Two different options to arrive at the same destination - useful
J2C Record and recordformathandler HelperClasses,
unneeded (CICS) Command.

3. Ongoing J2C Record artifact maintenance within WebSphere Studio
Now, you just perform normal ongoing life-cycle maintenance of your J2C Record artifacts with WebSphere Studio.
Step 4. Create JMS Commands (using JMS Command guidelines)
Background: MQ Build and Run-time JARs
Note: No matter which of the Command styles you choose below, you will need to add two MQ build and run-time JARs to your JMSadderService project. As well, you can optionally remove some of the other Services JARs which we will not actually need since we are not actually going to be using a real J2C service. The screen capture belows shows the JARs which you must have.
Right-click the JMSadderService project, then click Properties => Java build path. Click the Libraries tab and click Add External JARs to add the WebSphere Application Server MQ-JMS run-time library JARs com.ibm.mq.jar and com.ibm.mqjms.jar.
Background: Simplified application access to Records (Byte Buffer)
Note: The Command class must have the ability to Send and Receive Messages. However, we can use the WebSphere Studio Service tools to generate Record and FormatHandler HelperClasses that go between Java and COBOL representations and greatly simplify application access to the Message data.
The generic code below shows how to access the message buffers using the WebSphere Studio generated HelperClasses:
try {
// Use the format handler to get to the adder record
AdderRecordFormatHandler InFH = new AdderRecordFormatHandler();
AdderRecord rec = (AdderRecord) InFH.getObjectPart();
// Here is the byte buffer (if direct access is required)
byte [] b = InFH.getBytes();
// Set some values in the adder record (or manipulate directly)
rec.setOp1(123);
rec.setOp2(456);
// Serialize the values into the formathandler
rec.fireElementEvents();
// Do whatever is needed. Typical sequence is:
// ... create session+sender+message+send, create receiver+receive
// process reply
b = new byte[512];
int count = replyMessage.readBytes(b);
// Use the formathandler to deserialize the result
AdderRecordFormatHandler OutFH = new AdderRecordFormatHandler();
OutFH.setBytes( replyMessage.getBytes() );
AdderRecord rec1 = (AdderRecord) OutFH.getObjectPart();
System.out.print( "res..."+rec1.getRes());
} catch (Exception ex ){
ex.printStackTrace();} |
Background: Design of Commands (direct, JNDI, J2C invocation compatible)
You must now manually create your application specific Commands. We provide "Cut-And-Paste" code for the Adder sample which you can readily reuse in your own Commands.
1. You have two alternatives as to how your code locates its MQ Connections and Queues:
- Option 4A: Simply hard-code in the target.
- Option 4B: Or, use JNDI to dynamically look up administered locations (requires a running JNDI server with JMS services).
Note: Which technique you use is purely internal to the Command implementation and is invisible to the invoking application program.
2. You have two alternatives as to how you structure your Commands:
- Make them as CCF Compatible as possible to minimize application migration changes.
- Or, make them J2C Invocation Compatible to be similar what
might be generated if the J2C industry standard
incorporates JMS as a transport and if WebSphere Studio generates
Command Service Proxies for it (remember, this is
NOT an IBM committment nor statement of direction).
Note: We will postpone this option (J2C compatibility) until we discuss application migration since it is directly related to the particular Command Method invocation style used by the application.
Option 4A: Basic (non-JNDI) Command
- Desired Command structure (similar to CCF Command):

- Public "Accessors" - everything except "Execute":
public class AdderCommand { private AdderRecord _adderCommandRequestPart; public int getRes() { return _adderCommandRequestPart.getRes(); } public void setOp1(int i) { _adderCommandRequestPart.setOp1(i); System.out.println("Debug: JMSAdderCommand.setOp1="+i); } public void setOp2(int i) { _adderCommandRequestPart.setOp2(i); System.out.println("Debug: JMSAdderCommand.setOp2="+i); } public AdderCommand() { _adderCommandRequestPart = new AdderRecord(); }
- Main callable "Execute":
public void execute() throws JMSException { // ### set RequestMessage AdderRecordFormatHandler handler = new AdderRecordFormatHandler(); handler.setObjectPart(_adderCommandRequestPart); _adderCommandRequestPart.fireElementEvents(); try { // #### sendMessage and WaitResponse String reply = sendMessageWaitResponse( "ADDER.REQUEST", "ADDER.REPLY", handler.getBytes()); // #### get ResponseMessage handler = new AdderRecordFormatHandler(); handler.setBytes(reply.getBytes()); _adderCommandRequestPart = (AdderRecord)handler.getObjectPart(); } catch (Exception e) { String msg = e.getMessage(); if(e instanceof JMSException) { msg = ((JMSException)e).getLinkedException().getMessage(); } System.out.println("JMSAdderCommand.executeMQ Exception="+msg); } }
- Internal "SendMessage and WaitResponse":
private String sendMessageWaitResponse( String REQname, String REPname, byte[] messageBytes) throws JMSException { QueueConnection conn = null; QueueSession session = null; try { // ### getConnection conn = getConnection(); conn.start(); // ### getQueues Queue queue = getQueue(REQname); Queue replyQueue = getQueue(REPname); // ### createQueueSession and createTextMessage session = conn.createQueueSession( false, Session.AUTO_ACKNOWLEDGE); QueueSender sender = session.createSender(queue); TextMessage message = session.createTextMessage( new String(messageBytes)); message.setJMSReplyTo(replyQueue); // ### send message sender.send(message); // ### createReceiver and receive replyMessage QueueReceiver rcvr = session.createReceiver(replyQueue); BytesMessage replyMessage = (BytesMessage)rcvr .receive(25000); byte[] b = new byte[512]; int count = replyMessage.readBytes(b); // ### return replyMessage return (replyMessage != null) ? new String(b) : null; } catch (JMSException e) { if (session != null) session.close(); if (conn != null) conn.stop(); conn.close(); throw e; } }
- Internal "GetConnection":
private QueueConnection getConnection() throws JMSException { QueueConnectionFactory fact; QueueConnection connection; try { MQQueueConnectionFactory factory = new MQQueueConnectionFactory(); factory.setCCSID(819); // hardcoded factory.setChannel("SYSTEM.AUTO.SVRCONN"); // hardcoded factory.setHostName("bcsearle.torolab.ibm.com"); // hardcoded factory.setPort(1414); // hardcoded factory.setQueueManager("QM_bcsearle"); // hardcoded factory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP); // hardcoded QueueConnection conn = factory.createQueueConnection(); System.out.println("Debug: QueueConnection=" + conn); return conn; } catch (JMSException e) { System.out.println("JMSAdderCommand.getConnection Exception=" + e); throw e; } }
- Internal "GetQueue":
private Queue getQueue(String queueName) throws JMSException { MQQueue queue = null; try { queue = new MQQueue(); queue.setBaseQueueName(queueName); queue.setBaseQueueManagerName("QM_bcsearle"); // hardcoded queue.setCCSID(819); // hardcoded queue.setTargetClient(JMSC.MQJMS_CLIENT_NONJMS_MQ); // hardcoded System.out.println("Debug: Queue=" + queue); return queue; } catch (JMSException e) { System.out.println("JMSAdderCommand.getQueue Exception=" + e); throw e; } }
Option 4B: Enhanced (JNDI) Command
By using JNDI to look up the Connection and Queue values, the code is easier to maintain. However, it requires that a JNDI server (such as the one included in WebSphere Application Server) be running, and that it be configured to contain the desired values. Also, that JNDI server must also be a JMS provider (which WebSphere Application Server is) in order create the desired resource during JNDI lookup.
- WAS adminconsole setup of JNDI for ConnectionFactory:

- WAS adminconsole setup of JNDI for RequestQueue
(TargetClient=MQ bug discussed later):

- Similar WAS adminconsole setup of JNDI for ReplyQueue -
essentially identical, just use
ADDER.REPLYinstead ofADDER.REQUEST - Depending on what Version and ServicePack of WebSphere Application
Server adminconsole is being run, there is a bug where the
preceeding TargetClient=MQ is not saved. The administrator must
manually edit
resource.xmlto inset the correct data (typically within WebSphere Studio this file is "MyServersProject\MyBaseV5Server.wsc\cells\localhost\nodes\localhost\resources.xml").<factories xmi:type="resources.jms.mqseries:MQQueue" xmi:id="MQQueue_1" name="MQ.ADDER.REQUEST" jndiName="mq/MQ.ADDER.REQUEST" description="MQ.ADDER.REQUEST" persistence="QUEUE_DEFINED" priority="QUEUE_DEFINED" expiry="APPLICATION_DEFINED" baseQueueName="ADDER.REQUEST" baseQueueManagerName="QM_bcsearle" useNativeEncoding="true" integerEncoding="Normal" decimalEncoding="Normal" floatingPointEncoding="IEEENormal" targetClient="MQ" queueManagerHost="bcsearle.torolab.ibm.com" queueManagerPort="1414" serverConnectionChannelName="SYSTEM.AUTO.SVRCONN"/> <factories xmi:type="resources.jms.mqseries:MQQueue" xmi:id="MQQueue_2" name="MQ.ADDER.REPLY" jndiName="mq/MQ.ADDER.REPLY" description="MQ.ADDER.REPLY" persistence="QUEUE_DEFINED" priority="QUEUE_DEFINED" expiry="APPLICATION_DEFINED" baseQueueName="ADDER.REPLY" baseQueueManagerName="QM_bcsearle" useNativeEncoding="true" integerEncoding="Normal" decimalEncoding="Normal" floatingPointEncoding="IEEENormal" targetClient="MQ" queueManagerHost="bcsearle.torolab.ibm.com" queueManagerPort="1414" serverConnectionChannelName="SYSTEM.AUTO.SVRCONN"/>
- New JNDI InitialContext with hard-coded options (we just see the
system default):
private static InitialContext _initialContext = null; private InitialContext getInitContext() throws NamingException { if(_initialContext == null) { //############################################################## // Hashtable env = new Hashtable(); // env.put(Context.INITIAL_CONTEXT_FACTORY, // com.ibm.websphere.naming.WsnInitialContextFactory"); // env.put(Context.PROVIDER_URL, "corbaloc:iiop:localhost:2809"); // String NAME_SYNTAX = "com.ibm.websphere.naming.name.syntax"; // String NAME_SYNTAX_JNDI = "jndi"; // env.put(NAME_SYNTAX, NAME_SYNTAX_JNDI); // _initialContext = new InitialContext(env); //############################################################## _initialContext = new InitialContext(); } return _initialContext; }
- Enhanced JNDI Execute (passes in ConnectionFactory JNDI name):
public void execute() throws JMSException { // ### set RequestMessage AdderRecordFormatHandler handler = new AdderRecordFormatHandler(); handler.setObjectPart(_adderCommandRequestPart); _adderCommandRequestPart.fireElementEvents(); try { // #### sendMessage and WaitResponse String reply = sendMessageWaitResponse( "mq/MQ.ADDER.CF", "mq/MQ.ADDER.REQUEST", "mq/MQ.ADDER.REPLY", handler.getBytes()); // #### get ResponseMessage handler = new AdderRecordFormatHandler(); handler.setBytes(reply.getBytes()); _adderCommandRequestPart = (AdderRecord)handler.getObjectPart(); } catch (Exception e) { String msg = e.getMessage(); if(e instanceof JMSException) { msg = ((JMSException)e).getLinkedException().getMessage(); } System.out.println("JMSAdderCommand.executeMQ Exception="+msg); } }
- Enhanced JNDI SendMessage and WaitReply (passes ConnectionFactory JNDI
name through to GetConnection):
private String sendMessageWaitResponse( String CFname String REQname, String REPname, byte[] messageBytes) throws JMSException { QueueConnection conn = null; QueueSession session = null; try { // ### getConnection conn = getConnection(CFname); conn.start(); // ### getQueues Queue queue = getQueue(REQname); Queue replyQueue = getQueue(REPname); // ### createQueueSession and createTextMessage session = conn.createQueueSession( false, Session.AUTO_ACKNOWLEDGE); QueueSender sender = session.createSender(queue); TextMessage message = session.createTextMessage( new String(messageBytes)); message.setJMSReplyTo(replyQueue); // ### send message sender.send(message); // ### createReceiver and receive replyMessage QueueReceiver receiver = session.createReceiver(replyQueue); BytesMessage replyMessage = (BytesMessage)receiver .receive(25000); byte[] b = new byte[512]; int count = replyMessage.readBytes(b); // ### return replyMessage return (replyMessage != null) ? new String(b) : null; } catch (JMSException e) { if (session != null) session.close(); if (conn != null) conn.stop(); conn.close(); throw e; } }
- Enhanced JNDI GetConnection (uses JNDI ConnectionFactory lookup name):
private QueueConnection getConnection(String connName) throws JMSException { QueueConnectionFactory fact; QueueConnection connection; try { fact = (QueueConnectionFactory) getInitContext() .lookup(connName); connection = fact.createQueueConnection(); System.out.println("JNDI ConnectionFactory="+fact ); return connection; } catch (NamingException e) { System.out.println("getConnection NamingException="+e.getMessage() ); throw new JMSException( e.getMessage() ); } }
- Enhanced JNDI GetQueue (uses JNDI Queue lookup name):
private Queue getQueue(String queueName) throws JMSException { MQQueue queue = null; try { queue = (MQQueue) getInitContext() .lookup(queueName); System.out.println("JNDI Queue="+queue); return queue; } catch (NamingException e) { System.out.println("getQueue NamingException="+e.getMessage() ); throw new JMSException( e.getMessage() ); } }
- Important: Although everything builds correctly, you may encounter obscure JNDI runtime errors. You must add the required JNDI run-time support JARs to your build and run-time classpath:
- Right-click the JMSadderExecute project, then click
Properties => Java build path. Click the
Libraries tab and click Add External JARs to add
the WebSphere Application Server run-time library JARs
namingclient.jar, messagingImpl.jar and the
WAS_V5_IMPL_FACTORY_PROP CLASSPATH_VARIABLE.

We now have a valid Command, and the previous Record and FormatHandler HelperClasses, but we still need to migrate an application (Step 5 below) which actually uses it.
Step 5. Migrate CCF MQ applications to use JMS artifacts (using migration coding guidelines)
- Import the VisualAge for Java exported MQ application JAR.
- Modify the CCF MQ application to use the migrated JMS artifacts using the CCF to JMS application guidelines.
- The quickest migration invokes CCF Compatibility Methods in the Commands.
- Enhancement-5A: Or, for possible future J2C JMS Services compatibility, invoke J2C Style Methods in the Commands.
1. Import CCF MQ applications into Java (or Web) projects
- Create the desired application Web or Java project(s):
- Click File => New => Project => Java
=> Java Project => Next , then for the
Project Name type
JMSadderExecuteand click Finish. - Click Next and click the Projects tab. Select JMSadderService and click Finish. This adds the build and run-time dependent JMSadderService project.
- Import the CCF application from its JAR file:
- Select your new JMSadderExecute project.
- Click File => Import => Zip file =>
Next, then browse to your
C:\CCF\MQadderExecute.jarfile. - Click Open => Finish to import the application (just
one AdderExecute.java file for the MQ Adder sample).

2. Migrate application using CCF MQ to JMS Application Guidelines
- Because we chose to change our JMSadderService Record and
Command code to be in the renamed
com.ibm.studio.sample.jms.adderpackage, our application has errors. It cannot resolve those names (since AdderExecute is still incom.ibm.ivj.eab.sample.mq.adder). For consistency, we will rename the package (refactor it) to match the new name: - In line one (the Package declaration), select
com.ibm.ivj.eab.sample.mq.adder. - Right-click and click Refactor => Rename. Type
the new name
com.ibm.studio.sample.jms.adder. - Click Finish.

- One typical error (shown below) is due to requiring build and run-time
access to javax.jms.JMSException and other JMS classes:

- A typical time-saver is to define a workbench environment variable
(to do so, click Window => Preferences => Java
=> Classpath Variables, then click New and
name it
WAS_50_PLUGINDIR) to permit adding Library JARs as Add Variable => Extend => WAS_50_PLUGINDIR\lib extensions. - Right-click the JMSadderExecute project, then click
Properties => Java build path. Click the
Libraries tab and click Add External JARs to add
the WebSphere Application Server run-time library JAR
j2ee.jar.

- Another standard set of errors (shown below) requires removing all old
com.ibm.connector.* imports.

- Another standard set of errors (shown below) requires removing all old
JavaRuntimeContext code (there are 3 RuntimeContext
lines to be commented out in our sample).

- Another set of standard errors (shown below) requires
javax.jms.JMSException handling. This also requires adding
an import javax.jms.JMSException statement.
// execute the command and get the result System.out.println("Executing the Adder command, op1=" +op1+" op2="+op2+" ..."); try { adder.execute(); } catch (JMSException e) { System.out.println("JMSException="+e.getMessage() ); } System.out.println("Adder result: " + adder.getAdderCommandRequestPart().getRes());
- Best Practice: The outermost code catches JMSException
(from Command.execute()), but generally it must also catch
other exceptions including Exception. A JMSException, by
itself, is typically not very informative. Since it includes a
LinkedException, that should be obtained and displayed as
it will be more informative (it is the real error). A best practice is
to always try to extract the most informative message from any caught
Exception.
// execute the command and get the result System.out.println("Executing the Adder command, op1=" +op1+" op2="+op2+" ..."); try { adder.execute(); } catch (Exception e) { String msg = e.getMessage(); if(e instanceof JMSException) { JMSException je = (JMSException)e; Exception le = je.getLinkedException(); msg = le.getMessage(); } System.out.println("Exception="+msg ); } System.out.println("Adder result: " + adder.getAdderCommandRequestPart().getRes());
3. Enhancement-5A: J2C style invocations
The J2C desired Command structure (with J2C style methods):
New J2C invocation style methods (to replace deprecated CCF methods):
public void setAdderCommandRequestPart(Object record) {
_adderCommandRequestPart = (AdderRecord)record;
}
public AdderRecord getAdderCommandRequestPart() {
return _adderCommandRequestPart;
} |
Working with J2C style invocation:
- A standard set of deprecation warnings (shown below) relates to the
new J2C command invocation style.
The CCF to JMS Application guidelines describe standard application changes needed to manipulate Commands and Records using the J2C invocation style. - You might chose to put CCF Compatibility Methods into your Commands to minimize short-term application changes (to speed initial CCF to J2C application migration). Application usage of such short-term (deprecated) CCF compatibility methods should be removed during application life-cycle maintenance to use the current J2C invocation style.
- Important:This whole concept of J2C invocation style only applies if you care about J2C invocation compatibility because you believe that you may change to J2C generated Commands in the future (for example if/when JMS becomes a transport under J2C, and if/when J2C tools generate Service Proxies for it).
- For example, the old CCF Command.setOperand() plus Command.execute(CommandEvent) pattern is deprecated:
- Best J2C practice is the new J2C invocation new Record() plus Record.setOperand() plus Command.setAdderCommandRequestPart(Record) plus Command.execute()
- Another example, the old CCF Command.getRes() pattern is
deprecated:

- Best J2C practice is the new J2C invocation
Command.getAdderCommandRequestPart().

- Important: Adding the above J2C invocation style also requires that the standard J2C/WSIF JARs be added to the JMSadderExecute build and run-time classpath (in addition to the previous JNDI run-time jars).
- Right-click the JMSadderExecute project, then click
Properties => Java build path. Click the
Libraries tab and click Add External JARs to add
the WebSphere Application Server run-time library JARs
wsatlib.jar, wsif-j2c.jar, and wsif.jar.

- After removing all the commented out code, the basic code now looks
like this:
public static void main(java.lang.String[] args) { int op1 = 10; int op2 = 20; if(args.length>=1) { String s = args[0]; op1 = Integer.parseInt(s); s = args[1]; op2 = Integer.parseInt(s); } System.out.println("Sample program to demonstrate" +" commands using the MQ connector."); System.out.println("Adder client program."); // create a command that uses the SEND_RECEIVE mode the // command will put a request message with op1 and op2 // to the ADDER.REQUEST queue, then get the reply // message (with a result from ExecuteAdderServer) // from the ADDER.REPLY queue. AdderCommand adder = new AdderCommand(); AdderRecord record = new AdderRecord(); record.setOp1(op1); record.setOp2(op2); adder.setAdderCommandRequestPart(record); // execute the command and get the result System.out.println("Executing the Adder command, op1=" +op1+" op2="+op2+" ..."); try { adder.execute(); } catch (JMSException e) { Exception le = e.getLinkedException(); System.out.println("JMSException="+le.getMessage() ); } System.out.println("Adder result: " + adder.getAdderCommandRequestPart().getRes()); }
Step 6. Deploy and test (execute) the migrated application)
If your build and run-time classpath is set up correctly, you can now just run the migrated JMS application:
- Open the ExecuteAdder.java program and click Run.

- Important: During AdderExecute application execution, if
the Run => Classpath => Use default classpath
option is not selected, then you may get an error like this:
"
codepage-437 not available". Ensure you are running the file with the default classpath (which includes full codepage support). You need to ensure a full JDK is being used and not just a stripped down system JVM JRE. - The IBM JDK contains the
jre\lib\codepage.jarfile with many ByteToCharCpXxxx classes, including ByteToCharCp437.class - The Sun JRE contains the
lib\rt.jarfile with only 6 ByteToCharCp125X.classes - Important: During AdderExecute application execution, if you are using JNDI and your JMSadderService JNDI build and run-time classpath is not set up correctly you may get frustrating and obscure errors such as the following:
- Missing namingclient.jar causes
"
NamingException=Need to specify class name in environment or system property, java.naming.factory.initial".
Note: Even specifying "-DinitialContextFactory=com.ibm.websphere.naming.WsnInitialContextFactory" will not solve this misleading error. - Missing JNDI server (not running) causes
"
NamingException=Could not obtain an initial context due to a communication failure". - Missing messagingImpl.jar causes
"
NamingException=Failed to initialize the ORB". - Missing WAS_V5_IMPL_FACTORY_PROP causes
"
NamingException=Could not obtain an initial context due to a communication failure. Since no provider URL was specified, ...". - Missing messagingImpl.jar (and also incorrectly having
namingserver.jar) causes
"
Exception=javax.naming.Reference".
Other JMS application variations (Web, ApplicationClient)
We won't go through all the details here, but you could create a Web or an ApplicationClient J2EE project (which both need to be in an Enterprise Application (EAR) project) and simply have them call AdderExecute:
- To try an ApplicationClient, just create an Application
Client Project and then export JARs of the
JMSadderService and JMSadderExecute projects into
it. Create a WebSphere v5 Application Client Launch
Configuration to launch it, using Main class set to
com.ibm.studio.sample.jms.adder.ExecuteAdder, and then launch it.
- To try a Web, just create a Web Project and then export
JARs of the JMSadderService and JMSadderExecute projects
into it. Also create a JSP to invoke JMSadderExecute and then
select that JSP and click Run on Server ...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML> <HEAD> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" %> <LINK href="theme/Master.css" rel="stylesheet" type="text/css"> <TITLE>JMSadderExecuteWeb.jsp</TITLE> </HEAD> <%@ page import="com.ibm.studio.sample.jms.adder.ExecuteAdder" %> <BODY> <P>INVOKE ExecuteAdder ....</P> <% ExecuteAdder exec = new ExecuteAdder(); String[] args = {"12", "34"}; exec.main(args); %> <P>DONE.R ExecuteAdder (output is in CONSOLE VIEW)</P> </BODY> </HTML>
Step 7. Ongoing life-cycle migrated application maintenance within WebSphere Studio
Now, you just perform normal ongoing life-cycle maintenance of your JMS application within WebSphere Studio. One special consideration is if you used the CCF Compatibility Methods style invocation to speed your initial application migration, then you should replace them with the normal J2C style command and record invocations whenever convenient. They can be done a few at a time since both invocation styles work.
CMA limitations and guidelines
It is intended that this section of this article may be updated if or when significant new JMS CMA limitations or guidelines are discovered. Note: The CMA plug-in contains online documentation, and that online documentation is always the best, most detailed, and most current definition of known CMA limitations, issues, and guidelines.
The currently known most significant JMS specific CMA limitations and guidelines can be summarized as follows:
- Only migrates Records, cannot migrate MQ Commands (since there is no J2C MQ or JMS connector).
The currently known, most significant generic CMA limitations and guidelines can be summarized as follows:
- CCF IMS (or CICS-ECI, or Beta-JCA) artifacts only (see CICS-ECI article for CICS-ECI specifics), no CICS-EPI nor HOD-3270 nor MQ commands.
- COBOL records only (no C nor PL/I).
- Fixed-length and Dynamic Records must use the normal generated accessors (any base framework access requires manual migration).
- Must have a RecordType (RecordInfo) for all Records (otherwise they are skipped and need manual migration).
- Only the Default Mapping is supported for RecordTypes (a changed preferred type requires manual migration).
- No hierarchical style Records (manual migration required).
- Custom Methods in CCF Commands are not preserved (need to be manually copied).
- No CCF Navigator migration (manual migration required, likely to Processes).
- No CCF Mapper migration (manual migration required, likely to Transformers).
- No EAB SessionBean nor BusinessObject migration (manual migration required).
- If EAB SessionBeans were generated using Command wrappering, those Commands can be migrated, and deploy code generated within WebSphere Studio.
- If EAB SessionBeans were generated using CustomUserMethods, all code was inline and used user method names, so no automated migration is possible
- If matching SessionBeans are manually regenerated within WebSphere Studio, then user applications should migrate easily and typically require no SessionBean invocation changes
- CCF Commands generated with promote Record properties may require manual application changes.
- Group and export CCF artifacts by server and transaction name (CMA assumes common JNDI ConnectionFactory).
- Group and export CCF artifacts by name style (CMA assumes single name style throughout CCF JAR).
- The CMA and its documentation is English Only (it is not a production product).
- The CMA is officially unsupported and provided AS-IS (you cannot call IBM Support nor report PMR problems).
- Remember: The CMA online documentation is the ultimate source
for limitations and guidelines. If in doubt, consult it, not this
article (which may have become out of date).

Application limitations and guidelines
It is intended that this section of this article may be updated if or when
significant new JMS application limitations or guidelines are
discovered.
Note: The CMA plug-in contains online
documentation, and that online documentation is always the best, most
detailed, and most current definition of known application limitations,
issues, and guidelines.
The currently known most significant JMS specific application limitations and guidelines can be summarized as follows:
- See also the JMS Application Resources section.
- Catch JMSException (instead of old CCFException). Also, extract its embedded LinkedException for the real error.
- If your MQ message is a TextMessage, which most are (rather than a ByteMessage), then when creating the Service Proxy operation and importing the CopyBook, just accept the default encodings and MQ will automatically convert the Text as it goes to/from different platforms (i.e. from Windows ASCII to zOS EBCDIC, etc).
- Transactions:
- When JMS is the only participant in a transaction (i.e. no
database updates), then
local transactions can be used. JMS supports these local transactions via a transacted session, which can be created by a QueueConnection. Transacted sessions manage all messages sent and received until a roll-back or commit operation is performed. Due to the fact that JMS sessions are specific to a connection, in the case of point-to-point MQ messaging, a single session can only deal with queues managed by a single queue manager. - When JMS is not the only participant in a transaction (for
example, there are also database updates), then the Java
Transaction Service (JTS) must be used to control all transacted
resources. JMS resources (such as connection factories) can be
specified as being
XA enabled, which allows the resource to be controlled via the Java Transaction API (JTA). - As mentioned in this article, an applications use of JNDI to acquire JMS resources is desirable from a code and system maintenance standpoint. It must be noted, however, that repeated retrievals of JNDI resources will be a performance drain on the application. In order to avoid repeated JNDI lookups, JMS application code should employ a Resource (JNDI) Caching mechanism.
- An example design pattern for such a mechanism, the Service Locator, can be found at the Sun Web page.
- Good communication with your MQ administrator is necessary in order to enusre you obtain necessary information such as host names, ports, and channel names. These administrators will also be very helpful in debugging error and return codes.
- In the generic section below, since there is no J2C or JMS connector, nothing related to Commands nor generated CCF Compatibility Methods nor J2C EIS signon applies to JMS.
The currently known, most significant, J2C generic application limitations and guidelines can be summarized as follows:
- Catch WSIFException (instead of old CCFException).
- Initially use new CMA CCF Compatibility Methods (to emulate the old CCF Command superclass hierarchy) to speed short-term application migration.
- These CCF Compatibility Methods within CMA generated Service Proxies provide many of the features from the old CCF Command superclass hierarchy, and simplify the migration of applications which used those deprecated features.
- These CCF Compatibility Methods are added by the CMA into the "user code" section of proxies (i.e. without the "@generated" tag), and therefore that code is retained whenever the same proxies are regenerated within WebSphere Studio Integration Edition.
- Important: To maximize long-term compatibility, during ongoing application maintenance any migrated applications should be changed to use the new J2C style of invocation and stop using the short-term (deprecated) CMA CCF Compatibility Methods.
- Slight changes in DataBean getters and setters (cannot get attribute after command execution, etc).
- No record cloning (can use FormatHandler getBytes() if really needed).
- BigDecimal replaced by int (signature changes, precision may require application rewrite).
- Record field attributes (example length) are not accessible.
- Use new Application Server APIs (new security model, no RuntimeContext, etc).
- Currently cannot catch DataRangeExceptions (under investigation as possible J2C tooling enhancement).
- Subrecords are not always initialized (could cause NullPointerExceptions).
- In J2C there are 2 types of EIS sign-on, component managed and container managed. These types did not exist in the CCF architecture, where the CCF sign-on was more like component-managed sign-on.
- With J2C component-managed sign-on the userID, password and (optional) groupName can be passed in the ConnectionSpec (which is normally not programatically accessible).
- To access the ConnectionSpec, you must modify the WSDL files using the instructions in the WebSphere Studio product Help.
- ... Or, you can associate a component alias with the connection factory (which allows you to provide userID and password).
- Remember: As per the previous CMA section, the CMA online documentation is the ultimate source for limitations and guidelines. If in doubt, consult it, not this article (which may have become out of date).
- IBM product Web page IBM WebSphere MQ
- IBM RedBook: WebSphere Application Server and WebSphere MQ Family Integration
- Sun Web page for Java Message Service
- Sun JMS article Messaging Systems and the Java Message Service (JMS)
- Sun JNDI Resource caching Web page J2EE Patterns - Service Locator Pattern
- JavaWorld article Transaction and redelivery in JMS
WebSphere Studio Application Developer Integration Edition has a completely new set of tools optimized to create and maintain J2C objects and applications. It is desirable to migrate existing VisualAge for Java CCF applications into WebSphere Studio J2C applications whenever there are J2C equivalents. This article has covered three main topics:
- CMA migration of EAB tool-generated CCF records (or WebSphere Studio re-creation from CopyBooks)
- Migration of EAB tool-generated CCF MQ commands into JMS commands
- Migration of developer-written MQ applications that use those objects into JMS applications
Brent Cooley is an Information Technology Specialist for IBM Global Services (Application Innovation Services). He has worked extensively in e-business application design and development and has many years of experience with multi-tiered distributed Web systems, Web-to-legacy system integration, and a variety of Java and J2EE technologies. You can reach Brent at bcooley@us.ibm.com
Ellen Matheson McKay is an Information Developer for IBM Canada Ltd. She writes online help and publications for WebSphere Studio Application Developer. You can reach Ellen at ecmckay@ca.ibm.com

Barry Searle is the Migration Team Leader for WebSphere Studio Application Developer. He is a Professional Engineer who has worked at the IBM Canada Lab for over ten years on various application development tools. Prior to that he had many years of industry experience developing command and control systems and leading communications development projects. You can reach Barry at searle@ca.ibm.com
Comments (Undergoing maintenance)





