Trying out XA, part 2: transaction manager and JNDIView
Posted by danielmeyer on July 7, 2008
Last Thursday I tried out the configuration from last time, and… fireworks! (A big stack trace — appropriate for the day, no?)
So, I commented out the three bean IDs in the Spring bean file and tried again. No big stack trace in JBoss (mind you, I’m not actually trying to do anything with the beans yet, just deploy the .war file and not see a big failure stack trace on the JBoss console). That deployed ok. And I’m able to uncomment the transactionManager bean — when I do, I get this new output on the JBoss console:
7d56b: defining beans [transactionManager]; root of factory hierarchy 08:09:27,205 INFO [JtaTransactionManager] Using JTA UserTransaction: org.jboss.tm.usertx.client.ServerVMClientUserTransaction@1906773 08:09:27,221 INFO [JtaTransactionManager] Using JTA TransactionManager: com.arjuna.ats.jbossatx.jta.TransactionManagerDelegate@1d008ff
So that looks promising. The DefaultMessageListenerContainer depends on both the transactionManager and the JNDI-looked-up queueConnectionFactory, and when I uncomment the queueConnectionFactory-JNDI-looked-up bean I get this big stack trace on the JBoss console.
The first error is:
08:26:12,253 ERROR [ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘queueConnectionFactory’: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: QueueConnectionFactory not bound
This NameNotFoundException on QueueConnectionFactory keeps coming up in the “Caused by” lines farther down in the stack trace.
Spring is not finding something JNDI-registered as QueueConnectionFactory. This seemed intractable Thursday, but today I’m wondering:
Did I mix up the jndi-name with the ID?
Perhaps I got the jndi-name and the id mixed up in the Spring bean file. In the bean file I have:
<jee:jndi-lookup id="queueConnectionFactory" jndi-name="activemq/QueueConnectionFactory"/>
and in the deployed activemq-jms-ds.xml there is
Those seem to match.
Let’s see if I can examine JBoss’s JNDI directory somehow to see how it has the queue registered.
Searching for JBoss’s JNDI Directory
I pointed my browser to http://localhost:8080 , where my local JBoss instance is listening. After poking around in the Administration Console and looking a bit at Sun’s JNDI Tutorial, I thought I’d look in the JMX Console to see if I could find how activemq/QueueConnectionFactory was listed… or any other JNDI thing, for that matter.
Under the jboss heading I see a JNDIView link that looks promising:
Following that link, I get to a page about the JNDIView service that has this:
I press Invoke and find myself on an Operation Results page that has interesting JNDI stuff listed out.
Examining JBoss’s JNDI directory
On this page, I search for queue and find this under a heading titled java: Namespace:
+- activemq (class: org.jnp.interfaces.NamingContext) | +- QueueConnectionFactory (class: org.apache.activemq.ra.ActiveMQConnectionFactory) | +- TopicConnectionFactory (class: org.apache.activemq.ra.ActiveMQConnectionFactory)
Ok, continuing to search for queue, I find this under the heading Global JNDI Namespace:
+- queue (class: org.jnp.interfaces.NamingContext) | +- A (class: org.jboss.mq.SpyQueue) | +- testQueue (class: org.jboss.mq.SpyQueue) | +- ex (class: org.jboss.mq.SpyQueue) | +- DLQ (class: org.jboss.mq.SpyQueue) | +- D (class: org.jboss.mq.SpyQueue) | +- C (class: org.jboss.mq.SpyQueue) | +- B (class: org.jboss.mq.SpyQueue)
And, just as interesting, farther down under the same heading:
+- QueueConnectionFactory (class: org.jboss.naming.LinkRefPair)
To my untrained eye, it looks like in the global JNDI namespace, we have queue/A, queue/B, etc… but then just plain QueueConnectionFactory without the activemq/ before it. I even remember seeing entries like queue/A, queue/B, etc. in the JBoss console when it started up:
08:09:07,645 INFO [A] Bound to JNDI name: queue/A 08:09:07,645 INFO [B] Bound to JNDI name: queue/B 08:09:07,645 INFO [C] Bound to JNDI name: queue/C 08:09:07,661 INFO [D] Bound to JNDI name: queue/D 08:09:07,661 INFO [ex] Bound to JNDI name: queue/ex 08:09:07,692 INFO [testTopic] Bound to JNDI name: topic/testTopic 08:09:07,692 INFO [securedTopic] Bound to JNDI name: topic/securedTopic 08:09:07,707 INFO [testDurableTopic] Bound to JNDI name: topic/testDurableTopic 08:09:07,707 INFO [testQueue] Bound to JNDI name: queue/testQueue 08:09:07,754 INFO [UILServerILService] JBossMQ UIL service available at : /127.0.0.1:8093 08:09:07,785 INFO [DLQ] Bound to JNDI name: queue/DLQ
I bet if one of our Spring beans referred to a queue/A jndi-name, it would be found.
So if the global JNDI namespace holds the JNDI names to which a Spring bean file might refer, perhaps in my Spring bean file I should put plain QueueConnectionFactory as the jndi-name, instead of activemq/QueueConnectionFactory.
Reluctance to Use the Short JNDI-name
Let’s sit on that thought for a minute, because I’d rather use the more descriptive (?) activemq/QueueConnectionFactory as the jndi-name in the Spring bean file if possible. Looking at the java: Namespace, it would appear that the QueueConnectionFactory would be specified as activemq/QueueConnectionFactory there, if the tree is built the same as the queue/A under the Global JNDI Namespace heading. To access the java: JNDI namespace, do we just prepend java: to the JNDI-name?
Accessing the java: JNDI Namespace
That would make our bean definition look like this:
<jee:jndi-lookup id=”queueConnectionFactory” jndi-name=”java:activemq/QueueConnectionFactory”/>
I rebuilt and redeployed, and I don’t get a stack trace this time. No positive log messages about Spring finding the queueConnectionFactory, but at least no stack trace. I guess I was hoping for a little more positive feedback before I went on…
The Droids We Are Looking For
But while searching through the JBoss console messages for the queue/A, queue/B… messages, I found this!
08:09:06,367 INFO [ConnectionFactoryBindingService] Bound ConnectionManager ‘jboss.jca:service=ConnectionFactoryBinding,name=activemq/QueueConnection
Factory’ to JNDI name ‘java:activemq/QueueConnectionFactory’
Aha! It looks like that is the right name syntax.
Now that we have defined the JtaTransactionManager and QueueConnectionFactory beans, we can go on to define the DefaultMessageListenerContainer bean, which depends on both of them. But we’ll save that for Part 3…