This article helps IMS administrators, system programmers, and application programmers who are interested in using Java® within IMS dependent regions. This article highlights and gives examples of the steps needed to deploy Java in IMS dependent regions, including Java Batch Processing (JBP), Java Message Processing (JMP), and Message Processing Program (MPP) regions. The MPP example shows the capability to interoperate between COBOL and Java.

Kevin Hite (khite@us.ibm.com), IMS Solution Test, IBM

Kevin Hite photoKevin Hite is a software engineer working on the IMS Performance Test team. He is involved in integrating, analyzing and tuning the performance of new IMS features in customer-like applications and environments which utilize a wide range of IBM tools and products.



Shavia Jones (jonesps@us.ibm.com), Problem Determination Tools Solution Test, IBM

Shavia Jones photoShavia Jones is a software engineer at IBM's Silicon Valley Laboratory in San Jose, California and works on the Problem Determination Tools Solution Test team. Her role is to develop and execute use cases that exploit the Problem Determination Tools to validate that they work well from a client perspective when used together in a client-like environment.



Neela Mehta (mehtanj@us.ibm.com), IMS Solution Test z/OS System Programming, I.B.M.

Photo of Neela MehtaNeela Mehta is a software engineer working on the IMS Solution Test team. She is involved in integrating new IMS function to customer-like applications in customer-like environments.



Marian Sadowski (sadowski@us.ibm.com), IMS Solution Test, I.B.M.

Photo of Marian SadowskiMarian Sadowski is a software engineer working on the IMS Solution Test team. She is involved in integrating new IMS function to customer-like applications in customer-like environments.



02 December 2010

Introduction

This article describes an approach for using Java within IMS dependent regions. Examples show you how to set up, run, and troubleshoot the following:

  • IMS Java applications in Java Batch Processing regions (JBP)
  • Java Message Processing (JMP) regions
  • Interoperating between COBOL and Java within Message Processing Programs (MPP)

The Java in IMS dependent regions support was provided by requirements delivered using the IMS V10 and V11 service stream and with type-2 APARs (PM02734) (PK86498) and JVM APARs. In addition, the following are required:

  • LE APAR PK99010
  • DB2® driver for JDBC
  • PTF UK52962
  • JDK Version 6.0

The JBP, JMP, and MPP sections of this article are self contained. Some information is repeated in each of the areas, but this is intentional to allow each section to be read independently of the others. Specific roles, including programmer and system administrator, that are associated with activities are indicated with Role: for different areas of the article where appropriate.

Understanding IMS Universal drivers and Java

IMS offers several solutions to develop and extend applications in customer environments using Java. As a part of IMS Versions 10 and 11, IMS provides IMS Universal drivers that includes Java driver support for type-2 connectivity within IMS dependent regions. This support enables customers to develop new applications in Java using the IMS Universal JDBC driver and the IMS Universal DL/I driver.

The IMS Universal drivers are software components that provide Java applications with connectivity and access to IMS databases from z/OS® and distributed environments through TCP/IP. Java applications that use the type-2 IMS Universal drivers must reside on the same logical partition (LPAR) as the IMS subsystem. Java applications that use the type-4 IMS Universal drivers can reside on the same logical partition (LPAR) or on a different LPAR from the IMS subsystem.

JDBC driver

IMS provides a Java Database Connectivity (JDBC) driver for SQL-based database connectivity to access IMS databases over TCP/IP with the IMS Universal JDBC driver that is included in the IMS Universal drivers. The IMS Universal JDBC driver is based on the JDBC 3.0 standard. JDBC is an application programming interface (API) that Java applications use to access relational databases or tabular data sources.

The JDBC API is the industry standard for database-independent connectivity between the Java programming language and any database that has implemented the JDBC interface. The client uses the interface to query and update data in a database. It is the responsibility of the JDBC driver itself to implement the underlying (specific) access protocol for the specific database for which the driver is implemented.

Drivers are client-side adapters, so they are installed in the client machine, not in the server. The drivers convert requests from Java programs to a protocol that the database management system (DBMS) can understand. IMS support for JDBC allows Java applications to issue dynamic SQL calls to access IMS data and to process the result set that is returned in tabular format.

The IMS Universal JDBC driver is designed to support a subset of the SQL syntax with functionality that is limited to what the IMS database management system can process natively. Its DBMS-centric design enables the IMS Universal JDBC driver to fully leverage the high-performance capabilities of IMS. The IMS Universal JDBC driver also provides aggregate function support, ORDER BY support, and GROUP BY support.

JDBC driver type-2 architecture connectivity

Java programs with type-2 JDBC connectivity can run on the same z/OS system or zSeries® logical partition (LPAR) as the target IMS subsystem. The IMS Universal JDBC driver with type-2 connectivity is used to access IMS from IMS Java dependent regions (JDRs), including JMP and JBP regions. When programming, the driverType property must be set to indicate local (type-2) connectivity to IMS.

IMS Universal JDBC driver type-4 architecture connectivity

The IMS Universal JDBC driver with type-4 connectivity is used to access the IMS subsystem through a TCP/IP network connection. With type-4 connectivity, the IMS Universal drivers provide support for the Secure Sockets Layer (SSL) through the Java Secure Socket Extension (JSSE).

IMS Universal DL/I Driver

The IMS Universal DL/I driver is used when there is a need to write granular queries to access IMS databases directly from a Java client in a non-managed environment. Because of the fundamental differences between hierarchical databases and relational databases, sometimes the IMS Universal JDBC Driver does not provide access to the full set of IMS database features.

The IMS Universal DL/I driver is closely related to the traditional IMS DL/I database call interface that is used with other programming languages for writing applications in IMS. The driver provides a lower-level access to IMS database functions than the JDBC API. The IMS Universal DL/I driver provides the capability to build segment search arguments (SSAs) and use the methods of the program communication block (PCB) object to read, insert, update, delete, or perform batch operations on segments. Full navigation control in the segment hierarchy is gained by using the IMS Universal DL/I driver.


Understanding IMS dependent regions and Java

IMS provides address spaces to execute system and application programs that use IMS services. These address spaces are called dependent regions. The dependent regions are started by the submission of JCL to the operating system. The JCL is submitted through a command issued to the IMS control region, through automation, or through a regular batch job submission. After the dependent regions are started, the application programs are scheduled and dispatched by the IMS control region. In all cases, the z/OS address space executes an IMS control region program. The application program is then loaded and called by the IMS code. Up to 999 dependent regions can be connected to one IMS control region.

Dependent regions can be either message driven (message processing) regions or non-message driven regions (batch). Message processing regions (MPRs) run applications that process messages that come into IMS TM as input, such as from terminals or online programs. IMS submitting the JCL as a result of an IMS command can start MPRs. The address space does not automatically load an application program, but it waits until work becomes available. Priority settings determine which MPR runs the application program. When the IMS determines that an application is to run in a particular MPR, the application program is loaded into that region and receives control. The application processes the message and any further messages for that transaction that are waiting to be processed. Then, depending on options specified on the transaction definition, either the application waits for further input, or another application program is loaded to process a different transaction.

IMS provides the following dependent region types:

  • Message processing regions, which read and process messages from the IMS message queue, including the following:
    • Message Processing Program (MPP)
    • IMS Fast Path (IFP)
    • Java Message Processing (JMP)
  • Non-message driven regions, which are batch-oriented and do not process IMS messages:
    • Batch Message Processing (BMP)
    • Java Batch Processing (JBP)

JMP regions and JBP regions enable Java, object-oriented COBOL, object-oriented PL/I, or a combination of these languages to get control when an IMS transaction is scheduled. This differs from IFP regions and BMP regions, which allow programs written in Assembler, PL/I, C, COBOL, and PASCAL to get control when an IMS transaction is scheduled.

IMS dependent regions support persistent Java Virtual Machines (JVM) to provide the capability to efficiently make calls that interoperate between Java and languages such as COBOL and PL/I. This enables the capability to leverage existing IMS applications as well as extend functionality using Java. Interoperability is supported in MPP, BMP, IFP, JMP, and JBP regions.

Using Java to develop new business logic enables you to leverage the skills that are common in the distributed world environment, such as JDBC. In addition, you might lower the cost of running Java applications by taking advantage of System z Application Assist Processor (zAAP) engines, which assist in lowering the chargeable MIPs usage when processing Java.

JBP regions run flexible programs that perform batch-type processing online and can access the IMS message queues for output (similar to non-message-driven BMP applications). JBP applications are started by submitting a job with JCL or from TSO. JBP applications are like BMP applications, except that they cannot read input messages from the IMS message queue. Like BMP applications, JBP applications can use symbolic checkpoint and restart calls to restart the application after an abend. JBP applications can access IMS or DB2 data in a DB/DC or DBCTL environment and DB2 data in a DCCTL environment.


