We’re looking to make some performance improvements in how we manage CICS connections from our webapps.
Here’s what we’ve got:
- Enterprise Server v11 running a single CICS region with a CISAM data store.
- The CICS region has a main driver program (IMO0000) and a primary transaction ID (IMDE), both of which we can consider to be constant for all requests. The driver program is responsible for decoding the request, and delegating to the appropriate program for processing.
- There is no configured service, per se, that handles these requests. The transaction (IMDE) is wired to the default mirror program (DFHMIRS), which goes back to the ECI request to find the program name (IMO0000) to invoke.
- 99.999% of CICS requests come through the Java webapps over TCP. All CICS requests are completely stateless, and each opens its own socket/connection, and closes it upon completion of the request. The other 0.001% of CICS requests are mainly one-offs that would occur rarely during batch cycles. We will continue to make less efficient requests here, as there is no need for connection pooling in a single-threaded scenario.
- Today, a CICS request from a webapp is sent as a ECIBINPRequest object over a ECIBINPConnection. Again, these objects are completely constructed and destroyed with each (stateless) request.
What we would like to do is leverage a shared pool for CICS connections much in the same industry-standard fashion that we do for shared JDBC connection pools. With the high volume of stateless CICS requests we face, it only makes sense to keep the TCP sockets open and reuse these connections. Furthermore, managing these connections in a pool affords us the ability to track and report on pool usage; and to manage a separate queue of our own specifications when these connections are fully consumed.
Understanding that Tomcat is a servlet container, and not an application container, we were forced to get creative. While Enterprise Suite packages sets of “Resource Adapters”, these are meant for full-fledged application servers like WebSphere, JBoss, etc. But by subclassing the SPI ObjectFactory, we’ve created a mechanism for doing this in Tomcat. Here’s an example of what that resource configuration looks like under Tomcat:
<Resource name="eis/CICSConnectionPool" auth="Container" scope="Shareable"
singleton="true" type="com.microfocus.cics.connector.cci.MFECIConnectionFactory"
factory="com.mycompany.pool.CICSPoolFactory"
serverHost="localhost" serverPort="2005"
minSize="5" maxSize="100"
idleTimeout="120000" blockingTimeout="15000"
openTimeoutInSeconds="5" readTimeoutInSeconds="45"
enterpriseServerSocketCloseDueToInactivity="1" trace="false" />
And mechanically, this works. We’re able to obtain connections, and initiate requests. But Enterprise Server is “confused” by these requests. We’re seeing 9041 errors because the server is looking for a service called “IMO0000”. Unlike the previous ECIBINPRequest model, the newer model, which is based on the CCI “interaction” framework, is not following the same path on the server side of using the default mirror. The parameterization of the request is just so different under both models that we can’t make sense of how to convince the new model to do the same thing it was under the old model.
Here is an example of our request code under the new model:
byte[] reqBytes = strReqXml.getBytes("ISO-8859-1");
IndexedRecord input = rf.createIndexedRecord("COMM_AREA");
input.add(reqBytes);
// Setup Connection and Interaction
conn = cf.getConnection();
Interaction interaction = conn.createInteraction();
// Setup Interaction Spec
MFECIInteractionSpec spec = new MFECIInteractionSpec();
spec.setProgramName("IMO0000");
spec.setFunctionName("IMO0000");
spec.setTransactionId("IMDE");
spec.setExtendMode(CCLExtendMode.CCL_NO_EXTEND);
// Once we get this working, we might be able to remove this because we have
// the input object.
spec.setCommArea(new CommArea(reqBytes, "ISO-8859-1"));
// Execute
IndexedRecord output = (IndexedRecord) interaction.execute(spec, input);
And for contrast, here is our request code under the old model:
aConn = new ECIBINPConnection().setConnectionType(ConnectionType.NO_LUW)
.setHost(dfltGatewayHost).setPort(dfltGatewayPort).setOpenTimeout(dfltOpenTimeoutSec)
.setReadTimeout(dfltReadTimeoutSec).setTrace(dfltDoTrace);
aConn.open();
aReq = new ECIBINPRequest(aConn);
ca = new CommArea(reqBytes, "ISO-8859-1");
log.debug("Request CommArea size (in bytes)=" + ca.getLength());
theParams = new CCLParams();
theParams.setVersion(CCLVersion.CCL_VERSION_2);
theParams.setCallType(CCLCallType.CCL_SYNC);
theParams.setProgramName("IMO0000");
theParams.setTransactionId("IMDE");
theParams.setCommArea(ca);
theParams.setExtendMode(CCLExtendMode.CCL_NO_EXTEND);
aReq.setRequestParameter(theParams);
aResp = aReq.send();
I know we’re close. And I expect we’ll need to make a few adjustments to our Enterprise Server or CICS region configurations. Our trial-and-error thus far has fallen short, and there is a serious lack of documentation on these RA packages. We’ve also turned on tracing, and we can see the failed request in the trace log. But we’re unable to make any sense of the trace log itself, nor find the successful request to compare against.
Your thoughts and ideas are much appreciated. Upon request, I’m happy to share some screenshots from ESCWA.

