mq
  1. mq
  2. MQ-216

Exception caused when setting client ID to a Connection created out of ConnectionFactory without ClientID

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: mq-ra
    • Labels:
      None
    • Environment:

      Glassfish v4.0 b45 Windows

      Description

      Exception caused when setting client ID to a Connection created out of ConnectionFactory without ClientID.

      The attached JMS client does the followings:
      1. Lookup a ConnectionFactory without ClientID
      2. Create a Connection out of the ConnectionFactory of step 1.
      3. Create a Session out of the Connection created in step 2.
      4. Close the Connection created in step 2.
      5. Create a Connection again out of ConnectionFactory of step 1.
      6. SetClientID to the Connection created in step 5.

      The issue is when Step 6 is executed, following Exception ocurrs.
      javax.jms.IllegalStateException: [C4054]: Cannot set client ID, invalid state.

      The following steps reproduces the issue:
      1. Create a new Connection Factory (If you are using Windows, you can run attached setup.bat instead.)
      asadmin create-jms-resource --restype javax.jms.ConnectionFactory jms/ConnectionFactory001

      2. Run the test program. (If you are using Windows, you can run attached run.bat instead.)
      appclient -client dest\clientiderror.jar

      3. When the test program is executed, the following Exception is displayed.
      javax.jms.IllegalStateException: [C4054]: Cannot set client ID, invalid state.

      However, when the Step 2, 3, 4 (Line 45 to 52 in JMSProducer.java) are commented out, the Exception does not occur.
      Follow the steps below to re-create the clientiderror.jar and test this.
      1. Edit the JMSProducer.java
      2. Open command prompt and type ant. clientiderror.jar is created under the folder called dest.
      3. appclient -client dest\clientiderror.jar
      4. The program completes without exception.

        Activity

        Hide
        Nigel Deakin added a comment -

        Reproduced in GlassFish 4.1 (thank you for providing very simple instructions on reproducing this)

        Jan 21, 2015 9:57:18 AM org.hibernate.validator.internal.util.Version <clinit>
        INFO: HV000001: Hibernate Validator 5.0.0.Final
        Jan 21, 2015 9:57:18 AM com.sun.messaging.jms.ra.ResourceAdapter start
        INFO: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter: Version:  5.1  (Build 9-b) Compile:  July 29 2014 1229
        Jan 21, 2015 9:57:18 AM com.sun.messaging.jms.ra.ResourceAdapter start
        INFO: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter starting: broker is REMOTE, connection mode is TCP
        Jan 21, 2015 9:57:18 AM com.sun.messaging.jms.ra.ResourceAdapter start
        INFO: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter Started:REMOTE
        [JMSProducer] round 1 *****START*****
        javax.jms.IllegalStateException: [C4054]: Cannot set client ID, invalid state.
                at com.sun.messaging.jmq.jmsclient.ConnectionImpl.checkSetClientID(ConnectionImpl.java:2304)
                at com.sun.messaging.jmq.jmsclient.ConnectionImpl.setClientID(ConnectionImpl.java:1978)
                at com.sun.messaging.jms.ra.ConnectionAdapter.setClientID(ConnectionAdapter.java:164)
                at com.fujitsu.interstage.javaee.jms.application.JMSProducer.run(JMSProducer.java:59)
                at com.fujitsu.interstage.javaee.jms.application.JMSProducer.main(JMSProducer.java:86)
        

        The error message means either (1) clientID has been administratively configured on the connection factory, or (2) the call to setClientID is not the first action on the connection. Clearly neither is the case here, so this looks like a bug.

        setClientID is allowed in the application client, but in the server (the web or EJB container) it throws an exception. This test case goes through that check just fine, so we can eliminate the possibility that the client mistakenly thinks that it's running in the server.

        I modified the test case slightly to confirm that the problem is caused by the code that creates a different connection beforehand:

        	public void run( int round )
        		throws NamingException, JMSException
        	{
        		InitialContext initialContext = new InitialContext( ) ;
        		ConnectionFactory connectionFactory = ( ConnectionFactory )initialContext.lookup( connectionFactoryName ) ;
        		Connection connection1 = connectionFactory.createConnection( ) ;
        		try {
        			// if you comment out the next line the test passes
        			Session session1 = connection1.createSession( false, Session.AUTO_ACKNOWLEDGE ) ;
        		} finally {
        			connection1.close( ) ;
        		}
        
        		for( int i = 0 ; i < round ; i++ ) {
        			System.out.println( "[JMSProducer] round " + ( i + 1 ) + " *****START*****" ) ;
        			Connection connection2 = connectionFactory.createConnection( ) ;
        			try {
        				// Exception here.
        				connection2.setClientID( clientID ) ;
        				Session session2 = connection2.createSession( false, Session.AUTO_ACKNOWLEDGE ) ;
        			} finally {
        				connection2.close( ) ;
        			}
        			System.out.println( "[JMSProducer] round " + ( i + 1 ) + " ***** END *****" ) ;
        		}
        	}
        

        The first connection is created, a session is created (so that calling setClientiD becomes invalid), and the connection is then closed so that it returns to the pool.

        When the second connection is created it looks as if this is reusing the first connection, but that connection hasn't been reset correctly. To confirm this, if you leave the second connection open when you create the second connection, the test passes.

        Show
        Nigel Deakin added a comment - Reproduced in GlassFish 4.1 (thank you for providing very simple instructions on reproducing this) Jan 21, 2015 9:57:18 AM org.hibernate.validator.internal.util.Version <clinit> INFO: HV000001: Hibernate Validator 5.0.0.Final Jan 21, 2015 9:57:18 AM com.sun.messaging.jms.ra.ResourceAdapter start INFO: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter: Version: 5.1 (Build 9-b) Compile: July 29 2014 1229 Jan 21, 2015 9:57:18 AM com.sun.messaging.jms.ra.ResourceAdapter start INFO: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter starting: broker is REMOTE, connection mode is TCP Jan 21, 2015 9:57:18 AM com.sun.messaging.jms.ra.ResourceAdapter start INFO: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter Started:REMOTE [JMSProducer] round 1 *****START***** javax.jms.IllegalStateException: [C4054]: Cannot set client ID, invalid state. at com.sun.messaging.jmq.jmsclient.ConnectionImpl.checkSetClientID(ConnectionImpl.java:2304) at com.sun.messaging.jmq.jmsclient.ConnectionImpl.setClientID(ConnectionImpl.java:1978) at com.sun.messaging.jms.ra.ConnectionAdapter.setClientID(ConnectionAdapter.java:164) at com.fujitsu.interstage.javaee.jms.application.JMSProducer.run(JMSProducer.java:59) at com.fujitsu.interstage.javaee.jms.application.JMSProducer.main(JMSProducer.java:86) The error message means either (1) clientID has been administratively configured on the connection factory, or (2) the call to setClientID is not the first action on the connection. Clearly neither is the case here, so this looks like a bug. setClientID is allowed in the application client, but in the server (the web or EJB container) it throws an exception. This test case goes through that check just fine, so we can eliminate the possibility that the client mistakenly thinks that it's running in the server. I modified the test case slightly to confirm that the problem is caused by the code that creates a different connection beforehand: public void run( int round ) throws NamingException, JMSException { InitialContext initialContext = new InitialContext( ) ; ConnectionFactory connectionFactory = ( ConnectionFactory )initialContext.lookup( connectionFactoryName ) ; Connection connection1 = connectionFactory.createConnection( ) ; try { // if you comment out the next line the test passes Session session1 = connection1.createSession( false, Session.AUTO_ACKNOWLEDGE ) ; } finally { connection1.close( ) ; } for( int i = 0 ; i < round ; i++ ) { System.out.println( "[JMSProducer] round " + ( i + 1 ) + " *****START*****" ) ; Connection connection2 = connectionFactory.createConnection( ) ; try { // Exception here. connection2.setClientID( clientID ) ; Session session2 = connection2.createSession( false, Session.AUTO_ACKNOWLEDGE ) ; } finally { connection2.close( ) ; } System.out.println( "[JMSProducer] round " + ( i + 1 ) + " ***** END *****" ) ; } } The first connection is created, a session is created (so that calling setClientiD becomes invalid), and the connection is then closed so that it returns to the pool. When the second connection is created it looks as if this is reusing the first connection, but that connection hasn't been reset correctly. To confirm this, if you leave the second connection open when you create the second connection, the test passes.

          People

          • Assignee:
            Nigel Deakin
            Reporter:
            tak09
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: