I have successfully deployed and executed IBM's WSMQ JCA Resource Installation and Verification Test application (wmq.jmsra.ivt.ear) on my JBoss 5.1 AS instance.
The IVT app establishes on my JBoss instance a Resource-->ConnectionFactory-->TxConnectionFactory named 'IVTCF' that is visible from my JBoss 5 Admin console. Running the IVT app's Servlet example confirms that JMS code referencing the 'IVTCF' correctly uses the configured JCA adapter to produce a Message on an IBM WS MQ hosted Queue. Running the IVT app's MDB example confirms that I can also consume Messages from the exact same IBM WS MQ Queue.
Unfortunately, I don't have the IVT.ear .java source code so I don't have an explicit example of how this is achieved with explicit JMS code. I tried to execute the following producer, using the same 'IVTCF' TxConnectionFactory, but the runtime value of the 'factory' assignment always NULL. And thus the last line of this code is always an NPE.
Properties props = new Properties(); props.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory"); props.setProperty(Context.PROVIDER_URL,"jnp://10.4.164.105:11099"); Context ctx = new InitialContext(props); javax.jms.ConnectionFactory factory = (javax.jms.ConnectionFactory)ctx.lookup("IVTCF"); // 'factory' always value = NULL at his time, why? System.out.println("'IVTCF' ConnectionFactory established! IVTCF=["+factory+"]"); //NPE Connection conn = factory.createConnection();
This code is using the exact same 'IVTCF' ConnectionFactory used by the IVT.ear servlet and MDB (both of which run successfully).
Any suggestions on what might be wrong with the above code segment?
Did you set this jndi property ?
Thanks for your reply gaohoward.
I modified the code as you indicated:
Properties props = new Properties(); props.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory"); props.setProperty(Context.PROVIDER_URL,"jnp://10.4.164.105:11099"); props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); Context ctx = new InitialContext(props); ConnectionFactory factory = (ConnectionFactory)ctx.lookup("IVTCF"); System.out.println("looked up 'IVTCF' javax.jms.ConnectionFactory established! 'factory'=["+ factory+ "]");
But I still only get 'factory' values == NULL after executing the lookup().
Via the JBoss admin console, I checked the value for 'IVTCF' in the JNDI global namespace and it shows a correct and expected value.
Global JNDI Namespace +- IVTCF (class: com.ibm.mq.connector.outbound.ConnectionFactoryImpl)
I guess in the worst case, I could code this Producer to directly invoke the WS MQ implementation of com.ibm.msg.client.jms.JmsConnectionFactory, but I was hoping I could just deploy the WS MQ JCA Resource adapter to my JBoss instance, config a Resource-->ConnectionFactory via the JBoss admin console, and then just do a 'lookup' on that ConnFactory to have all the plumbing (from JBoss to WS MQ) done for me transparently (via JCA).
Hoping to avoid coding directly to com.ibm.msg.client.jms.* API, do you have any other ideas/recommendations on how I might be able to get this to work via JBoss/JCA?
FYI, I have a reasonably manageable workaround (though not ideal).
When I code the exact same .lookup() logic from a JBoss-deployed servlet (instead of from an external app), everything works perfectly. This is obviously because the internal InitialContext construction needs no Context.XXX properties set.
InitialContext ic = new InitialContext(); // no Context.XXX props!! Now everything works via JCA! javax.jms.ConnectionFactory cf = (javax.jms.ConnectionFactory) ic.lookup("IVTCF"); // confirm that we found the CF log.info("'IVTCF' javax.jms.ConnectionFactory found: [" + cf + "]"); // get the queue Queue q = (Queue) ic.lookup("IVTQueue"); // confirm that we found the queue log.info("'IVTQueue' javax.jms.Queue found: [" + q +"]");
Now the 'cf' value is NON-NULL and I can indeed publish to an IBM WS MQ destination from a JBoss component just by looking up a Resource-->ConnectionFactory ... and then relying on the JCA resource adapter to transparently manage all the messaging plumbing. :-)
I still can't do this from an external stand-alone application that parameterizes its JBoss InitialContext() construction with Properties, but I'll live with that for now (or maybe post the issue to a JNDI focused forum).
I am not sure, but it looks like the connection factory is bound in the java namespace, instead of the global JNDI.
You can view the jndi tree from the jmx-console.
Thanks for the reply.
The IVTCF-ds.xml includes the explicit config
Also, the JMX-Console JNDIView 'list' operation confirms that "IVTCF" is bound in the JNDI Global Namespace.
It remains puzzling that when I parameterize the InitialContext with Properties (from an extermal stand-alone application) that the
ConnectionFactory cf = ic.lookup("IVTCF");invoke always returns NULL.
another thing to check is the connection-factory-service.xml, see what the JNDIBindings for it. sth like:
<attribute name="JNDIBindings"> <bindings> <binding>/IVTCF</binding> </bindings> </attribute>