Announcement Announcement Module
Collapse
No announcement yet.
jms:listener-container, resource references and IBM Websphere 6.1 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • jms:listener-container, resource references and IBM Websphere 6.1

    I'm creating this thread because I could not find the answer to the question online. Now that I found out the solution, I want to share it in case others encounter it in the future.

    Situation: we have an application deployed in Websphere 6.1 which uses the Spring JMS DefaultMessageListenerContainer to reply to any messages sent to a queue. The localhost development WAS queue implementation is done as described on this page.

    Currently, this queue is included in an application configuration properties file and we want to move these queue name definitions to the web.xml using Resource References, like so:
    Code:
    <resource-ref>
      <res-ref-name>jms/queueConnectionFactory</res-ref-name>
      <res-type>javax.jms.QueueConnectionFactory</res-type>
      <res-auth>Container</res-auth>
      <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
    
    <resource-ref>
      <res-ref-name>jms/inQueue</res-ref-name>
      <res-type>javax.jms.Queue</res-type>
      <res-auth>Container</res-auth>
      <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
    Next, we changed the defintion in the application context to use these resource references, like so:
    Code:
    <jee:jndi-lookup id="connectionFactory" jndi-name="jms/queueConnectionFactory" expected-type="javax.jms.QueueConnectionFactory" resource-ref="true" />
    
    <bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
      <!--
        This property control if java:comp/env/ should be added, which is the case when doing a lookup in the J2EE container.
      -->
      <property name="resourceRef" value="true" />
    </bean>
    
    <!--
      Message listener container definition, for more information about Spring JMS namespaces please refer to the Spring
      documentation. The messageConvertorFactory determines the right convertor (with or without SOAP).
    -->
    <jms:listener-container destination-resolver="jmsDestinationResolver" connection-factory="connectionFactory" cache="none" >
      <jms:listener ref="dummyMessageListener" destination="jms/inQueue"/>
    </jms:listener-container>
    This configuration results in the following error from WAS (on startup):
    Code:
    javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the serverruntime is not able to associate the operation's thread with any J2EE application component.  This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request.  Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application.  Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names. [Root exception is javax.naming.NameNotFoundException: Name "comp/env/inQueue" not found in context "java:".]
    Yep, it's a long-ass line and I didn't spot the actual error at first (a lot of stacktracing is done afterwards). Once read carefully, the error is actually pretty understandable: the Spring Message Listener spawns it's own thread and does the resolving of the queue (through the jmsDestinationResolver) in it's own thread. WAS cannot determine which J2EE application component is associated with this thread and therefor cannot return the queue object.

    We resolving this by reverting to the 'old way' of defining the Message listener where can pass the queue object directly:
    Code:
    <jee:jndi-lookup id="inQueue" jndi-name="jms/inQueue" expected-type="javax.jms.Queue" resource-ref="true" />
    
    <!-- The container responsible for consuming the JMS message and passing it through -->
    <bean id="container" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
      <property name="connectionFactory" ref="connectionFactory" />
      <property name="messageListener" ref="dummyMessageListener" />
      <property name="destination" ref="inQueue" />
    </bean>
    In this case, the queue gets resolved when processing the applicationContext, which is done within a 'valid' thread. All goes well then!

    A weird side effect is the following error:
    Code:
    J2CA0045E: Connection not available while invoking method createOrWaitForConnection for resource jms/queueConnectionFactory.
    This is because the Message Listener container's default settings caches a connection and when it tries to recover (default every 5 seconds) it starts a new thread but the old connection does not get released (ever). Setting caching to none resolves this side effect (but we reverted this afterwards ofcourse). Maybe this is a bit of a Spring bug even...?

    Open questions are:
    • Is it possible to pass the queue object when using the 'new' namespace configuration (jms:listener-container.. etc). Documentation seems to indicate it cannot and that the jmsDestinationResolver should always be used.
    • Could using a task-executor solve this problem so we can use the 'new' namespace configuration?

    The workaround is acceptable for us, but if anyone knowns answers to this question we can make it a little more neat, plus it might help other people in the future

    Thanks for reading this big pile of text, hope it helps

    Some extra URLs:
    The complete configuration can be found here:
    http://wiki.ivonet.nl/display/howto/...+WebSphere+6.1
    This thread is related to the problem:
    http://forum.springsource.org/showthread.php?p=233179

  • #2
    Hi,
    I spent two days now with the same problem... Sorry I haven't got any answers to your questions though, so I am also a bit curious if anyone can answer this?

    I took a look at the 3.0 code, but there were nothing in the schema indicating any change.

    The "old" solution works fine but seems a bit dull when there's a leaner way with less code with the jms namespace...

    Comment


    • #3
      I'm not sure I understand what you're getting at... in the startpost it is explained what the difference is between the two variants and why the 'new way' fails..

      Can you elaborate on what you mean?

      Comment


      • #4
        I just wanted answers to the same open questions you stated at the end of your post as well...

        Comment


        • #5
          Turns out a co-worker of mine encoutered the same problem, but also managed to get it working using the workmanager thingy:

          http://blog.smart-java.nl/blog/index...s-in-websphere

          http://www.ibm.com/developerworks/we...09_alcott.html

          Comment


          • #6
            try to use
            <jms:listener-container destination-resolver="destinationResolver"

            <bean id="destinationResolver" class="org.springframework.jms.support.destination .JndiDestinationResolver"/>

            Comment

            Working...
            X