JBP environment: Setting up

This section describes using Java in a Java Batch Processing region environment.

Role: System Programmer

This section provides an overview to set up an IMS Java Batch Processing Region (JBP) to run Java applications. Listing 1 shows an example of a job called JBPSAMPL to start a JBP region.

Listing 1. Sample job JBPSAMPL to start a JBP region
//JBPSAMPL  JOB,0M 
// CLASS=A,MSGCLASS=H,MSGLEVEL=(1,1),NOTIFY=&SYSUID,REGION=32M
//       EXEC DFSJBP,                                                
//            IMSID=IMSB,MBR=JBPSAMPL,PSB=S2U1LPSJ,JVMOPMAS=DFSJVMMS,
//            ENVIRON=DFSJVMEV
//STEPLIB  DD DSN=IMS.PGMLIB,DISP=SHR           
//         DD DSN=IMS.SDFSJLIB,DISP=SHR
//         DD DSN=IMS.SDFSRESL,DISP=SHR
//         DD DSN=CEE.SCEERUN,DISP=SHR                           
//         DD DSN=SYS1.CSSLIB,DISP=SHR                           
//PROCLIB  DD DSN=IMS.PROCLIB,DISP=SHR
//JAVAOUT  DD  PATH='/tmp/jvm.out',                              
//             PATHDISP=(KEEP,KEEP),                                
//             PATHOPTS=(OWRONLY,OCREAT,OTRUNC),                    
//             PATHMODE=(SIRWXU,SIRWXG,SIRWXO)                                          
//JAVAERR  DD  PATH='/tmp/jvm.err',
//             PATHDISP=(KEEP,KEEP),                                
//             PATHOPTS=(OWRONLY,OCREAT,OTRUNC),                    
//             PATHMODE=(SIRWXU,SIRWXG,SIRWXO)

The JBPSAMPL job executes the DFSJBP procedure provided in the default IMS.PROCLIB. The parameters include the following:

IMSID
The IMS subsystem ID under which to execute
MBR
An application program name
PSB
The program specification block defined in IMS to allow appropriate access to the databases and transactions based on the PSB definition. In the JBPSAMPL sample, S2U1LPSJ is the PSB provided. The sample PSB called S2U1LPSJ is shown in Listing 2.
Listing 2. S2U1LPSJ PSB definition
         PCB   TYPE=DB,DBDNAME=S2U1ADBD,PROCOPT=A,KEYLEN=20,           X
               PCBNAME=PCB01                                            
         SENSEG  NAME=ADDINFO,PARENT=0                                  
         PSBGEN  LANG=JAVA,PSBNAME=S2U1LPSJ                             
         END

S2U1LPSJ provides access to the ADDINFO segment in the S2U1ADBD database defined in IMS. Additionally, the processing option (PROCOPT) specifies A, which allows all operations against that segment, including retrieve, update, insert, and delete.

Recommendation

If using PCBs that define multiple segments, PROCOPT P is recommended to allow joining segments in the same hierarchy. This is useful when the applications require data from multiple segments in a single query.

Important: If using the IMS Universal driver, a PCBNAME or LABEL is required on the PCB statement, because Java libraries leverage the AIB interfaces, which require the name or label to be present. JVMOPAS is the name of the IMS.PROCLIB member that contains the CLASSPATH and the JVM options for the master JVM. Listing 3 shows an example of the JVMOPAS IMS.PROCLIB member DFSJVMMS.

Listing 3. DFSJVMMS member
********************************************************************  
* Specify the profile that has environment settings and JVM options.  
* The following two JVM options are required.                                  
********************************************************************            
-Djava.class.path=>                                                             
/stjava/ims/IMS Universal driver .jar:>  
/stjava/ims/imsutm.jar:>                                                        
/stjava/SolutionTestApps.jar:>                                                  
********************************************************************            
* The following JVM options are a subset of the options allowed
* Xmx64M       - set the maximum Java heap size of your program     
* Xmso512k     - set stack size for OS threads for 32 bit  
* Xss256k      - set Java thread stack size                                
* Xms1M        - set initial Java heap size                       
*******************************************************************          
-Xmaxf0.8
-Xminf0.3
-Xmx64M  
-Xmso512k
-Xss256k 
-Xms1M

The CLASSPATH (java.class.path) in Listing 3 specifies the location of the IMS Universal driver .jar, imsutm.jar, and SolutionTestApps.jar libraries. The IMS Universal driver .jar and imsutm.jar are the libraries required when programming with the IMS Universal driver APIs. The IMS Universal driver .jar and imsutm.jar can be installed using the IMS Installation Verification Program (IVP) for Java scenarios.

The IMS Universal driver .jar and imsutm.jar are the libraries required when programming with the IMS Universal driver APIs. The SMP/E installation of the IMS Java On Demand FMID adds the IMS Universal DB resource adapter parts into the appropriate directories in the file system. Before the IMS Java On Demand FMID can be installed, a ZFS or HFS file system must be created and mounted. Once this file system has been mounted, sample job DFSJSMKD is then run to create the directories in the file system. DFSJSMKD calls DFSJMKDR to create the directory structures and symbolic link libT2DLI.so.

The SolutionTestApps.jar contains the sample applications to be run in this sample. Listing 4 shows a list of the SolutionTestApps.jar file contents.

Listing 4. SolutionTestApps.jar file contents
JavaPayPolicy.class
databaseviews/S2U1LPSJDatabaseView.class
databaseviews/S2U1PSBDatabaseView.class
com/ibm/ims/st/opendb/jmp/AdditionalCustomerIOMessage.class
com/ibm/ims/st/opendb/jmp/AdditionalCustomerCRUD.class  
com/ibm/ims/st/opendb/jbp/AdditionalCustomerInfo.class

ENVIRON is the name of the IMS.PROCLIB member that contains the library path (LIBPATH) definition for the Java environment. Listing 5 shows the ENVIRON IMS.PROCLIB member DFSJVMEV.

Listing 5. DFSJVMEV sample member
**********************************************************************
* Specify the location of Java Virtual Machine (JVM) installation and 
* IMS Java native code (libT2DLI.so) 
**********************************************************************
LIBPATH=>     
/javaroot/java160/J6.0/bin:>     
/javaroot/java160/J6.0/bin/j9vm:>     
/usr/lpp/ims/lib

The first two paths specified in DFSJVMEV point to the Java Version 6.0 runtime libraries located in the z/OS UNIX® System Services (USS) Hierarchical File System (HFS). The last path specifies the location of the libT2DLI.so, which points to the Java native code for IMS type-2 Java connectivity provided in IMS Version 10 and 11. The libT2DLI.so file is created in the USS file system when running the IMS Installation Verification Program for Java scenarios.

MBR is an application program name used to invoke Java applications.

To indicate which Java application to invoke when running a JBP, specify a 1-8 character name in the MBR parameter. When the MBR name is specified, the JBP tries to load the DFSJVMAP IMS.PROCLIB member. DFSJVMAP maps MBR names to fully qualified Java class names.

Listing 6 shows an example of a DFSJVMAP definition.

Listing 6. DFSJVMAP sample Member
**********************************************************************
* The Java applications specified here are located in the      
* SolutionTestApps.jar file.        
********************************************************************** 
JBPSAMPL=com/ibm/ims/st/opendb/jbp/AdditionalCustomerInfo
**********************************************************************

In this example, JBPSAMPL is mapped to a Java class called AdditionalCustomerInfo so that when the JBP is submitted, it will execute the main method in the AdditionalCustomerInfo Java class. If the MBR parameter is not provided, the JBP attempts to load a Java class with the name of the PSB. For the example, IMS will try to load S2U1LPSJ.class.

The JBPSAMPL job in Listing 1 also specifies the DD names JAVAOUT and JAVAERR. These files are used for Java applications, and they specify where the Java System.out and System.err streams are written to. The provided JAVAOUT and JAVAERR DD statements create these files if they don't exist, and if they do exist, the files will be overwritten.


JBP environment: Application development

This section describes JBP application development.

Role: DBA or Application Programmer, depending on your environment

When you plan to access an IMS database from Java, the first step in developing applications that use the IMS Universal driver is to create a database view. This database view is a Java class containing metadata that describe the IMS PSBs, DBDs, segments, fields, relationships, keys/non-keys, and data-type information. This class serves as the metadata for a PSB and its set of related views (PCBs) and databases (DBDs). This is necessary for the IMS Universal drivers to build and validate queries against IMS databases as well as field layouts in a segment.

