Message Driven Bean onMessage() unable to detect JMS Message
ezanih May 22, 2009 5:10 AMHi there
I created a RichFaces/Facelets + Seam + JMSQueue + JPAEntity JEE5 project in my Eclipse 3.4 using JBoss AS 4.2.2.GA and JBossESB 4.4.
Workflow for the project is a simple CRUD operation as follows :- I have a Bidder JPA entity with properties BidderId (long) and BidderName(String). My RF/Facelets UI opens up a blank Create Bidder form and accepts the user input when the Save button is pressed. The bidder details which the user just entered is then sent in a queue across JBossESB ("queue/quickstart_jms_router_Request_gw") using a QueueSender initiated by a ConnectionFactory of type ObjectMessage ("I made the Bidder JPA entity serializable) from my SendJMSMessage.java class.
A message-driven bean (TestMDB.java) listens to the "queue/quickstart_jms_router_Request_gw" queue and when the bidder entity gets on the queue, is supposed to activate the MDB's onMessage(msg) method. Within this method, I have just put in some System.out.println because I want to see the MDB receiving the bidder message sent. My ultimate aim is to persist the bidder to the db (to be done later).
My problem : TestMDB.java doesn't appear to be receiving/detecting the bidder message sent through the allocated queue as none of my System.out.println in its onMessage(msg) is being called. What's wrong?
Here's my SendJMSMessage.java which is correctly getting the bidder entity from the RichFaces/Facelets UI:
package org.domain.testseam.jms; import java.util.Properties; import javax.jms.JMSException; import javax.jms.ObjectMessage; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.domain.testseam.entity.Bidder; import org.jboss.seam.annotations.Name; @Name("messageSender") public class SendJMSMessage { public final String SENDING_QUEUE = "queue/quickstart_helloworld_Request_gw"; QueueConnection conn; QueueSession session; Queue que; public void setupConnection() throws JMSException, NamingException { Properties properties1 = new Properties(); properties1.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties1.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); properties1.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099"); InitialContext iniCtx = new InitialContext(properties1); Object tmp = iniCtx.lookup("ConnectionFactory"); QueueConnectionFactory qcf = (QueueConnectionFactory) tmp; conn = qcf.createQueueConnection(); que = (Queue) iniCtx.lookup(SENDING_QUEUE); session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); conn.start(); System.out.println("[SendJMSMessage.java]: Connection Started"); } public void stop() throws JMSException { conn.stop(); session.close(); conn.close(); } public void sendAMessage(Bidder msg) throws JMSException { QueueSender send = session.createSender(que); ObjectMessage tm = session.createObjectMessage(msg); System.out.println("[SendJMSMessage.java] : sendAMessage() - Bidder.getBidderId(): " + msg.getId()); System.out.println("[SendJMSMessage.java] : sendAMessage() - Bidder.getBidderName(): " + msg.getName()); System.out.println("[SendJMSMessage.java] : sendAMessage() - sending Bidder through the JMS gateway..."); send.send(tm); send.close(); } public boolean sendMsg(Bidder bidder) { try { SendJMSMessage sm = new SendJMSMessage(); sm.setupConnection(); //sm.sendAMessage(args[0]); sm.sendAMessage(bidder); System.out.println("[SendJMSMessage.java] : MESSAGE SENT !"); sm.stop(); return true; } catch (Exception e) { System.out.println(e.getMessage()); return false; } } }
Here's my MDB whose onMessage(msg) method doesn't seem to be called:
package org.domain.testseam.mdb; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; import javax.jms.ObjectMessage; import javax.ejb.EJBException; import javax.ejb.MessageDriven; import javax.ejb.MessageDrivenBean; import javax.ejb.MessageDrivenContext; import org.jboss.seam.annotations.Name; import org.domain.testseam.entity.Bidder; @MessageDriven public class TestMDB implements MessageDrivenBean, MessageListener { private transient MessageDrivenContext mdbContext; //public empty constructor public TestMDB() { } // required for implements MessageListener public void onMessage(Message msg) { try { System.out.println("Hi there!"); // check for message type: text or object message if (msg instanceof TextMessage) { TextMessage testMsg = (TextMessage) msg; System.out.println("TestMDB.java: TextMessage received in onMessage() method : " + testMsg.getText()); } if (msg instanceof ObjectMessage) { ObjectMessage objectMessage = (ObjectMessage) msg; Object obj = (Object) objectMessage.getObject(); System.out.print("TestMDB.java - in onMessage() method : ObjectMessage received (toString() - ) : " + obj.toString()); System.out.print("[Now I, mdbBean, am going to convert intoa JPA entity and persist it with an EntityManager]"); } } catch (JMSException e) { e.printStackTrace(); } } public void ejbCreate () { System.out.println("TestMDB.java: ejbCreate() - Message driven bean created."); } public void ejbDestroy () { System.out.println("TestMDB.java: ejbDestroy() - Message driven bean destroyed."); } // required for implements MessageDrivenBean public void ejbRemove() throws EJBException { } // required for implements MessageDrivenBean public void setMessageDrivenContext(MessageDrivenContext ctx) throws EJBException { mdbContext = ctx; } }
My jboss-ejb.xml :
<?xml version = "1.0" encoding = "UTF-8"?> <jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd" parameterReloadSecs="5"> <providers> <jms-provider name="JBossMQ" connection-factory="ConnectionFactory"> <jms-bus busid="quickstartGwChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_jms_router_Request_gw" /> </jms-bus> <jms-bus busid="quickstartEsbChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_jms_router_Request_esb" /> </jms-bus> </jms-provider> </providers> <services> <service category="FirstServiceESB" name="SimpleListener" description="Hello World"> <listeners> <jms-listener name="JMS-Gateway" busidref="quickstartGwChannel" is-gateway="true" /> <jms-listener name="helloWorld" busidref="quickstartEsbChannel" /> </listeners> <actions mep="OneWay"> <action name="action1" class="org.jboss.soa.esb.samples.quickstart.helloworld.MyJMSListenerAction" process="displayMessage" /> <action name="action2" class="org.jboss.soa.esb.actions.SystemPrintln"> <property name="printfull" value="true"/> </action> <!-- The next action is for Continuous Integration testing --> <action name="testStore" class="org.jboss.soa.esb.actions.TestMessageStore"/> </actions> </service> </services> </jbossesb>
and my ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?> <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0"> <display-name>testSeam-ejb JAR</display-name> <enterprise-beans> <message-driven> <display-name>TestMDB</display-name> <ejb-name>TestMDB</ejb-name> <ejb-class>TestMDB</ejb-class> <messaging-type>javax.jms.MessageListener</messaging-type> <transaction-type>Container</transaction-type> <message-destination-type>javax.jms.Queue</message-destination-type> </message-driven> </enterprise-beans> <interceptors> <interceptor> <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class> </interceptor> </interceptors> </ejb-jar>
My console output is :
16:47:11,312 INFO [STDOUT] [SendJMSMessage.java]: Connection Started 16:47:11,343 INFO [STDOUT] [SendJMSMessage.java] : sendAMessage() - Bidder.getBidderId(): 1 16:47:11,343 INFO [STDOUT] [SendJMSMessage.java] : sendAMessage() - Bidder.getBidderName(): Allan 16:47:11,343 INFO [STDOUT] [SendJMSMessage.java] : sendAMessage() - sending Bidder through the JMS gateway... 16:47:11,359 INFO [STDOUT] [SendJMSMessage.java] : MESSAGE SENT ! 16:47:11,375 ERROR [JmsGatewayListener] Problems invoking method <process> java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.jboss.soa.esb.listeners.gateway.JmsGatewayListener.doRun(JmsGatewayListener.java:156) at org.jboss.soa.esb.listeners.lifecycle.AbstractThreadedManagedLifecycle.run(AbstractThreadedManagedLifecycle.java:115) at java.lang.Thread.run(Thread.java:595) Caused by: javax.jms.MessageFormatException: ClassNotFoundException: No ClassLoaders found for: org.domain.testseam.entity.Bidder at org.jboss.mq.SpyObjectMessage.getObject(SpyObjectMessage.java:154) at org.jboss.soa.esb.listeners.gateway.PackageJmsMessageContents.setESBMessageBody(PackageJmsMessageContents.java:160) at org.jboss.soa.esb.listeners.gateway.PackageJmsMessageContents.process(PackageJmsMessageContents.java:84) ... 7 more
What seems to be going wrong?