Hi, we have done something similar with a customer. The difference was, that they have called WebSphere ILOG as business rules engine. The COBOL Java approach worked very well. But you need to make sure that you code JNI calls and do not use the INVOKE syntax of the COBOL compiler. I'll attach some code. COBOL and Java run in the same address space so in terms of performance you save the cross address space calls. The JVM is reusable for the lifetime of the batch region, with the latest enhancements of JDK 6.0.1 it is great performance. There was one difference, we also executed the rules engine (ILOG) which is implemented in Java on z/OS. So we did not do calls to outside z/OS, which are most likely the biggest performance eaters. But there is still the option to run multithreaded.
[Environment] As for development, there are plenty of tools on the market, which generate Java code from WSDL (Eclipse, Rational Application Developer, etc.), so there is almost no coding to be done apart from Data conversion. It is recommended to pass copybooks by reference and then make a byte array out of it which is passed to java. Then use the JZOS record generator to create a Java class with matching offsets getter and setter methods to be used in Java. Since all our data was fixed length strings, in the Java part we just did String.substring to get the data as Java String. You need a JDK on z/OS to do that. Thats it. If you want DB2 calls from Java and COBOL transactional, you need RRSAF linked with COBOL and the JDBC Driver for Java. [Development Process] The development process would be like this, that the z/OS people create the cobol code as samples are below: Plus use the JZOS record generator to generate Java classes from any used input and output copybooks. Send the generated Java classes to the Java devlopers with the WSDL. The Java developers would generated a Java proxy for the web service from the WSDL. The Java developers have to code a method with an input and output byte array for the data to be passed from and to COBOL, plus they have to implement the getter and setter methods to fill the input to the web service from the byte array and to retrieve the output from the web service and pass it to the output byte array. This is manual work, but could be simple depending on the data types, offsets, etc. The Java developers test the web service from Java with some sample data and create the Jar file with all dependencys or get you a bunch of Jar files. The jar files are uploaded to z/OS. You can run and test the batch. [Sample Scenario] Our scenario was as follows, this is simplified: Main Program CJ01MAIN (NODLL) reads records from sequential file, calls subroutine and writes output to sequential file. (needs to be linked with CEEUOPT to set XPLINK(ON) and POSIX(ON) LE runtime options). This allows to simply code a MOVE 'CJ01KAPS' TO MODULE plus CALL MODULE to invoke the subroutine dynamically. Wrapper subroutine CJ01KAPS , because Java runs as DLL compiled, dynamic calls are only possible from DLL to DLL and from NODLL to NODLL. COBOL subroutine CJ01JAVA which implements the JNI calls, preparing the byte array objects, caching the objects and some ids to save most of the JNI overhead during repeated processing, passing the copybook data to the bytearray object, find the java class and method to be called, call the java method and pass the result byte array object into an output copybook. This is a sample of CEEUOPT to be linked with the main program: //SYSIN DD * TITLE 'CEEUOPT' CEEUOPT CSECT CEEUOPT AMODE ANY CEEUOPT RMODE ANY CEEXOPT XPLINK=(ON), X POSIX=(ON), X ENVAR=('_CEE_ENVFILE=/u/gaebler/hello/ENV') END //* The File /u/gaebler/hello/ENV contains the environment variables for Java: PATH=/bin:/usr/lpp/java/J6.0/bin:. LIBPATH=/lib:/usr/lib:/usr/lpp/java/J6.0/bin:> /usr/lpp/java/J6.0/bin/j9vm:/usr/lpp/db2/db2910/db2910_jdbc/lib CLASSPATH=/u/gaebler/hello.jar The classpath can be one or multiple jar files or directorys and should contain the Java classes and all dependent jar files. [Sample compile] CJ01COMP [Sample wrapper source] CJ01KAPS [Sample JNI calls in cobol sub source] CJ01JAVA If you need assistence please feel free to contact me directly. mfg / best regards Denis Gäbler IMS Senior Technical Sales Professional Kst.: B471, Geb.: 10, Am Keltenwald 1, Ehningen, 71139, Germany Chat with me through AIM (AOL Instant Messenger): For people outside IBM, use AOL and add the IBMers: x...@yy.ibm.com Fax: +49-(0)30-484986506 Funk: +49-(0)172-6286935 IBM Deutschland GmbH / Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Martina Koederitz (Vorsitzende), Reinhard Reschke, Dieter Scholz, Michael Diemer, Gregor Pillen, Joachim Heel Sitz der Gesellschaft: Ehningen / Registergericht: Amtsgericht Stuttgart, HRB 14562 / WEEE-Reg.-Nr. DE 99369940 ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@bama.ua.edu with the message: GET IBM-MAIN INFO Search the archives at http://bama.ua.edu/archives/ibm-main.html
//CJ01COMP JOB , // MSGCLASS=A,TIME=1440,USER=&SYSUID, // MSGLEVEL=(1),REGION=0M //* //* Definitions //* // SET IMSHLQ=IMS.IMSD // SET DSNHLQ=DB2.V9R1 // SET DB2SSID=DSNA // SET CEEHLQ=CEE // SET SYS1HLQ=SYS1 // SET SRCHLQ=DDS1479.CJLAB //* //* Change the following occurences of paths and qualifiers in SYSIN //* In the CEEUOPT Assembly change /u/itso12/hello to the path that //* will contain the files uploaded from Eclipse //* In the CJ01JAVA Assembly change /usr/lpp/java/J5.0 to the path //* that contains the JAVA 5 JDK on your system //* In the CJ01JAVA Aseembly change /usr/lpp/cobol to the path //* that contains the Enterprise COBOL compilers HFS installation //* In the DB2GRANT and BINDJDBC jobsteps change the DB2 SSID DB9H //* to the DB2 SSID of your system and the DB9H9 DB2 High Level //* Qualifier to the one of your DB2 system //* //* Lib containing the COBOL compiler procedures //* //PROC04 JCLLIB ORDER=(&SRCHLQ..PROCLIB) //* //* Create CEEUOPT //* //CEEUOPT 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 DSNAME=&&OPTIONS(CEEUOPT),UNIT=SYSALLDA, // DISP=(MOD,PASS),SPACE=(TRK,(3,3,5)), // DCB=(BLKSIZE=3200) //SYSLIB DD DSN=&CEEHLQ..SCEEMAC,DISP=SHR // DD DSN=&SYS1HLQ..MACLIB,DISP=SHR //SYSIN DD * TITLE 'CEEUOPT' CEEUOPT CSECT CEEUOPT AMODE ANY CEEUOPT RMODE ANY CEEXOPT XPLINK=(ON), X POSIX=(ON), X ANYHEAP=(3M,128K,ANY,FREE), X HEAP=(80M,10M,ANY,KEEP,16K,8K), X HEAPPOOLS=(ON,8,10,32,10,128,10,256,10,1024,10,2048,10, X 0,1,0,10,0,10,0,10,0,10,0,10), X STACK=(64K,16K,ANY,KEEP,128K,128K), X STORAGE=(NONE,NONE,NONE,0K), X THREADSTACK=(OFF,64K,16K,ANY,KEEP,128K,128K), X TERMTHDACT=(UADUMP), X ENVAR=('_CEE_ENVFILE=/u/dds1479/CJ01ENVIMSDB2') END //* //* //* Compile and Link of Main IMS Transaction //* //CJ01MAIN EXEC DSNHICOB,MEM=CJ01MAIN,USER=&SYSUID, // PARM.COB=RENT,REGION=1400K, // PARM.LKED='RENT,LIST,XREF,LET,MAP' //PC.SYSIN DD DSN=&SRCHLQ..SOURCE(CJ01MAIN),DISP=SHR //PC.SYSLIB DD DUMMY //LKED.SYSLMOD DD DSN=&IMSHLQ..PGMLIB(CJ01TRAN),DISP=SHR //LKED.SYSLIB DD DSN=&IMSHLQ..SDFSRESL,DISP=SHR // DD DSN=&DSNHLQ..SDSNLOAD,DISP=SHR // DD DSN=&CEEHLQ..SCEELKED,DISP=SHR // DD DSN=&CEEHLQ..SCEELKEX,DISP=SHR // DD DSN=&SYS1HLQ..CSSLIB,DISP=SHR // DD DSNAME=&&OPTIONS,DISP=(OLD,DELETE) //LKED.SYSIN DD * INCLUDE SYSLIB(CEEUOPT) ORDER CEEUOPT INCLUDE SYSLIB(DSNTIAR) INCLUDE SYSLIB(DFSLI000) ENTRY CJ01MAIN NAME CJ01TRAN(R) /* //* //* Compile and Link of COBOL Subroutine Executing Java Class //* //* //CJ01JAVA EXEC IGYWCPL,PARM.COBOL='RENT',REGION=1400K, // PARM.LKED='RENT,LIST,XREF,LET,MAP,DYNAM(DLL),CASE(MIXED)' //COBOL.SYSIN DD DSN=&SRCHLQ..SOURCE(CJ01JAVA), // DISP=SHR //* Dataset containing JNI.cpy //COBOL.SYSLIB DD DISP=SHR,DSN=&SRCHLQ..SOURCE //LKED.SYSLMOD DD DSNAME=&&MODULES(CJ01JAVA),UNIT=SYSALLDA, // DISP=(MOD,PASS),SPACE=(TRK,(3,3,5)), // DCB=(BLKSIZE=3200) //LKED.SYSLIB DD DSN=&IMSHLQ..SDFSRESL,DISP=SHR // DD DSN=&CEEHLQ..SCEELKED,DISP=SHR //PLKED.SYSIN DD // DD PATH='/usr/lpp/java/J6.0/bin/j9vm/libjvm.x' // DD PATH='/usr/lpp/cobol/lib/igzcjava.x' //LKED.SYSIN DD * INCLUDE '/usr/lpp/java/J6.0/bin/j9vm/libjvm.x' INCLUDE '/usr/lpp/cobol/lib/igzcjava.x' ENTRY CJ01JAVA NAME CJ01JAVA(R) /* //* //* Compile and Link of COBOL DLL,LIB Wrapper for previous Step //* //* //CJ01KAPS EXEC IGYWCL,PARM.COBOL='RENT,NODLL,NODYNAM',REGION=1400K, // PARM.LKED='RENT,LIST,XREF,LET,MAP' //COBOL.SYSIN DD DSN=&SRCHLQ..SOURCE(CJ01KAPS), // DISP=SHR //LKED.SYSLMOD DD DSN=&IMSHLQ..PGMLIB(CJ01KAPS),DISP=SHR //LKED.SYSLIB DD DSN=&IMSHLQ..SDFSRESL,DISP=SHR // DD DSN=&CEEHLQ..SCEELKED,DISP=SHR // DD DSNAME=&&MODULES,DISP=(OLD,DELETE) //LKED.SYSIN DD * NAME CJ01KAPS(R) /* //BINDJDBC EXEC PGM=IKJEFT01,DYNAMNBR=20 //DBRMLIB DD DISP=SHR,DSN=&DSNHLQ..SDSNDBRM // DD DISP=SHR,DSN=&SYSUID..DBRMLIB.DATA //STEPLIB DD DISP=SHR,DSN=&DSNHLQ..SDSNLOAD //SYSTSPRT DD SYSOUT=* //SYSPRINT DD SYSOUT=* //SYSUDUMP DD SYSOUT=* //SYSTSIN DD * DSN SYSTEM(DSNA) BIND PACKAGE(DDS1479) MEMBER(CJ01MAIN) - ISOLATION(UR) QUALIFIER(SYSIBM) BIND PLAN(CJ01TRAN) - PKLIST(DDS1479.CJ01MAIN, - NULLID.SYSLH200, - NULLID.SYSSTAT) END /* //DB2GRANT EXEC PGM=IKJEFT01,DYNAMNBR=20 //STEPLIB DD DISP=SHR,DSN=&DSNHLQ..SDSNLOAD //SYSTSPRT DD SYSOUT=* //SYSTSIN DD * DSN SYSTEM(DSNA) RUN PROGRAM(DSNTIAD) PLAN(DSNTIA91) - LIB('DB2.V9R1.DSNA.RUNLIB.LOAD') END //SYSPRINT DD SYSOUT=* //SYSUDUMP DD SYSOUT=* //SYSIN DD * GRANT EXECUTE ON PLAN CJ01TRAN TO PUBLIC; COMMIT; //* ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@bama.ua.edu with the message: GET IBM-MAIN INFO Search the archives at http://bama.ua.edu/archives/ibm-main.html
CBL APOST,NODLL,NODYNAM,RENT 00010000 * DUMMY MODULE WITH NO LOGIC TO PROVIDE A WRAPPER FOR * LIB,DLL COMPILED MODULES, WHICH JAVA IS USING IDENTIFICATION DIVISION. 00020000 PROGRAM-ID. 'CJ01KAPS'. 0003000 * 00390000 ENVIRONMENT DIVISION. 00400000 CONFIGURATION SECTION. 00410000 SOURCE-COMPUTER. IBM-370. 00420000 OBJECT-COMPUTER. IBM-370. 00430000 * 00440000 DATA DIVISION. 00450000 WORKING-STORAGE SECTION. 00460000 * 00470000 LINKAGE SECTION. 01900000 * 01910000 * COMMENT TO REMIND WHAT DATATYPES THE CALLING VARIABLES ARE * 01 JAVARC USAGE IS POINTER. 01 JAVAIN USAGE IS POINTER. 01920000 01 JAVAOUT USAGE IS POINTER. 01920000 * 02020000 PROCEDURE DIVISION USING JAVARC, JAVAIN, JAVAOUT. 02030000 * 02040000 * ON ENTRY CALLER PASSES ADDRESSES FOR JAVA INPUT AND OUTPUT 02050000 * 02060000 * MAIN PROGRAM JUST OUTPUTS TRACING INFORMATION * AND CALLS THE CJ01JAVA MODULE STATICALLY * MAIN-RTN. 02070000 * Static call to get around DLL/NODDL restriction CALL 'CJ01JAVA' USING JAVARC, JAVAIN, JAVAOUT. 0208000 MAIN-RTN-END. GOBACK. ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@bama.ua.edu with the message: GET IBM-MAIN INFO Search the archives at http://bama.ua.edu/archives/ibm-main.html
cbl lib,dll,pgmname(longmixed),noexp 00000108 * 00000207 * Sample program to call a Java Class 00000307 * 00000407 * Compile options, lib, thread and dll to be java compatible 00000507 * 00000607 Identification Division. 00002000 * recursive required for Java interaction 00002107 Program-id. "CJ01JAVA" recursive. 0000300 Environment Division. 00004000 Configuration section. 00005000 * Repository requires Java Class Definitions and mapping 00005107 * to Java package and class name 00005207 Repository. 00006000 Class Base is "java.lang.Object" 00007000 Class Hello is "com.ibm.cjlab.CJ0xHello" 00008000 Class JavaException is "java.lang.Throwable" 00008100 Class jbytearray is "jbytearray" 00008200 Class jclass is "jclass". Data division. 00009300 Working-storage section. 00009400 * This is the place for storing the Global References * that they can be reused for further invokations of the same * module as long as the module is loaded * This saves lots of CPU for saved JNI calls 01 cached-class-reference object reference Hello value null. 01 STATIC-METHOD-ID PIC S9(9) BINARY VALUE 0. 01 cachedDataByteArray object reference jbyteArray value null. Local-storage section. 00009400 * Now declaring the local instance variables for the objects 00009507 * that contain a class when it was instanciated 00009607 01 ex object reference JavaException. 00009907 01 exObject object reference jclass. 01 DataByteArray object reference jbyteArray. 01 OutputByteArray object reference jbyteArray. 01 class-reference object reference Hello. * Simple cobol variables 00010007 01 rc pic s9(9) comp-5. 00010200 01 laenge pic s9(9) comp-5 value 50. 01 offset pic s9(9) comp-5 value 0. 01 len pic 9(9) binary. 01 method-name pic x(50). 01 class-name pic x(50). 01 method-parm-description pic x(50). 01 input-string pic x(50). 01 JMETHOD-ID PIC S9(9) BINARY VALUE 0. * Shows how to pass variables to the subroutine 00010307 Linkage section. 00010400 01 JAVARC PICTURE S9(3) COMP. 00010500 01 JAVAIN PIC X(50). 00010600 01 JAVAOUT PIC X(50). 00010700 * Copybook for JNI copybooks and function pointer definitions 00010807 Copy JNI. 00010900 Procedure Division USING JAVARC, JAVAIN, JAVAOUT. 00011000 * Required JNI setup 00011107 Set address of JNIenv to JNIEnvPtr 00011200 Set address of JNINativeInterface to JNIenv 00011300 * When Global Instance of Input ByteArray exists If cachedDataByteArray = null * Create a new Input Byte Array (Local Reference) Call NewByteArray using by value JNIEnvPtr by value laenge returning DataByteArray * Check for Error 00014307 Perform JavaExceptionCheck 00014405 * And make this ByteArray a Global Reference Display 'newglobalref start.' Call NewGlobalRef using by value JNIEnvPtr by value DataByteArray returning cachedDataByteArray * Check for Error 00014307 Perform JavaExceptionCheck 00014405 Display 'newglobalref ended.' Else * Create a local reference of Input Byte Array * From the Global Reference which is saved in * Working Storage Display 'newlocalref start.' Call NewLocalRef using by value JNIEnvPtr by value cachedDataByteArray returning DataByteArray * Check for Error 00014307 Perform JavaExceptionCheck 00014405 Display 'newlocalref ended.' End-if * Populate the Input Byte Array from the Input String 00011507 * passed to the routine Move javain to input-string Display 'SetByteArrayRegion start.' Call SetByteArrayRegion using by value JNIEnvPtr, DataByteArray, offset, laenge, address of input-string * Check for Error 00014307 Perform JavaExceptionCheck 00014405 * Create a local class reference by using Findclass * If there is no cached class in working storage If cached-class-reference = null * Make sure the global version of static method id is also * null Move 0 to STATIC-METHOD-ID * Set Class Name Move z"com/ibm/cjlab/CJ0xHello" to class-name * Convert Class Name to ascii Call "__etoa" using by value address of class-name returning len * Do the FindClass call with the ascii class name Display 'FindClass start.' Call FindClass using by value JNIEnvPtr address of class-name returning class-reference * Check for Error 00014307 Perform JavaExceptionCheck 00014405 * If there is no class reference after Findclass * either the class is not in the classpath, the class has * the wrong class version (e.g. invoking a Java 6 compiled * class with a JDK 5 JVM) or something else went wrong If class-reference = null Display "Error occurred locating TestClass class" * Call ExceptionClear using by value JNIEnvPtr Goback End-if * After successful Findclass create a global reference * and store it in working storage for reuse Display 'Findclass NewGlobalRef' Call NewGlobalRef using by value JNIEnvPtr by value class-reference returning cached-class-reference * Check for Error 00014307 Perform JavaExceptionCheck 00014405 Display 'findclass ended.' Else * When the cached Class Reference in Working Storage is * already there, create a Locally useable reference from it Call NewLocalRef using by value JNIEnvPtr by value cached-class-reference returning class-reference * Check for Error 00014307 Perform JavaExceptionCheck 00014405 Display 'newlocalref instead of findclass ended.' End-if * Static Method Id from working storage is 0 when getstatic * methodid was not executed or findclass was executed the * first time * The static method id remains the same as long as the same * instance of the JVM remains active If STATIC-METHOD-ID = 0 * Move static method name to variable Move z"executeWithByteArray" to method-name * And convert to ascii Call "__etoa" using by value address of method-name returning len * Move method signature (accept and return byte array) * to variable Move z"(B)B" to method-parm-description * And convert to ascii Call "__etoa" using by value address of method-parm-description returning len * Call GetStaticMethodID with method name and signature * returning static-method-id call GetStaticMethodID using by value JNIEnvPtr by value class-reference address of method-name address of method-parm-description returning STATIC-METHOD-ID * Check for Error 00014307 Perform JavaExceptionCheck 00014405 * If static-method-id is 0 something went wrong If STATIC-METHOD-ID = 0 Display "Error occurred while getting STATIC-METHOD-ID" Goback End-if Display 'getstaticmethodid ended.' End-if * Check for Error 00011707 Perform JavaExceptionCheck 00011800 * Finally invoke the static method with DataByteArray as * Input and OutputByteArray as Output call CallStaticObjectMethod using by value JNIEnvPtr by value class-reference by value STATIC-METHOD-ID by value DataByteArray returning OutputByteArray * Check for Error Perform JavaExceptionCheck * Retrieve the OutputByteArray from the Java Method Display 'GetByteArrayRegion started.' Call GetByteArrayRegion using by value JNIEnvPtr, OutputByteArray, offset, laenge, address of javaout * Check for Error 00014307 Perform JavaExceptionCheck 00014405 Display Javaout * Delete Local Object Reference OutputByteArray because it is * no longer needed Call DeleteLocalRef using by value JNIEnvPtr by value OutputByteArray * We're done and return to caller 00014507 Goback 00014600 . 00014700 * Check for an Exception occured in Java 00014807 JavaExceptionCheck. 00014900 * ExceptionOccured JNI function returns Exception object 00015007 Call ExceptionOccurred using by value JNIEnvPtr 00015100 returning ex 00015200 * If its not null then Exception was not caught in Java 00015307 * and needs to be analyzed with JNI calls * If you don't catch the Exceptions in the Java code you will 00015407 * land here and to go back to Java you need to call another 00015507 * method, so better handle all Exceptions in Java try catch 00015607 * blocks 00015707 If ex not = null then 00016000 * Display a message to the Job output 00017107 Display "Caught an unexpected exception" 00018000 * Get the actual Java Object Reference for the Exception object call GetObjectClass using by value JNIEnvPtr by value ex returning exObject * Print the Exception Stack Trace to get a clue what went wrong 00018107 Call ExceptionDescribe using by value JNIEnvPtr 00017000 * Move static method name to variable Move z"printStackTrace" to method-name * And convert to ascii Call "__etoa" using by value address of method-name returning len * Move method signature (accept and return byte array) * to variable Move z"(V)V" to method-parm-description * And convert to ascii Call "__etoa" using by value address of method-parm-description returning len * Call GetMethodID with method name and signature * returning jmethod-id Display 'GetMethodID in Exception' call GetMethodID using by value JNIEnvPtr by value exObject address of method-name address of method-parm-description returning JMETHOD-ID if not JMETHOD-ID = 0 then Display 'CallVoidMethod in Exception' call CallVoidMethod using by value JNIEnvPtr by value exObject by value JMETHOD-ID by value 0 End-If * Clear the Exception 00016107 Call ExceptionClear using by value JNIEnvPtr 00017000 * Set error code to 100 00019109 MOVE 100 TO JAVARC 00019209 * Return to caller 00019809 Goback 00020009 End-if 00030000 . 00040000 End program "CJ01JAVA". 0005000 ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@bama.ua.edu with the message: GET IBM-MAIN INFO Search the archives at http://bama.ua.edu/archives/ibm-main.html