To generate this metadata class, IMS provides the IMS Enterprise Suite DLIModel Utility Plug-in for Eclipse, which can be downloaded at no charge (see Resources).

The plug-in installs on top of Eclipse and provides a wizard, which imports PSB source and DBD source to generate the database view based on a particular PSB. In the JCL provided in Listing 1, the PSB used is S2U1LPSJ, which references a DBD called S2U1ADBD. The source for S2U1LPSJ and S2U1ADBD needs to be downloaded with a file name that matches the PSB and DBD name.

Hint: It is possible for a DBD to reference other DBDs, so be sure to download all of the referenced DBDs, including secondary indexed DBDs, logical DBDs, and DBDs referenced in LCHILD statements. Contact your database administrator (DBA) to ensure that this is available for use.

Once you obtain all the parts, search for the IMS Enterprise Suite DLIModel utility plug-in information in the InfoCenter (see Resources).

For your reference, Listing 7 shows the S2U1LPSJDatabaseView.java generated from using the DLIModel utility. You will never need to look at this class, because the Java libraries consume it internally. In the S2U1LPSJDatabaseView class, the ADDINFO segment contains additional customer information and has various fields defined, including CustomerNumber (Unique Key), Email, Phone, Fax, and so on.

Listing 7. S2U1LPSJDatabaseView.java
package databaseviews;

import com.ibm.ims.db.*;
import com.ibm.ims.base.*;

public class S2U1LPSJDatabaseView extends DLIDatabaseView {

    // This class describes the data view of PSB: S2U1LPSJ
    // PSB S2U1LPSJ has database PCBs with 8-char PCBNAME or label: 
    //       PCB01

    // The following describes Segment: ADDINFO ("ADDINFO") in PCB: PCB01 ("PCB01")
    static DLITypeInfo[] PCB01ADDINFOArray= {
        new DLITypeInfo("info_length", DLITypeInfo.SMALLINT, 1, 2),
        new DLITypeInfo("CustomerNumber", DLITypeInfo.INTEGER, 3, 4,
     		"CUSTNO",DLITypeInfo.UNIQUE_KEY),
        new DLITypeInfo("Email", DLITypeInfo.CHAR, 7, 30),
        new DLITypeInfo("Phone", DLITypeInfo.CHAR, 37, 10),
        new DLITypeInfo("Fax", DLITypeInfo.CHAR, 47, 10),
        new DLITypeInfo("CompanyName", DLITypeInfo.CHAR, 57, 30),
        new DLITypeInfo("DriversLicense", DLITypeInfo.CHAR, 87, 8),
        new DLITypeInfo("DLState", DLITypeInfo.CHAR, 95, 2),
        new DLITypeInfo("Notes", DLITypeInfo.CHAR, 97, 1468)
    };
    static DLISegment PCB01ADDINFOSegment= new DLISegment
        ("ADDINFO","ADDINFO",PCB01ADDINFOArray,1564);

    // An array of DLISegmentInfo objects follows to describe the view 
	// for PCB: PCB01 ("PCB01")
    static DLISegmentInfo[] PCB01array = {
        new DLISegmentInfo(PCB01ADDINFOSegment,DLIDatabaseView.ROOT)
    };

    // Constructor
    public S2U1LPSJDatabaseView() {
        super("2.0.3","S2U1LPSJ", "PCB01", "PCB01", PCB01array, "A");
    } // end S2U1LPSJDatabaseView constructor

} // end S2U1LPSJDatabaseView class definition

Accessing the IMS database in Java using the IMS Universal JDBC driver or the IMS Universal DL/I driver

The IMS Universal drivers provide two APIs: JDBC and DL/I for Java. The IMS Universal JDBC driver treats IMS DB segments as equivalent to relational tables. Listings 8 and 9 show application samples provided for each. The samples will run in the JBP region and report a list of all customer numbers, company names, and phone numbers in the ADDINFO segment (table).

Listing 8. IMS Universal Driver JDBC driver for Java API
public static void main(String[] args) {
	//Setting Type 2 Properties
	IMSDataSource imsDS = new IMSDataSource();
	imsDS.setDatastoreName("IMSB");
	imsDS.setDriverType(IMSDataSource.DRIVER_TYPE_2);
	imsDS.setMetadataURL("class://databaseviews.S2U1LPSJDatabaseView");
	
	//Application is used to get a Transaction object
	Application app = ApplicationFactory.createApplication();
	
	//Transaction is primarily used for commit or rollback calls
	Transaction tran = app.getTransaction();
		
	try {
		Connection conn = imsDS.getConnection();
		Statement st = conn.createStatement();
		ResultSet rs = st.executeQuery(
		  "SELECT CustomerNumber, CompanyName, Phone FROM PCB01.ADDINFO");
		
		while(rs.next()){
		   System.out.println("CustomerNumber: " + 
		      rs.getString("CustomerNumber") + 
			  ", CompanyName: " + 
			  rs.getString("CompanyName") + 
			  ", Phone: " + 
			  rs.getString("Phone"));
		}
		
		rs.close();
		st.close();
		tran.commit();
		conn.close();
	} catch (SQLException e) {
		System.out.println("An SQLException occurred: " + e.getMessage());
		e.printStackTrace();
	} catch (DLIException e) {
		System.out.println("A DLIException occurred: " + e.getMessage());
		e.printStackTrace();
	}
}

JDBC is a standard API for issuing SQL statements in Java. The application uses IMSDataSource to define the following:

  • Driver type
  • Datastore name or IMSID
  • Metadata URL points the IMS Universal driver to the database view class for the PSB being accessed

The application uses the standard JDBC programming model of getting a connection, creating a statement, executing the statement, and processing the result set. To commit data in IMS dependent regions, use the transaction instance (tran) to commit the work done.

Listing 9 shows an example that uses the IMS Universal DL/I driver.

