Does JBoss ESB violate the JEE 5 Specification?
bech Sep 21, 2010 4:32 AMHi JBoss people
For the project I’m currently working on, I’m trying to get the JBoss ESB to use IBM WebSphere MQ queues as both incoming data providers and outgoing data consumers.
I’m using IBM’s “WebSphere MQ resource adapter” and JCA administered objects to bind remote WMQ queues to my local JNDI.
The guides I have followed, to configure the resource adaptor and to define my queues is found here:
http://www.ibm.com/developerworks/websphere/library/techarticles/0710_ritchie/0710_ritchie.html
http://community.jboss.org/wiki/UsingWebSphereMQSeriesWithJBossASPart4
It seems to work beautifully; I have developed a proof-of-concept EJB3 Webservice that looks up WMQ queues and uses the WMQ ConnectionFactory implementation to put messages on the queue.
The following is the Webservice I have successfully used to put messages on a WebSphere queue from a JBoss AS, hence I conclude that my queue and resource adapter configuration is correct.
package com.test.ws; import java.util.Properties; import javax.ejb.Stateless; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.QueueSession; import javax.jms.Session; import javax.jms.TextMessage; import javax.jws.WebMethod; import javax.jws.WebService; import javax.naming.Context; import javax.naming.InitialContext; import org.jboss.wsf.spi.annotation.WebContext; @Stateless @WebService(serviceName = "TestWMQService", targetNamespace = "http://TestWMQService") @WebContext(contextRoot = "/ws", urlPattern = "/TestWMQService") public class TestWMQService { private static final Logger logger = Logger.getLogger(TestWMQService.class.getName()); @WebMethod public void testing() throws Exception { try { Properties properties = new Properties(); properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); properties.put(Context.PROVIDER_URL, "jnp://127.0.0.1:9199"); InitialContext iniCtx = new InitialContext(); ConnectionFactory qcf = (ConnectionFactory) iniCtx.lookup("java:WMQConnectionFactory"); Connection conn = qcf.createConnection(); Queue queue = (Queue) iniCtx.lookup("queue/WMQTest"); Session session = conn.createSession(false, QueueSession.AUTO_ACKNOWLEDGE); conn.start(); MessageProducer send = session.createProducer(queue); TextMessage tm = session.createTextMessage(); tm.setText("WMQ Testing"); send.send(tm); send.close(); session.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); throw e; } } }
My problem occurs, when I’m trying to use the JBoss ESB JMSRouter class to write to a queue:
When the ESB project is initialized i get the following error:
Caused by: org.jboss.soa.esb.ConfigurationException: Failed to configure JMS Destination for routing. at com.testproject.esbpoc.JMSRouter.createQueueSetup(JMSRouter.java:509) at com.testproject.esbpoc.JMSRouter.<init>(JMSRouter.java:291) ... 93 more Caused by: com.ibm.msg.client.jms.DetailedIllegalStateException: MQJCA1031: The method can only be called in the application client container. The application was not running in the application client container when this method was called. Ensure that the application runs in the application client container, or modify the application to avoid this method call. at com.ibm.mq.connector.services.JCAExceptionBuilder.buildException(JCAExceptionBuilder.java:149) at com.ibm.mq.connector.services.JCAExceptionBuilder.buildException(JCAExceptionBuilder.java:86) at com.ibm.mq.connector.outbound.ConnectionWrapper.setExceptionListener(ConnectionWrapper.java:183) at org.jboss.internal.soa.esb.rosetta.pooling.JmsConnectionPool$JmsSessionPool.initConnection(JmsConnectionPool.java:778) at org.jboss.internal.soa.esb.rosetta.pooling.JmsConnectionPool$JmsSessionPool.getSession(JmsConnectionPool.java:704) at org.jboss.internal.soa.esb.rosetta.pooling.JmsConnectionPool.internalGetSession(JmsConnectionPool.java:260) at org.jboss.internal.soa.esb.rosetta.pooling.JmsConnectionPool.getSession(JmsConnectionPool.java:198) at org.jboss.internal.soa.esb.rosetta.pooling.JmsConnectionPool.getSession(JmsConnectionPool.java:353) at com.testproject.esbpoc.JMSRouter.createQueueSetup(JMSRouter.java:488) ... 94 more
The “WebSphere MQ resource adapter” fails; telling me that an illegal method has been called.
After a little investigation I think I have found out why:
For sending messages to the queues I’m using the action class:
org.jboss.soa.esb.actions.routing.JMSRouter
The class internally use the class:
org.jboss.internal.soa.esb.rosetta.pooling.JmsConnectionPool.
On line 778, the JmsConnectionPool class is calling the method setExceptionListener() on the ConnectionFactory.
On page 133 - 134 of the Java™ Platform, Enterprise Edition (Java EE) Specification, v5 (http://jcp.org/aboutJava/communityprocess/final/jsr244/index.html) it is clearly stated that call to this method (and other methods), from web or EJB containers is prohibited.
The “WebSphere MQ resource adapter” has implemented this restriction and throws an Exception if the method is call on their ConnectionFactory implementation.
So the questions is:
Isn’t JBoss ESB violating the JEE5 specification, and how do I create a workaround for the problem?
Looking forward to hear your opinions.
Kind regards
Peer Bech Hansen
Logica Denmark
Environment used:
Microsoft Windows XP SP3
JBoss AS 5.1.0 GA
JBoss Messaging 1.4.3 GA
JBoss ESB 4.9