IBM Support

Java application tries to reuse a session and gets javax.jms.IllegalStateException

Troubleshooting


Problem

You access WebSphere MQ V6.0 queues using JMS from a Java™ application which sits in EJB beans in WebSphere Application Server. The application has been running for a number of years with no errors, in WebSphere Application Server V5. You are now trying to run exactly the same Java application on WebSphere Application Server V6. The bean creates a connection to a queue. It then creates a session on this connection, using: queueSession = queueConnection.createQueueSession(transactional,Session.AUTO_ACKNOWLEDGE); It then creates a sender, and places a message on the queue. When access is completed, the session is closed, but the connection is left open for re-use. This is done for performance reasons.The application which is deployed on WebSphere Application Server V6 fails at the point when it tries to re-use a connection on the queue. The createQueueSession method fails, creating an associated ffdc log. The relevant section of the failing method stack from the ffdc log shows: javax.jms.IllegalStateException com.ibm.ejs.jms.JMSQueueConectionHandle.createQueueSession 159Exception = javax.jms.IllegalStateExceptionSource = com.ibm.ejs.jms.JMSQueueConnectionHandle.createQueueSessionprobeid = 159 Stack Dump = javax.jms.IllegalStateException: Connection closed at com.ibm.ejs.jms.JMSConnectionHandle.checkOpen(JMSConnectionHandle.java:671) at com.ibm.ejs.jms.JMSQueueConnectionHandle.createQueueSession( JMSQueueConnectionHandle.java:172) at com.littlewoods.enterprise.framework.services.AsyncPutterBean.getSession (Unknown Source) at com.littlewoods.enterprise.framework.services.AsyncPutterBean.GenericPut (Unknown Source)

Cause

When the genericPut method completes, then a connection handle which was retrieved from the pool is dissociated from the application and returned to the JMS connection pool as part of the EJBPostInvoke() method.This happens when the local transaction associated with the put completes. As part of the Transaction commit, the ContainerTx class tries to release resources if the Transaction state is COMMITTED. As part of releasing resources the HandleList class tries to close all JMS, JDBC and resource cci connectionhandles.

In WebSphere Application Server when Connection pooling is enabled physical connections are always pooled. Applications requesting a connection to the backend resource actually get a connectionHandle to the ManagedConnection object, which sits in the pool. Whenever the application calls a connection close the associated handle is closed and not the managed physical connection. Whenever the application re-requests for a connection, the Pool Manager assigns it a new connectionHandle to the same Managed physical connection.

The Illegal State occurred because the EJB Container is responsible for managing the behavior of the bean. When an EJB method is called, a transaction is started. This transaction is committed or rolled back when the method exits. As part of the commit or rollback processing, the EJB Container will also close any open JMS or JDBC connections associated with the bean automatically. A trace reveals that just a few moments before the IllegalStateException occurs The PoolManager shows a total of 45 connections in the pool with their state as STATE_ACTIVE_FREE, with all connections having 0 open connection handles. This clearly shows that all active connections in the pool have had their connection handles closed.

In other words the EJB container, as part of the post invoke, cleans up all connectionHandles that it acquired during the preInvoke, when the transaction boundary ends.

Resolving The Problem

1. Modify the application to create a new JMS connection every time the EJB is called. This is the recommended solution.

This will not have too much impact on performance, due to the way the application server's connection pooling mechanism works. The first time the EJB is invoked, the application server will create a new physical connection to MQ. However, when the EJB method exits, the physical connection is left open and returned to the connection pool. The second time the EJB runs and calls QueueConnectionFactory.createQueueConnection(), the application server will simply return the connection from the pool. This means that there is minimal overhead in calling createQueueConnection() again.

2. Change the value of the TransactionResolver attribute in the EJB's deployment descriptor from "ContainerAtBoundary" to "Application".

Making this change means that the EJB is responsible for closing any JMS or JDBC connections, and committing or rolling back any transactions, when a method exits.

[{"Product":{"code":"SSFKSJ","label":"WebSphere MQ"},"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Component":"Java","Platform":[{"code":"PF002","label":"AIX"},{"code":"PF010","label":"HP-UX"},{"code":"PF016","label":"Linux"},{"code":"PF027","label":"Solaris"}],"Version":"6.0","Edition":"","Line of Business":{"code":"LOB45","label":"Automation"}},{"Product":{"code":"SSEQTP","label":"WebSphere Application Server"},"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Component":"EJB Container","Platform":[{"code":"PF002","label":"AIX"},{"code":"PF010","label":"HP-UX"},{"code":"PF016","label":"Linux"},{"code":"PF027","label":"Solaris"},{"code":"PF033","label":"Windows"}],"Version":"6.1;6.0","Edition":"","Line of Business":{"code":"LOB45","label":"Automation"}}]

Product Synonym

WMQ;WebSphere MQ

Document Information

Modified date:
15 June 2018

UID

swg21267957