You can invoke an ETP program or transactions from a non-transaction Java environment. The technique is demonstrated in the Call ETP From Java sample project available when you create new COBOL projects from the Elastic COBOL IDE. This project is technically not a COBOL project, but a simple Java project. But for you to include the sample source code you must select the project from the New Elastic COBOL Project dialog box and select the "Samples" down-arrow. As an alternative, you can create a new Java Project and add files attached to this article.
You can create a new sample project with the New COBOL Project dialog box:
This will create a COBOL project containing only a single Java file in the src directory, ETPCallFromJava.java.(attached). Since ETP transactions are packaged as an Enterprise Java Bean as a single SYSID (i.e., "CICS region") we must use EJB client protocols to access this transaction. It is the same interface that is used for Distributed Program Link (DPL) between two transactions in different SYSIDs. Here are the relevant lines from the attached file:
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;import com.heirloomcomputing.etp.transaction.env.ejb.LinkDispatcherRemote;
import com.heirloomcomputing.etp.transaction.link.CommArea;...
final Properties props = new Properties();
String sysID = "etp2"; // the SYSID (i.e., CICS REGION) to connect
String transID = null;;
String programID = null;
CommArea sendCommArea = null, returnCommArea = null;
boolean syncOnReturn;
String resultString = null;
Object AnyThing = null;props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.openejb.client.RemoteInitialContextFactory");
props.setProperty(Context.PROVIDER_URL, "ejbd://localhost:4201");
//props.setProperty(Context.SECURITY_PRINCIPAL, "system");
//props.setProperty(Context.SECURITY_CREDENTIALS, "manager");// look up the remote system
final Context context = new InitialContext(props);// Get a new EJB Context to the ETP with SYSID "ETP2"
try {
AnyThing = context.lookup("ETPSYSL_" + sysID + "Remote");
} catch (NamingException e) {
System.err.println("ETP server not started or region name '" + sysID + "' not deployed and started.");
e.printStackTrace(System.err);
return;
}
LinkDispatcherRemote ETP2System = (LinkDispatcherRemote) AnyThing;// invoke an ETP transaction from Java
// call either a 4-char trans ID or a COBOL program ID
// (as a Java class: lower case; replace "-" with "_")//transID = "ELNK";
programID = "etpetrn";
sendCommArea = new CommArea("Hello ETP transaction from Java".getBytes());
syncOnReturn = false; // require this program to commit() rather than the transaction itself.
returnCommArea = ETP2System.link(transID, programID, sendCommArea, syncOnReturn);
There are two special classes defined in the Elastic COBOL Runtime Library that are needed for this communication task:
- LinkDispatcherRemote - used to start, commit and rollback transactions as well as link to the program.
- CommArea - a wrappered byte[] array that is sent to the remote program and is returned by the remote transaction .
EJB APIs are used to look up the remote context. In this example the OpenEJB library will be used to connect to the EJB managed by ETP running under a JEE server. Different JEE servers may have different classes, end-point URLs and other properties. The OpenEJB set of properties that define the connection classes and the end-point of the connection are:
- java.naming.factory.initial - the class to be use to manufacture the connection to the destination. (Geronimo default: openejb.client.RemoteINitialContextFactory).
- java.naming.provider.url - the URL indicating the destination JEE server, depending upon the protocol used. (Use EJB Directory Lookup Protocol URL ejbd://host:port).
- java.naming.provider.principal - if the JEE server is running under security, this is the user ID allowing access (optional).
- java.naming.provider.credentials - if the JEE server is running under security, this is the user's password (optional).
When the context is looked up and cast to the LinkDispatcherRemote class several methods are available to the Java program:
- link() - invoke the remote transaction specifying the following parameters
- Transaction ID - The 4-character transaction ID indicating which program should be executed (may be null if Program Name is specified).
- Program Name - the program name in the destination system that should be invoked (may be null if Transaction ID is specified)
- System ID - the 4 character SYSID defining the ETP or "CICS region" name.
- CommArea - an arbitrarily large communications area used to send and receive parameters to the called program. This is a Java byte[] array.
- SyncOnReturn - perform a SYNC (single phase commit transaction) before returning from the transaction. Also affects reinitialization of the program after each LINK. If set to true the transaction's working storage variables will be reset to their initial values after the sync. To improve performance, uncheck the ETP Deployment Setting Reinitialize program on LINK setting and use SyncOnReturn false and explicitly commit() or abort() the transaction after the link() returns.
- prepare() - prepares the first phase of a two phase commit process (if SyncOnReturn is false) on the remote transaction.
- commit() - perform the second or only phase of the two-phase commit process (if SyncOnReturn is false) on the remote transaction.
- rollback() - rollback (abort) theremote transaction
- abort() - abort (rollback) the remote transaction
- abend() - request that the remote transaction to abend
The CommArea passed to the transaction and returned by the transaction. It has the following methods available to it:
- CommArea() - constructor
- CommArea(String ca) - constructor
- CommArea(byte[] ba) - constructor
- CommArea(byte[] ba, offset, length) - constructor
- byte[] toByteArray() - return the CommArea as an array of bytes
Note that if the CommArea contains COBOL data types such as COMP-1, COMP-3, etc. they must be converted to/from Java native object types using library routines in the Elastic COBOL runtime library. See "Java Calling COBOL" examples and sections in the Getting Started Guide.
Each connection library for a JEE server may be different (although most accept OpenEJB protocols) so you must build and package your application with these libraries. When building under Eclipse additional libraries are specified on the Java Build Properties > Libraries dialog box. Use the Add JARs or Add External JARs buttons to find your libraries (like openejb-client and javaee-api) and add them to the list.
When running your program you must also specify these libraries in the CLASSPATH. From the command line,
java -cp ecobol.jar:openejb-client-4.5.2.jar:javaee-api-6.0-5.jar ETPCallFromJava
You can run Java programs under the Elastic Batch Platform just as easily as running COBOL. For running under EBP, set the classpath1..9 configurations to these jar.
*OpenEJB Server Exceptions*
Oracle's WebLogic uses it's own implementation of the RMI specification and favors it's own proprietary protocol known as T3 with the context lookup port 7001.
- java.naming.factory.initial - weblogic.jndi.WLInitialContextFactory.
- java.naming.provider.url - t3://host:port.
Similarly, IBM's WebSphere 8.5 (full profile) utilizes the Internet Intra-ORB Protocol (IIOP) with the context lookup port 2809.
- java.naming.factory.initial - com.ibm.websphere.naming.WsnInitialContextFactory.
- java.naming.provider.url - iiop://host:port.
Example
Attached is ETPETRN.CBL and the ETPCallFromJava.java command line program which invokes it. Create an Elastic COBOL Project in the Elastic COBOL IDE within Eclipse. Make sure to select the Compatibility > Elastic Transaction Platform Template setting in the New COBOL Project dialog box. Place ETPETRN.CBL in the cobol_sources folder. Create an Elastic Transaction Project in the Elastic COBOL IDE under Eclipse and associate with the project you created earlier. Define the following attributes in the ETP Settings for this project:
- General
- SYSID: etp2
- Participating Projects: your-cobol-project-name
- Programs
- Program ID: etpetrn
- Class Name: etpetrn
- Transactions
- Transaction 1:
- Transaction ID: etrn
- Program ID: etpetrn
- Transaction 2:
- Transaction ID: init
- Program ID: etpetrn
- Journals
- Journal Name: journal1
- Protocol: sysout
Select the project name in the Navigator view in Eclipse and deploy with File > Export > Elastic Transaction Platform Deploy Wizard. Save it as etp2.ear. Start Geronimo and connect to its administration console. Use the Deployer menu to deploy etp2.ear. ETRN is not a BMS transaction so you will not be able to invoke it as a Web page, only from the ETPCallFromJava client application.
For the client side, create the ETPCallFromJava project from the built-in sample template as described above. Right click on the Java source and select Run As ... Java Application from the menu. In the Geronimo standard output log (Journal journal1) you will see:
[RC] ETP: Tue Nov 12 17:17:57 PST 2013 (EIBTASKN 7) (EIBTRMID null) (EIBTRNSID CPMI):
ETRN INVOKED WITH COMMAREA LENGTH:000000067
[RC] ETP: Tue Nov 12 17:17:57 PST 2013 (EIBTASKN 7) (EIBTRMID null) (EIBTRNSID CPMI):
ETRN INVOKED WITH EIBDATE 113316 AND EIBTIME 171757
[RC] ETP: Tue Nov 12 17:17:57 PST 2013 (EIBTASKN 7) (EIBTRMID null) (EIBTRNSID CPMI):
AND VALUE:Hello ETP transaction from Java
[RC] ETP: Tue Nov 12 17:17:57 PST 2013 (EIBTASKN 7) (EIBTRMID null) (EIBTRNSID CPMI):
ETRN RETURNING COMMAREA LENGTH:000000067
[RC] ETP: Tue Nov 12 17:17:57 PST 2013 (EIBTASKN 7) (EIBTRMID null) (EIBTRNSID CPMI):
AND VALUE:The current date is 11/12/13 (EIBDATE 113316)
In the ETPCallFromJava standard output you will see:
ETP call From Java example
EJB Context Lookup properties:
{java.naming.provider.url=ejbd://localhost:4201, java.naming.factory.initial=org.openejb.client.RemoteInitialContextFactory}
Nov 12, 2013 5:17:57 PM org.apache.openejb.client.EventLogger log
INFO: RemoteInitialContextCreated{providerUri=ejbd://localhost:4201}
Nov 12, 2013 5:17:57 PM org.apache.openejb.client.EventLogger log
INFO: ConnectionOpened{uri=ejbd://localhost:4201}
ETP2 program etpetrn returned 67 bytes.
returned communications area:The current date is 11/12/13 (EIBDATE 113316)
Transaction Semantics
There are a number of ways to commit transactions executing within ETP.
- The transactions can commit themselves
- The transactions can be implicitly committed by the Java program
- The transactions can be explicitly committed by the Java program
The first is to have the transaction contain the ETP API to commit the entire transaction
EXEC CICS
SYNCPOINT
END-EXEC
or commit just the SQL resources attached by the transaction with the ETP SQL API,
EXEC SQL
COMMIT WORK
END-EXEC
The latter form may not be allowed in some circumstances and the Elastic COBOL compiler will generate a warning. It depends on whether the SQL resources can be committed independently of other resources (Journals, Spools, Queues, etc.).
The second option is the implicit transaction commit while the transaction is returning. The syncOnReturn option of the link() API indicates this should happen. In the client code one would call the transaction with,
syncOnReturn = true; // request the transaction commit itself
returnCommArea = ETP2System.link(transID, programID, sendCommArea, syncOnReturn);
The third option gives explicit control to the client application, possibly based on the values contained in the return COMMAREA.
syncOnReturn = false; // transaction control here
returnCommArea = ETP2System.link(transID, programID, sendCommArea, syncOnReturn);
if (returnCommArea.getLength() == 0) {
ETP2System.rollback(); // something went wrong
} else {
ETP2System.commit(); // it worked
}
Explicit transaction control also allows the client application to also use 2-phase commit protocol if the underlying resources of the transaction (XA compliant JDBC database drivers, for example) allow it. In this case the prepare() API can be used before the commit() API allowing the client to control resources that are unknown to the back-end system.
Note: Not doing anything of these options will result in the transaction being rolled back.
The options are included in the (extended) example program. The client application ETPCallFromJava has been extended to take a combination of parameters that demonstrate these options and the ETPETRN transaction modified to issue a database insert statement. The table "t" of the configured database should contain a single CHAR(10) column to hold the time-of-day the transaction was executed. If the transaction was committed, the TOD will be inserted and can be checked offline.
Here are the options to the ETPCallFromJava application:
Usage: java ETPCallFromJava [-sr] [-r] [-c] [-p] [-a] [-q]
[-s milli] [-sys sysid] [-trans transid] [-prog progid]
[-host hostid] [-user userid] [-password pw]
[-i iterations] [-b beans] [msg]
-sr - pass syncOnReturn to transaction link
-p - prepare a commit
-a - abort the prepare
-c - commit
-r - rollback
-q - do not print messages
-s milli - wait milliseconds between each transaction (default:0)
-sys sysid - system id to contact (default:etp1)
-tran transid - transaction to invoke (default:<none>)
-prog progid - program name to invoke (default:etpetrn)
-host hosturl - ETP connection host (default:ejbd://localhost:4201)
-user userid - ETP connection user (default:<none>)
-password pw - ETP connection password (default:<none>)
-i iterations - perform n transactions per bean, default 1
-b beans - start beans sessions n transactions per bean, default 1
msg - COMMAREA msg to sendWhen invoking ETPETRN program or the ETRN transaction
the 'msg' may be:'INSERT' - ETRN SQL INSERTs current time into table T
'SYNC' - ETRN issues EXEC CICS SYNC
'COMMIT' - ETRN issues EXEC SQL COMMIT
'COUNT' - ETRN increments a working-storage counter
'INIT' - ETRN INITIALIZEs the working-storage counter
'POINTER' - ETRN assigns a POINTER
'CALL ETPETRN' - COBOL call to ETPETRN, then GOBACK
'TRAN ETRN' - EXEC LINK to TRAN ETRN, then EXEC RETURN
'PROG ETPETRN' - EXEC LINK to PROGRAM ETPETRN, then EXEC RETURN
'GOBACK' - after finishing other commands GOBACK
'RETURN' - after finishing other commands EXEC RETURN
'TRAN ETRN INSERT GOBACK'- EXEC LINK to ETRN, then insert,
then GOBACK instead of EXEC RETURN
'TRAN ETRN CALL ETPETRN INSERT'- EXEC LINK to ETRN, then
recursivly call it again, then insert
'TRAN ETRN CALL ETPETRN PROG ETPETRN GOBACK INSERT POINTER'
4-level call, insert, assign a ptr in 3rd level
Note: A transaction performs differently depending on whether the Reinitialize programs on LINK checkbox is checked (default) or unchecked on the Programs tab of the ETP Deploy Settings. This setting indicates whether the transaction state should be reinitialized on every call (checked - default) or just on each new "bean" or "session" (ETPCallFromJava -b option above). Reinitialization of a program takes considerable amount of time in a high-transaction environment but guarantees each transaction starts in the same state.
Note: The link() SyncOnReturn setting also affects reinitialization. When set to true, the transaction will always be reinitialized regardless of the Reinitialize programs on LINK checkbox. In other words, to avoid reinitialization you must set SyncOnReturn to false and explicitly commit() the transaction after link()ing to it. You may need to use the COBOL INITIALIZE statement on working storage elements or groups that must be reinitialized to zero or blanks.
The following table indicates the outcome, data saved or not saved into table "t", based on the options:
Client Options | Sync On Return | ETRN Options | Result |
false | INSERT | Not Saved | |
-c | false | INSERT | Saved |
-r | false | INSERT | Not Saved |
-p | false | INSERT | Not Saved |
-p -c | false | INSERT | Saved |
false | INSERT SYNC | Saved | |
false | INSERT COMMIT | Saved | |
true | INSERT | Saved | |
true | INSERT SYNC | Saved | |
true | INSERT COMMIT | Saved | |
-p -c | true | INSERT SYNC | Saved |
Following is an example of an invocation of this program which simulates the Heirloom ETPJCA connector connection to a transaction. The transaction links to a second transaction which links to a third transaction, which inserts data into a database table, SYNCs upon return from the top level transaction and executes that sequence 10000 times:
java ETPCallFromJava -sr -i 10000 EXEC ETRN CALL ETPETRN INSERT
0 Comments