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:
Next, we changed the defintion in the application context to use these 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>
This configuration results in the following error from WAS (on startup):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>
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.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:".]
We resolving this by reverting to the 'old way' of defining the Message listener where can pass the queue object directly:
In this case, the queue gets resolved when processing the applicationContext, which is done within a 'valid' thread. All goes well then!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>
A weird side effect is the following error:
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...?Code:J2CA0045E: Connection not available while invoking method createOrWaitForConnection for resource jms/queueConnectionFactory.
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




Reply With Quote