Listing 9. IMS Universal DL/I driver example
public static void main(String[] args) {
	//Setting Type 2 Properties
	IMSConnectionSpec connSpec = IMSConnectionSpecFactory.createIMSConnectionSpec();
	connSpec.setDatastoreName("IMSB");
	connSpec.setDriverType(IMSConnectionSpec.DRIVER_TYPE_2);
	connSpec.setMetadataURL("class://databaseviews.S2U1LPSJDatabaseView");
	
	//Application is used to get a Transaction object
	Application app = ApplicationFactory.createApplication();
	
	//Transaction is primarily used for commit or rollback calls
	Transaction tran = app.getTransaction();
	
	try {
            PSB psb = PSBFactory.createPSB(connSpec);
            PCB pcb = psb.getPCB("PCB01");
            SSAList ssa = pcb.getSSAList("ADDINFO");
            PathSet pathSet = pcb.batchRetrieve(ssa);
		
	    while(pathSet.hasNext()){
	        Path path = pathSet.next();
	        System.out.println("CustomerNumber: " + 
			   path.getString("CustomerNumber") + 
	           ", CompanyName: " + 
			   path.getString("CompanyName") + 
	           ", Phone: " + 
			   path.getString("Phone"));
	    }	
	
            tran.commit();
            psb.close();
	} catch (DLIException e) {
		System.out.println("An error occurred: " + e.getMessage());
		e.printStackTrace();
	}

The main method in Listing 9 shows how to obtain a type-2 connection to S2U1LPSJ by creating IMSConnectionSpec that specifies the following:

  • Driver type
  • Datastore name or IMSID
  • Metadata URL points the IMS Universal driver to the database view class for the PSB being accessed

Next the application uses the PSB, PCB, and SSAList objects to execute a batch retrieve of the ADDINFO segment. This returns a pathSet, which is a collection of paths. A path object is the I/O area for a database call, and it contains the segments that the call returns. A while loop is used to print one line for every path returned listing the CustomerNumber, CompanyName, and Phone number fields.


JBP environment: Deploying the Java application

This section describes how to deploy the Java application in the JBP environment.

Role: Application Developer and System Administrator

To deploy the application, export the Java project as a jar file, and FTP the jar file to your USS file system in BINARY mode on the LPAR you want to run on.

The jar file should be referenced in the DFSJVMMS IMS.PROCLIB member described in Listing 3. In Listing 3, stjava is the directory where the application archive SolutionTestApps.jar was FTPed.

Executing the JBP and viewing the results

This section describes how to execute the JBP and view the results.

Role: Application Developer

Now that all the parts are in place (JCL, IMS.PROCLIB members, and Java classes), run the JBPSAMPL JCL in Listing 1. To check the results, use SDSF to find the active or completed JBP job. Ensure that there are no errors in the JOBLOG for the JBPSAMPL task.

Next, check the output locations specified by JAVAOUT and JAVAERR. In the sample, you can find JAVAOUT in /tmp/jvm.out, and you can find JAVAERR in /tmp/jvm.err in the USS environment. If nothing was written to the error stream, jvm.err is empty. For the sample application, the jvm.out file contains a report of customer numbers, company names, and phone numbers.

On most z/OS systems you can access the USS environment by entering OMVS from TSO. To browse a file in the USS environment that is named jvm.out and that is located in the tmp path, enter obrowse /tmp/jvm.out.


JMP environment: Setting up

This section describes using Java in a Java batch processing region environment.

Role: System Programmer

A JMP application program is similar to an MPP application program, except that JMP applications are written in Java or object-oriented COBOL. Like an MPP application, a JMP application is started when there is a message in the message queue for the JMP application. IMS schedules the message for processing.

Each transaction code represents a transaction that the JMP application processes. A single application can also be started from multiple transaction codes. JMP applications are very flexible in how they process transactions and where they send the output. JMP applications send any output messages back to the message queues and process the next message with the same transaction code. The program continues to run until there are no more messages with the same transaction code.

JMP applications can access IMS or DB2 z/OS data in a DB/DC environment, and they can access DB2 z/OS data in a DCCTL environment using JDBC. JMP applications run in JMP regions that have Java virtual machines (JVMs). JMP applications can also do the following:

  • Retrieve input messages from the IMS message queue
  • Access IMS and DB2 for z/OS databases
  • Commit or roll back transactions
  • Send output messages

This section describes the setup specific to running a JMP that uses the IMS Universal driver type-2 driver.

Listing 10 is an example of a job that starts a JMP region.

Listing 10. JMP with IMS Universal driver type-2 driver
//JMPADTL1 JOB ,                                              
// CLASS=A,MSGCLASS=H,MSGLEVEL=(1,1),NOTIFY=&SYSUID,REGION=0M 
/*JOBPARM  S=*                                                
//       EXEC DFSJMP,                                         
//            IMSID=IMSB,JVMOPMAS=DFSJVMMS,ENVIRON=DFSJVMEV,  
//            CL1=002,CL2=000,CL3=000,CL4=000                 
//STEPLIB  DD DSN=IMS.PGMLIB,DISP=SHR           
//         DD DSN=IMS.SDFSJLIB,DISP=SHR
//         DD DSN=IMS.SDFSRESL,DISP=SHR
//         DD DSN=CEE.SCEERUN,DISP=SHR                           
//         DD DSN=SYS1.CSSLIB,DISP=SHR                           
//PROCLIB  DD DSN=IMS.PROCLIB,DISP=SHR
//JAVAOUT  DD  PATH='/tmp/jvm.out',                              
//             PATHDISP=(KEEP,KEEP),                                
//             PATHOPTS=(OWRONLY,OCREAT,OTRUNC),                    
//             PATHMODE=(SIRWXU,SIRWXG,SIRWXO)                                          
//JAVAERR  DD  PATH='/tmp/jvm.err',
//             PATHDISP=(KEEP,KEEP),                                
//             PATHOPTS=(OWRONLY,OCREAT,OTRUNC),                    
//             PATHMODE=(SIRWXU,SIRWXG,SIRWXO

The JMPADTL1 job executes the DFSJMP procedure provided in the default IMS.PROCLIB. The parameters include the following:

IMSID
The IMS subsystem ID under which to execute
JVMOPAS
The name of the IMS.PROCLIB member that contains the CLASSPATH and JVM options for the master JVM. In this sample, the DFSJVMMS member is defined in Listing 11.
Listing 11. DFSJVMMS sample member
********************************************************************  
* Specify the profile that has environment settings and JVM options.  
* The following two JVM options are required.                                  
********************************************************************            
-Djava.class.path=>                                                             
/stjava/ims/IMS Universal driver .jar:>        
/stjava/ims/imsutm.jar:>                                                        
/stjava/SolutionTestApps.jar:>        
********************************************************************            
* The following JVM options are a subset of the options allowed
*                                                                       
* Xmx64M       - set the maximum Java heap size of your program    
* Xmso512k     - set stack size for OS threads for 32 bit   
* Xss256k      - set Java thread stack size      
* Xms1M        - set initial Java heap size      
********************************************************************  
-Xmaxf0.8
-Xminf0.3
-Xmx64M  
-Xmso512k
-Xss256k 
-Xms1M

The CLASSPATH (java.class.path) specifies the IMS Universal driver .jar, imsutm.jar, and SolutionTestApps.jar libraries. The IMS Universal driver .jar and imsutm.jar are the libraries required when programming with the IMS Universal driver APIs. The SMP/E installation of the IMS Java On Demand FMID adds the required parts into the appropriate directories in the file system. Before you can install the IMS Java On Demand FMID, you need to create and mount a ZFS or HFS file system. Once this file system has been mounted, you can then run sample job DFSJSMKD to create the directories in the file system. DFSJSMKD calls DFSJMKDR to create the directory structures and symbolic link libT2DLI.so.

The SolutionTestApps.jar contains the sample applications to be run in this article. Listing 12 shows the SolutionTestApps.jar file contents generated by using the jar tf SolutionTestApps.jar command.

Listing 12. SolutionTestApps.jar file
JavaPayPolicy.class
databaseviews/S2U1LPSJDatabaseView.class
databaseviews/S2U1PSBDatabaseView.class
com/ibm/ims/st/opendb/jmp/AdditionalCustomerIOMessage.class
com/ibm/ims/st/opendb/jmp/AdditionalCustomerCRUD.class  
com/ibm/ims/st/opendb/jbp/AdditionalCustomerInfo.class

Parameter ENVIRON specifies the name of the IMS.PROCLIB member that contains the library path (LIBPATH) definition for the Java environment. In the sample, DFSJVMEV is defined as shown in Listing 13.

Listing 13. DFSJVMEV sample member
 **********************************************************************
* Specify the location of Java Virtual Machine (JVM) installation and 
* IMS Java native code (libT2DLI.so) 
**********************************************************************
LIBPATH=>                                                             
/javaroot/java160/J6.0/bin:>                                          
/javaroot/java160/J6.0/bin/j9vm:>                                     
/usr/lpp/ims/lib

The first two paths specified in DFSJVMEV point to the Java Version 6.0 runtime libraries located in the z/OS UNIX System Services (USS) file system. The last path specifies the location of the libT2DLI.so, which points to the Java native code for IMS type-2 Java connectivity provided in IMS Versions 10 and 11. The libT2DLI.so file is created in the USS file system when running the IMS installation verification program for Java scenarios.

Parameters CL1,CL2,CL3, and CL4 are required positional parameters that specify four three-digit decimal numbers indicating which classes of messages are to be processed by this message region. The maximum value for a class is 999. The sequence of specifying the classes determines relative class priority within the message region.

The JMPADTL1 in Listing 10 also specifies the DD names JAVAOUT and JAVAERR. These files are used for Java applications, and they specify where the Java System.out and System.err streams are written. The provided JAVAOUT and JAVAERR DD statements will create these files if one of them doesn’t exist, and if it does exist it will be overwritten.

To indicate which Java application to invoke when a transaction is scheduled, IMS uses the DFSJVMAP IMS.PROCLIB member. Each transaction in IMS has an associated application name. For the purposes of this article, the transaction that will be used is named ADTLTRAN.

There are two ways to define transactions in IMS: Stage 1 definitions or dynamic resource definitions (DRD). Use the following DRD query command in Listing 14 to get the PSB name for the trans.

Listing 14. DRD query command
QRY TRAN NAME(ADTLTRAN) SHOW(PSB CLASS)

Listing 15 shows the output from the DRD command.

Listing 15. DRD command output
Trancode MbrName    CC PSBname  LCls 
ADTLTRAN IMSB        0 S2U1LPSJ    2

The DRD command output shows the PSB name and the message class for the ADTLTRAN transaction. If the IMS system is not using DRD functionality, you can find these definitions in the Stage1 (MODBLKS) definitions. In this case, the class number indicated (2) matches the CL1=002 parameter in the JMPADTL1 from Listing 10. The PSB name is S2U1LPSJ. IMS searches the DFSJVMAP IMS.PROCLIB member for this name to determine the correct Java class to invoke. Listing 16 shows an example of DFSJVMAP, which maps S2U1LPSJ to the AdditionalCustomerCRUD Java class.

Listing 16. DFSJVMAP sample member
**********************************************************************
* The Java applications specified here are located in the             
* SolutionTestApps.jar file.                                          
********************************************************************** 
S2U1LPSJ=com/ibm/ims/st/opendb/jmp/AdditionalCustomerCRUD 
**********************************************************************

JMP environment: Application development

This section describes JMP application development.

Role: DBA or Application Programmer, depending on your environment

For this JMP example, when ADTLTRAN is invoked, the Java application executed is AdditionalCustomerCRUD. The application inserts customer information into the ADTLINFO segment of the S2U1ADBD IMS database. The PSB being used is defined in Listing 16.

The steps to create a JMP application include the following:

  1. Create a Java class to represent the transactions' input/output message layouts
  2. Create a Java database view to represent the database layout
  3. Create the application that contains the business logic to process the input/output messages and interact with the database

Create Java input/output message classes

For this example, the application expects an input message containing all the fields necessary to insert into the ADTLINFO segment, including the following:

  • Unique customer number
  • Email address
  • Phone number
  • Fax number
  • Company name
  • Driver’s license number
  • State
  • Additional notes

This example also uses the same message format for the output message. It will also include an error message field to indicate success or failure.

The IMS Universal driver libraries provide an abstract class called IMSFieldMessage for Java objects that represent a message both coming from and going to an IMS message queue. The Java code in Listing 17 shows the input/output message definition for the application.

Listing 17. Java input/output message
 public class AdditionalCustomerIOMessage extends IMSFieldMessage {
	private static final long serialVersionUID = 23432884;
	
    static DLITypeInfo[] fieldInfo = {
    	new DLITypeInfo("CustomerNumber", DLITypeInfo.INTEGER, 1, 4, "CUSTNO"),
        new DLITypeInfo("Email", DLITypeInfo.CHAR, 5, 30),
        new DLITypeInfo("Phone", DLITypeInfo.CHAR, 35, 10),
        new DLITypeInfo("Fax", DLITypeInfo.CHAR, 45, 10),
        new DLITypeInfo("CompanyName", DLITypeInfo.CHAR, 55, 30),
        new DLITypeInfo("DriversLicense", DLITypeInfo.CHAR, 85, 8),
        new DLITypeInfo("DLState", DLITypeInfo.CHAR, 93, 2),
        new DLITypeInfo("Notes", DLITypeInfo.CHAR, 95, 1468),
        new DLITypeInfo("ErrorMessage", DLITypeInfo.CHAR, 1563, 500)
    };
    /**
     * Instantiate a new OutMessage object. 
	 **/
    public AdditionalCustomerIOMessage() {     
    	 super(fieldInfo, 2070, false); //false indicates that this is not a SPA message
                                        //2070 is the length of the message
    }
}

Creating a Java database view

When accessing an IMS database from Java using the IMS Universal drivers, you need to generate a database view. This database view is a Java class with metadata describing the IMS PSBs, DBDs, segments, fields, relationships, keys/non-keys, and data-type information. This is necessary for the IMS Universal drivers to build and validate queries against IMS databases. The database view that is generated must be compiled at the same level that the JVM used in the IMS is on.

To generate this metadata class, IMS provides the IMS Enterprise Suite DLIModel Utility Plug-in for Eclipse, which can be downloaded at no charge (see Resources).

The plug-in installs on top of Eclipse and provides a wizard that imports PSB source and DBD source to generate the database view based on a particular PSB. In the JCL provided in Listing 10, the PSB used is S2U1LPSJ, which references the DBD S2U1ADBD. The source for S2U1LPSJ and S2U1ADBD needs to be downloaded with a file name that matches the PSB and DBD name.

Hint: It is possible for a DBD to reference other DBDs, so be sure to download all of the referenced DBDs, including secondary indexed DBDs, logical DBDs, and DBDs referenced in LCHILD statements. Contact the database administrator (DBA) to ensure that this is available for use.

Once you obtain all the parts, follow the tutorial from Chapter 6.3 IBM IMS Enterprise Suite DLIModel utility from the IMS Version 11 Technical Overview (see Resources).

Listing 18 shows a view of S2U1LPSJDatabaseView.java.

Listing 18. S2U1LPSJDatabaseView.java
package databaseviews;

import com.ibm.ims.db.*;
import com.ibm.ims.base.*;

public class S2U1LPSJDatabaseView extends DLIDatabaseView {

    // This class describes the data view of PSB: S2U1LPSJ
    // PSB S2U1LPSJ has database PCBs with 8-char PCBNAME or label: 
    //       PCB01

    // The following describes Segment: ADDINFO ("ADDINFO") in PCB: PCB01 ("PCB01")
    static DLITypeInfo[] PCB01ADDINFOArray= {
        new DLITypeInfo("info_length", DLITypeInfo.SMALLINT, 1, 2),
        new DLITypeInfo("CustomerNumber", DLITypeInfo.INTEGER, 3, 4, 
		               "CUSTNO",DLITypeInfo.UNIQUE_KEY),
        new DLITypeInfo("Email", DLITypeInfo.CHAR, 7, 30),
        new DLITypeInfo("Phone", DLITypeInfo.CHAR, 37, 10),
        new DLITypeInfo("Fax", DLITypeInfo.CHAR, 47, 10),
        new DLITypeInfo("CompanyName", DLITypeInfo.CHAR, 57, 30),
        new DLITypeInfo("DriversLicense", DLITypeInfo.CHAR, 87, 8),
        new DLITypeInfo("DLState", DLITypeInfo.CHAR, 95, 2),
        new DLITypeInfo("Notes", DLITypeInfo.CHAR, 97, 1468)
    };
    static DLISegment PCB01ADDINFOSegment= new DLISegment
        ("ADDINFO","ADDINFO",PCB01ADDINFOArray,1564);

    // An array of DLISegmentInfo objects follows to describe the view 
	// for PCB: PCB01 ("PCB01")
    static DLISegmentInfo[] PCB01array = {
        new DLISegmentInfo(PCB01ADDINFOSegment,DLIDatabaseView.ROOT)
    };

    // Constructor
    public S2U1LPSJDatabaseView() {
        super("2.0.3","S2U1LPSJ", "PCB01", "PCB01", PCB01array, "A");
    } // end S2U1LPSJDatabaseView constructor

} // end S2U1LPSJDatabaseView class definition

The sample Java application

The sample AdditionalCustomerCRUD application uses the IMS Universal driver to get access to the IMS message queues, and the application uses JDBC to access the IMS database. Listing 19 details the major parts of the sample AdditionalCustomerCRUD application.

Listing 19. AdditionalCustomerCRUD application
 public static void main(String[] args) {
	Application app = ApplicationFactory.createApplication();
	Transaction tran = app.getTransaction();
	MessageQueue msgQueue = app.getMessageQueue();
	IOMessage ioMessage = null;
		
	try {
		ioMessage = app.getIOMessage
	  ("class://com.ibm.ims.solutiontest.opendb.jmp.AdditionalCustomerIOMessage");
		while (msgQueue.getUnique(ioMessage)) {
			IMSDataSource ds = new IMSDataSource();			
			ds.setMetadataURL("class://databaseviews.S2U1LPSJDatabaseView");
			ds.setDatastoreName("IMSB");
			ds.setDriverType(IMSDataSource.DRIVER_TYPE_2);
				
			Connection conn = ds.getConnection();
			conn.setAutoCommit(false);
	 			
			PreparedStatement addinfo = conn.prepareStatement("INSERT INTO "
			+ "PCB01.ADDINFO (Info_length,CustomerNumber,Email,"
			+  Phone, Fax, CompanyName,"
			+ "DriversLicense, DLState, Notes) Values(?,?,?,?,?,?,?,?,?)");

			addinfo.setInt(1, 1564);
			addinfo.setInt(2, ioMessage.getInt("CustomerNumber"));
			addinfo.setString(3, ioMessage.getString("email"));
			addinfo.setString(4, ioMessage.getString("Phone"));
			addinfo.setString(5, ioMessage.getString("Fax"));
			addinfo.setString(6, ioMessage.getString("CompanyName"));
			addinfo.setString(7, ioMessage.getString("DriversLicense"));
			addinfo.setString(8, ioMessage.getString("DLState"));
			addinfo.setString(9, ioMessage.getString("Notes"));
		
			int rowsInserted = addinfo.executeUpdate();
		
			if (rowsInserted == 1) {
				ioMessage.setString("ErrorMessage", "");
			} else {
				ioMessage.setString("ErrorMessage", "Insert failed");
			}
		
			addinfo.close();
			conn.close();
				
			msgQueue.insert(ioMessage, MessageQueue.DEFAULT_DESTINATION);
			tran.commit();
			}
		} catch (Exception e) {
			e.printStackTrace();
		try {
		if(e.getMessage().length()>500){
		ioMessage.setString("ErrorMessage", e.getMessage().substring(0, 500));
		} else {
		ioMessage.setString("ErrorMessage", e.getMessage());
		}	
		msgQueue.insert(ioMessage, MessageQueue.DEFAULT_DESTINATION);	
		} catch (DLIException e1) {
		e1.printStackTrace();			
		}
	}
}

The first part of the application creates the following instances to allow for interaction with the message queue:

  • Application
  • Transaction
  • MessageQueue
  • IOMessage

The following code listings show an application instance (app) being created using the ApplicationFactory. The app object is used to get a handle on a transaction, messageQueue, and ioMessage instance. When creating an instance of an ioMessage, a string parameter is used to specify the fully qualified name of a Java class created to represent that message. Listing 20 is an excerpt of Listing 19.

Listing 20. Java class input/output message
Application app = ApplicationFactory.createApplication();
Transaction tran = app.getTransaction();
MessageQueue msgQueue = app.getMessageQueue();
IOMessage ioMessage = app.getIOMessage
+ ("class://com.ibm.ims.solutiontest.opendb.jmp.AdditionalCustomerIOMessage");

Next, the application uses the MessageQueue instance (msgQueue) to retrieve messages off of the IMS message queue using the getUnique method call. The getUnique method takes a parameter, ioMessage, which defines the message structure of the expected input message described in Listing 17. If the getUnique call is successful, the ioMessage is populated with the transaction input message data. Listing 21 shows the getUnique call.

Listing 21. getUnique call
while (msgQueue.getUnique(ioMessage))

Once the message is retrieved, the application creates an IMSDataSource in order to obtain a type-2 connection to the S2U1LPSJ PSB. To specify the PSB for the application to connect to, provide the fully qualified class name of the database view created in Listing 18. Then use the IMSDataSource instance (ds) to get a JDBC connection, as shown in Listing 22.

Listing 22. Getting a JDBC connection
IMSDataSource ds = new IMSDataSource();
ds.setMetadataURL("class://databaseviews.S2U1LPSJDatabaseView");
ds.setDatastoreName("IMSB");
ds.setDriverType(IMSDataSource.DRIVER_TYPE_2);
				
Connection conn = ds.getConnection();

When using JDBC from within an IMS transaction, the JDBC connection setAutoCommit must be set to false in order to prevent JDBC connections from automatically committing work. Commits are instead explicitly issued using the transaction object or implicitly committed when the getUnique method returns a QC status code from IMS indicating no more messages are on the queue, as shown in Listing 23.

Listing 23. setAutoCommit
conn.setAutoCommit(false);

Next the application creates a PreparedStatement (addinfo) to define the SQL insert call, as shown in Listing 24. This SQL call will be inserted into the ADDINFO segment defined in the S2U1LPSJ PSB, and it will provide the input data including the following:

  • Info_length
  • CustomerNumber
  • Email
  • Phone
  • Fax
  • CompanyName
  • DriversLicense
  • DLState
  • Notes
Listing 24. Providing input data
PreparedStatement addinfo = conn.prepareStatement("INSERT INTO "
	+ "PCB01.ADDINFO (Info_length,CustomerNumber,Email, Phone, Fax, CompanyName,"
	+ "DriversLicense, DLState, Notes) Values(?,?,?,?,?,?,?,?,?)");

The application then uses the ioMessage to get the data from the input message. The application uses that data to set the addinfo fields to insert into the ADTLINFO segment, as shown in Listing 21. The values 1-9 in the addinfo.set methods listed in Listing 25 correspond to each of the nine question marks (?) specified in the PreparedStatement.

Listing 25. Setting data
	addinfo.setInt(1, 1564);
	addinfo.setInt(2, ioMessage.getInt("CustomerNumber"));
	addinfo.setString(3, ioMessage.getString("email"));
	addinfo.setString(4, ioMessage.getString("Phone"));
	addinfo.setString(5, ioMessage.getString("Fax"));
	addinfo.setString(6, ioMessage.getString("CompanyName"));
	addinfo.setString(7, ioMessage.getString("DriversLicense"));
	addinfo.setString(8, ioMessage.getString("DLState"));
	addinfo.setString(9, ioMessage.getString("Notes"));

After the prepared statement values are set, the application executes the statement using the executeUpdate() method, which returns an integer indicating the number of rows (segments) affected by the call, as shown in Listing 26.

Listing 26. Number of rows inserted
int rowsInserted = addinfo.executeUpdate();

In the case of this insert, the application checks that one row was inserted into the database. If the operation was successful, the application sets the output message ErrorMessage field to blank. Otherwise it sets the output message ErrorMessage field to Insert failed, as shown in Listing 27.

Listing 27. Insert failed
if (rowsInserted == 1) {
	ioMessage.setString("ErrorMessage", "");
} else {
	ioMessage.setString("ErrorMessage", "Insert failed");
}

The application then inserts an output message to the IMS message queue using the DEFAULT_DESTINATION, as shown in Listing 28. The application can also choose to insert messages to alternative message destinations. After inserting, the application commits the unit of work.

Listing 28. Insert message
msgQueue.insert(ioMessage, MessageQueue.DEFAULT_DESTINATION);
tran.commit();

Lastly, the application closes the prepared statement and connection instances, as shown in Listing 29.

Listing 29. Close prepared statement
addinfo.close();
conn.close();

JMP environment: Deploying the Java application

This section describes how to deploy the Java application.

Role: Application Developer and System Administrator

After writing the application, the next step is to deploy it. To deploy the application, export the Java project as a jar file and FTP the jar file to your USS file system in BINARY mode on the LPAR on which you want to run. The jar file should be referenced in the DFSJVMMS IMS.PROCLIB member described in Listing 11 for DFSJVMMS. In DFSJVMMS, stjava is the directory to which the application archive SolutionTestApps.jar was FTPed.


JMP environment: Executing the JMP transaction

This section describes how to execute the JMP transaction.

Role: Application Developer

Now that all the parts are in place (JCL, IMS.PROCLIB members, and Java classes), run the JMPADTL1 JCL from Listing 10. To check that the JMP region is running, issue the /DISPLAY ACTIVE REGION IMS command, and verify that the output is similar to Listing 30.

Listing 30. /DISPLAY IACTIVE REGION output
DFS000I     REGID JOBNAME   TYPE  TRAN/STEP PROGRAM  STATUS   CLASS   IMSB        
DFS000I         1 JMPADTL1  TPE                      WAITING  2       IMSB

Now the IMS transaction ADTLTRAN is ready to run. The next step is to invoke the application. You can invoke the IMS transaction from any of the following:

  • TM resource adapter
  • OTMA client interface
  • MFS applications
  • IMS connection API for C
  • IMS connection API for Java
  • MVS console
  • IMS terminal

After the transaction is successfully invoked, check the output locations specified by JAVAOUT and JAVAERR. Based on the JMPADTL1 job, you can find JAVAOUT in /tmp/jvm.out, and you can find JAVAERR in /tmp/jvm.err in the USS environment. If nothing was written to either stream, the jvm.err and jvm.out will be empty.

On most z/OS systems, you can access the USS environment by issuing OMVS from TSO. To browse a file named jvm.out in USS located in the tmp path, issue the obrowse /tmp/jvm.out command.

The application provides an output message response that is returned to the client.


MPP solution: Overview

This section describes how to use an MPP region for a COBOL-to-Java solution. This scenario is an insurance payment transaction that accesses an IMS database to determine the amount due for a policy and also pays policies by updating the database with payment information. This COBOL/Java interoperability scenario begins with an IMS COBOL application. Once the COBOL application is called, it calls an OO COBOL wrapper program, which invokes a Java method. The OO COBOL wrapper program is essentially a program that translates the COBOL interface into a Java interface. The goal for this scenario is to extend a legacy COBOL program to invoke modernized Java methods that can access both IMS and DB2 databases.

In IMS 10 and IMS 11, IMS provides support of a persistent JVM in MPP/BMP/IFP/JMP/JBP regions. It also supports DB2 calls from a Java application invoked by an MPP/BMP/IFP/JMP/JBP using External Subsystem Attach Facility (ESAF). Currently, each time a Java application is invoked, COBOL creates and destroys the JVM. This new support enables IMS to now manage the JVM by creating the JVM only once and maintaining it through the life of the region.


MPP environment: Setting up

This section describes the MPP environment setup.

Role: System Programmer

In order to run a COBOL/Java interoperability application, some setup is required. This section describes all steps needed to run the COBOL-to-Java solution in an MPP region.

Listing 31 shows a sample job to start the MPP region.

Listing 31. Sample job to start MPP region
//IMSMPP01 JOB ,                                              
// CLASS=A,MSGCLASS=H,MSGLEVEL=(1,1),NOTIFY=&SYSUID,REGION=0M 
/*JOBPARM  S=*                                                
//PROCS JCCLIB ORDER=IMS.PROCLIB       
//IMSMPP01 EXEC PROC=DFSMPR,TIME=(1440),                     
//   NBA=6,
//   OBA-5;
//   SOUT=’*’   
//         CL1=001,               TRANSACTION CLASS 1          
//         CL2=000,               TRANSACTION CLASS 2          
//         CL3=000,               TRANSACTION CLASS 3          
//         CL4=000,               TRANSACTION CLASS 4          
//         TLIM=10,               MPR TERMINATION LIMIT        
//         SOD=,                  SPIN-OFF DUMP CLASS          
//         ENVIRON=DFSJVMEV,                                   
//         JVMOPMAS=DFSJVMMS,                                  
//         IMSID=IMSB,            IMSID OF IMS CONTROL REGION  
//         PREINIT=DC,            PROCLIB DFSINTXX MEMBER      
//         PWFI=N                 PSEUDO=WFI                   
//PROCLIB  DD DISP=SHR,DSN=IMS.PROCLIB      
//DFSCTL   DD DISP=SHR,DSN=IMS.PROCLIB(DFSSBPRM)     
//SYSEXEC  DD  DSN=IMS.SDFSEXEC,            
//             DISP=SHR                                         
//SYSTSIN  DD *                                                 
//SYSTSPRT DD SYSOUT=*                                          
//SYSOUT   DD SYSOUT=*

The IMSMPP01 job executes the DFSMPR procedure provided in the default IMS.PROCLIB. The parameters include the following:

IMSID
The IMS subsystem ID under which to execute
ENVIRON
The name of the IMS.PROCLIB member that contains the library path (LIBPATH) definition for the Java environment
JVMOPMAS
The name of the IMS.PROCLIB member that contains the CLASSPATH and JVM options for the master JVM
CL1, CL2, CL3, CL4
A required positional parameter that specifies four three-digit decimal numbers indicating which classes of messages are to be processed by this message region. The maximum value for a class is 999. The sequence of specifying the classes determines relative class priority within the message region.

Listing 32 defines the ENVIRON settings.

Listing 32. DFSJVMEV sample member
**********************************************************************
* Specify the location of Java Virtual Machine (JVM) installation and 
* IMS Java native code (libT2DLI.so) 
**********************************************************************
LIBPATH=>                                                             
/javaroot/java160/J6.0/bin:>                                          
/javaroot/java160/J6.0/bin/j9vm:>                                     
/usr/lpp/ims/lib

The first two paths specified in DFSJVMEV point to the Java Version 6.0 runtime libraries located in the z/OS UNIX System Services (USS) file system. The third path specifies the location of the libT2DLI.so, which points to the Java native code for IMS type-2 Java connectivity provided in IMS Versions 10 and 11. The libT2DLI.so file is created in the USS file system when running the IMS installation process for Java scenarios. Listing 33 defines the JVM options JVMOPMAS.

Listing 33. DFSJVMMS sample member
********************************************************************  
* Specify the profile that has environment settings and JVM options.  
* The following two JVM options are required.                                  
********************************************************************            
-Djava.class.path=>                                                             
/stjava/ims/IMS Universal driver .jar:>    
/stjava/ims/imsutm.jar:>                                                        
/stjava/SolutionTestApps.jar:>                                                  
********************************************************************            
* The following JVM options are a subset of the options allowed
*                                                                               
* Xmx64M       - set the maximum Java heap size of your program      
* Xmso512k     - set stack size for OS threads for 32 bit     
* Xss256k      - set Java thread stack size    
* Xms1M        - set initial Java heap size      
********************************************************************  
-Xmaxf0.8
-Xminf0.3
-Xmx64M  
-Xmso512k
-Xss256k 
-Xms1M

Be aware of the following details:

  • The CLASSPATH (java.class.path) specifies the IMS Universal driver .jar and imsutm.jar libraries.
  • The IMS Universal driver .jar and imsutm.jar are the libraries required when programming with the IMS Universal driver APIs.
  • The IMS Universal driver .jar and imsutm.jar can be installed using the IMS installation verification program (IVP) for Java scenarios.
  • The IMS Universal driver .jar and imsutm.jar are the libraries required when programming with the IMS Universal driver APIs.
  • The SMP/E installation of the IMS Java On Demand FMID adds the required parts into the appropriate directories in the file system.
  • Before the IMS Java On Demand FMID can be installed, a ZFS or HFS file system must created and mounted.
  • Once this file system has been mounted, the sample job DFSJSMKD is then run to create the directories in the file system.
  • DFSJSMKD calls DFSJMKDR to create the directory structures and symbolic link libT2DLI.so.

MPP environment: Application development

This section describes the MPP application development.

Role: Application Developer

Compile options dll and thread must be specified for the OO COBOL program. The program’s Program-id paragraph must be qualified with the recursive keyword in order for the OO COBOL program to invoke Java methods. The sample code in Listing 34 implements an OO COBOL program (INQPAY.cbl) to Java program (JavaPayPolicy.java) passing a primitive data type and returning a retrieved primitive data type from an IMS database.

Listing 34. INQPAY.cbl
cbl dll,thread
       Identification division.
       Program-id. "INQPAY" recursive.
       Environment division.
       Configuration section.
       Repository.
           Class Base is "java.lang.Object"
           Class JavaException is "java.lang.Exception"
           Class jstring is "jstring"
           Class JavaPayPolicy is "JavaPayPolicy".
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 jpp object reference JavaPayPolicy.
       01 stringBuf pic X(500) usage display.
       01 ccDate object reference jstring.
       01 rc pic s9(9) comp-5
       01 CA-PAYMENT-CCEXP      PIC X(10).
       01 CA-PAYMENT-ID         PIC 9(10).
       01 PAYMENTID PIC S9(9) COMP.  
       01 AMOUNTDUE pic S9(6) comp-5.
       Linkage section.
       COPY STCMAREA.
       COPY JNI.
       01  IOPCB.
           02  LTERM-NAME   PICTURE X(8).
           02  FILLER       PICTURE X(2).
           02  TPSTATUS     PICTURE XX.
           02  FILLER       PICTURE X(3620).
       01  DBPCB.
           02  DBNAME       PICTURE X(8).
           02  SEG-LEVEL-NO PICTURE X(2).
           02  DBSTATUS     PICTURE XX.
           02  FILLER       PICTURE X(20).
       Procedure division USING IOPCB, COMM-AREA, DBPCB.
           Set address of JNIenv to JNIEnvPtr
           Set address of JNINativeInterface to JNIenv
           Move CA-PAYMENT-ID to PAYMENTID
           IF CA-REQUEST-ID EQUAL 'INQPAY  '
           THEN Invoke JavaPayPolicy "getAmountPaid" using by value
               PAYMENTID returning
               AMOUNTDUE
           Goback.
       End program
       "INQPAY".

The sample code in Listing 35 implements an OO COBOL program to Java program passing a primitive data type and returning a retrieved string data type from an IMS database.

Listing 35. INQPAY.cbl code snippet
       Invoke JavaPayPolicy "getCCDate" using by value
		PAYMENTID returning
		ccdate
       Call 'GetStringPlatform'
            using by value JNIEnvPtr
                 ccDate
                 address of stringbuf
                 500
                 0
               returning rc
               If rc not = zero then
                   Display "Error occurred creating CARDEXP object"
                   Stop run
               End-if
               MOVE stringBuf to CA-PAYMENT-CCEXP
           Goback.
       End program
       "INQPAY".

Listing 36 shows the getAmountPaid and getCCDate methods that the OO COBOL program invokes that make an IMS DB call and return the result to the calling OO COBOL program. For more information on passing parameters between OO COBOL and Java programs, data types must be interoperable as described in Enterprise COBOL for z/OS (see Resources).

Listing 36. JavaPayPolicy.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.annotation.Resource;
import javax.annotation.Resource.AuthenticationType;
import javax.sql.DataSource;
import com.ibm.ims.dli.tm.ApplicationFactory;
import com.ibm.ims.dli.tm.Transaction;
import com.ibm.ims.dli.tm.Application;
import com.ibm.ims.jdbc.IMSDataSource;
import java.sql.DriverManager;
import java.util.logging.*;
//import test.PaymentInfo;

import com.ibm.ims.jdbc.IMSDataSource;

 public class JavaPayPolicy
 {		
	 static int amountDue=0;
	 static Application app = null;
	 private static Transaction tran = null;
	 final static Logger loggerDli = Logger.getLogger("com.ibm.ims.db.opendb.dli");
	 final static Logger loggerT2 = Logger.getLogger("com.ibm.ims.db.dli.t2");	
	 
	 	public static String getCCDate(int paymentID) {
		  try{
				
   		    IMSDataSource datasource = new IMSDataSource();
			datasource.setDriverType(IMSDataSource.DRIVER_TYPE_2);
			datasource.setDatastoreName("IMSB");
			datasource.setMetadataURL(
			  "class://databaseviews.S2U1PSBDatabaseView");
			Connection conn = datasource.getConnection();
			conn.setAutoCommit(false);
			// create a statement
			PreparedStatement stmt = conn.prepareStatement(
			  "Select creditCardExp from PGINSUR.Payment where PAYMENTID ="
					+ paymentID);
			while (rs.next()) {
				creditCardExp = rs.getString(1);
		   	}
			rs.close();
			stmt.close();
 			conn.close();
 			app = ApplicationFactory.createApplication();
			tran = app.getTransaction();	

			return creditCardExp;
	 	  }catch(SQLException e) {
	 		e.printStackTrace();
	 		return null;
	 	  }    	   
	 	}	    	    
		public static int getAmountPaid(int paymentID) {
   	      try{
			IMSDataSource datasource = new IMSDataSource();
			datasource.setDriverType(IMSDataSource.DRIVER_TYPE_2);
			datasource.setDatastoreName("IMSB");
			datasource.setMetadataURL(
			   "class://databaseviews.S2U1PSBDatabaseView");
			Connection conn = datasource.getConnection();
			conn.setAutoCommit(false);
			// create a statement
			PreparedStatement stmt = conn.prepareStatement(
			    "Select amount from PGINSUR.Payment where PAYMENTID ="
				+ paymentID);
			while (rs.next()) {
				amountPaid = Integer.parseInt(rs.getString(1));    
	   		}
			rs.close();
			stmt.close();
			conn.close();
			app = ApplicationFactory.createApplication();
			tran = app.getTransaction();	

			return amountPaid;
 		}catch(SQLException e) {
 			e.printStackTrace();
 			return -5;
 		}
	}
}

Listing 37 shows the sample JCL code used to compile and link an OO COBOL program. Program objects must reside in a PDSE. Region size should be set to 96M or greater. Parameter PGMNAME(LONGMIXED) must be specified for compiling.

Listing 37. INQPAY.jcl
//C        EXEC  PGM=IGYCRCTL,REGION=512M,                          
//         PARM='TEST(ALL,SYM,SEP),SOURCE,LIB,MAP,LIST,XREF,NOTERM, 
//                 THREAD,RENT,PGMNAME(LONGMIXED)'                  
//STEPLIB  DD DISP=SHR,DSN=IGYV3R40.SIGYCOMP                        
//         DD DISP=SHR,DSN=CEE.SCEERUN                              
//SYSDEBUG DD DISP=SHR,DSN=IMS.SYSDEBUG(INQPAY)        
//SYSLIN   DD DSN=IMS.OBJ(INQPAY),                     
//             DISP=(OLD,KEEP),SPACE=(CYL,(1,1,1)),UNIT=VIO         
//SYSLIB   DD DISP=SHR,DSN=IMS.COPY   
//SYSPRINT DD DISP=SHR,DSN=IMS.LISTCOB(INQPAY)         
//SYSUT1   DD UNIT=SYSDA,DISP=(,DELETE),                            
//            SPACE=(CYL,(1,1))                      
//SYSUT2   DD UNIT=SYSDA,DISP=(,DELETE),             
//            SPACE=(CYL,(1,1))                      
//SYSUT3   DD UNIT=SYSDA,DISP=(,DELETE),             
//            SPACE=(CYL,(1,1))                      
//SYSUT4   DD UNIT=SYSDA,DISP=(,DELETE),             
//            SPACE=(CYL,(1,1))                      
//SYSUT5   DD UNIT=SYSDA,DISP=(,DELETE),             
//            SPACE=(CYL,(1,1))                      
//SYSUT6   DD UNIT=SYSDA,DISP=(,DELETE),             
//            SPACE=(CYL,(1,1))                      
//SYSUT7   DD UNIT=SYSDA,DISP=(,DELETE),             
//            SPACE=(CYL,(1,1))                      
//SYSIN    DD DISP=SHR,                                              
//         DSN=IMS.COBOL(INQPAY)    
//  SET VAR= '/ENVAR("_CEE_ENVFILE=/Java/ENVAR")'    
//  SET VAR2= 'POSIX(ON),XPLINK(ON)'                           
//L        EXEC PGM=IEWL,                                      
//         PARM='&VAR &VAR2 RENT,LIST,LET,DYNAM(DLL),          
//             CASE(MIXED),MAP,XREF,RMODE(ANY)',               
//            COND=(4,LT,C)                                    
//RESLIB   DD DSN=IMSNST.I11APAR.DBDC.CM1.SDFSRESL,DISP=SHR    
//SYSLIB   DD DSN=SYS1.V1R3M2.COB2LIB,DISP=SHR       
//         DD DISP=SHR,DSN=NEELA.MNA.S2U1F6.COPY      
//         DD DSN=SYS1.MACLIB,DISP=SHR      
//         DD DSN=CEE.SCEERUN,DISP=SHR        
//         DD DSN=CEE.SCEELKED,DISP=SHR      
//         DD DSN=IMS.SDFSRESL,DISP=SHR    
//         DD DSN=IMS.PGMLIB,DISP=SHR               
//SYSLMOD  DD DSN=IMS.PGMLIB(INQPAY),DISP=SHR,UNIT=VIO,  
//            SPACE=(CYL,(1,1,1)),DSNTYPE=LIBRARY                   
//SYSPRINT DD SYSOUT=*                                              
//SYSTERM  DD SYSOUT=*                                              
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(5,1))                          
//SYSDEFSD DD DUMMY                                                 
//OBJMOD   DD DSN=IMS.OBJ,DISP=(OLD,KEEP)              
//SYSLIN   DD *                                                     
  INCLUDE OBJMOD(INQPAY)                                            
  INCLUDE '/javaroot/java160/J6.0/bin/classic/libjvm.x'             
  INCLUDE '/cob42/lib/igzcjava.x'                                   
//*

Troubleshooting

The JVMOPAS parameter is required in the MPP startup region. If the parameter is not specified correctly, then the region abends with a U0101.

If you receive the error message ABEND=S000 U4088 REASON=000003EC, ensure that the region size is 96M or greater.

If you receive the error message IEW2606S 4B39 MODULE INCORPORATES VERSION 3 PROGRAM OBJECT FEATURES AND CANNOT BE SAVED IN LOAD MODULE FORMAT, check that the program object resides in a PDSE.

If you receive the error message Cannot find the libjvm.so file, create a module as shown in Listing 37 and include the created module in the linkage section of the JCL used to compile and link the OO COBOL program.

The linkage JCL is shown in Listing 38.

Listing 38. Linkage JCL
//HLASM    EXEC PGM=ASMA90,PARM='LINECOUNT(0)'                    
//SYSPRINT DD SYSOUT=*                                            
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(1,1))                        
//SYSUT2   DD UNIT=SYSDA,SPACE=(CYL,(1,1))                        
//SYSUT3   DD UNIT=SYSDA,SPACE=(CYL,(1,1))                        
//SYSLIN   DD DSN=NEELA.MNA.S2U1F6.OBJ(SHAYCEE),DISP=SHR          
//SYSLIB   DD DSN=CEE.SCEEMAC,DISP=SHR                            
//         DD DSN=SYS1.MACLIB,DISP=SHR                            
//SYSIN    DD *                                                   
         TITLE 'CEEUOPT'                                          
CEEUOPT  CSECT                                                    
CEEUOPT  AMODE ANY                                                
CEEUOPT  RMODE ANY                                                
         CEEXOPT XPLINK=(ON),                                     
               POSIX=(ON),                                        
               STACK=(512K,512K,ANYWHERE,KEEP,512K,512K),         
               ENVAR=('_CEE_ENVFILE=/Java/ENVAR') 
         END                                                
//*//*

Conclusion

This article describes how IMS offers various solutions for developing and extending applications in customer environments using Java. As part of IMS Versions 10 and 11, IMS provides Universal Driver Database (IMS Universal driver) Java driver support for type-2 connectivity within IMS-dependent regions. This support enables customers to develop new applications in Java using IMS Universal JDBC driver and IMS Universal DL/I driver.

Resources

Learn

Get products and technologies

  • Build your next development project with IBM trial software, available for download directly from developerWorks.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Information management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management
ArticleID=593383
ArticleTitle=Use Java in IMS dependent regions
publish-date=12022010