-
1. Re: JMS MessageListener in a web application
tes May 13, 2009 9:18 AM (in response to nbhatia.bhatian.comcast.net)Seam has POJO-based JMS support, you will not have any problem to use JMS in your war application
-
2. Re: JMS MessageListener in a web application
kapitanpetko May 13, 2009 10:27 AM (in response to nbhatia.bhatian.comcast.net)You will need to get a Session, create a QueueReceiver and call setMessageListener to register your bean.
Btw, you probably want a listener with application scope for this to work.
Something like:@In private QueueSession queueSession; @In private MyListener myListener; ... Queue queue = lookupQueue(); // get queue from JNDI QueueReceiver receiver = queueSession.createReceiver(queue); receiver.setMessageListener(myListener)
-
3. Re: JMS MessageListener in a web application
nbhatia.bhatian.comcast.net May 13, 2009 5:15 PM (in response to nbhatia.bhatian.comcast.net)Thanks Orestes and Nikolay. I will give it a try!
-
4. Re: JMS MessageListener in a web application
asegarra.angel.segarra.gmail.com May 29, 2009 4:45 PM (in response to nbhatia.bhatian.comcast.net)So did you managed to get this going? if so could you give some details as to how you did it? There is nothing in the ref docs or the Seam in Action book on how to do this which is a major oversight.
-
5. Re: JMS MessageListener in a web application
nbhatia.bhatian.comcast.net Jun 3, 2009 8:28 AM (in response to nbhatia.bhatian.comcast.net)I have not been able to solve this yet. I did create a listener in Application scope (as per Nikolay's suggestion). However the bean is never created because no one really calls it. Is there any way to force instantiation of a bean during application startup? I have looked through the manual as well as the Seam examples - this topic is covered nowhere!
Here's my code:
@Name("myListener") @Scope(ScopeType.APPLICATION) public class MyListener implements MessageListener { @In(create=true) private QueueSession queueSession; private QueueReceiver queueReceiver; @Create public void init() { try { InitialContext ctx = new InitialContext(); Queue myQueue = (Queue)ctx.lookup("queue/myqueue"); QueueReceiver = queueSession.createReceiver(myQueue); QueueReceiver.setMessageListener(this); } catch (NamingException e) { throw new RuntimeException("MyListener initialization failed", e); } catch (JMSException e) { throw new RuntimeException("MyListener initialization failed", e); } } @Override public void onMessage(Message message) { ... } }
-
6. Re: JMS MessageListener in a web application
kapitanpetko Jun 3, 2009 8:36 AM (in response to nbhatia.bhatian.comcast.net)You can use @AutoCreate to create it automatically. Or you could observe the postInitialization event
and do your setup in the observer method:@Name("startup) public class Startup { @Observer("org.jboss.seam.postInitialization") public void startup() { // wire MessageListeners, etc } }
-
7. Re: JMS MessageListener in a web application
nbhatia.bhatian.comcast.net Jun 3, 2009 3:26 PM (in response to nbhatia.bhatian.comcast.net)Thanks Nikolay. I have tried your suggestions, but things aren't working yet.
It seems that @AutoCreate does not automatically create a bean - it creates the bean only if it needs to be injected in something else (which was not the case in my earlier code).
Well, I took out the initialization code from my listener and put it in a separate startup bean as you suggested. I also added the postInitialization observer. Now the postInitialization method is indeed being called by Seam, but this call does not seem to initialize the bean itself. Although I have @AutoCreate on my listener it is not injected into my startup bean. I must be missing something!!!
Here's my latest code:
@Name("myListenerInitializer") @Scope(ScopeType.APPLICATION) @AutoCreate public class MyListenerInitializer { @In(create=true) private QueueSession queueSession; @In(create=true) MyListener myListener; private QueueReceiver queueReceiver; @Observer("org.jboss.seam.postInitialization") public void init() { try { InitialContext ctx = new InitialContext(); Queue queue = (Queue)ctx.lookup("queue/myqueue"); queueReceiver = queueSession.createReceiver(queue); queueReceiver.setMessageListener(myListener); } catch (NamingException e) { throw new RuntimeException("myListener initialization failed", e); } catch (JMSException e) { throw new RuntimeException("myListener initialization failed", e); } } } @Name("myListener") @Scope(ScopeType.APPLICATION) @AutoCreate public class MyListener implements MessageListener { @Override public void onMessage(Message message) { ... } }
Here's the exception I am getting:
ERROR Exception sending context initialized event to listener instance of class org.jboss.seam.servlet.SeamListener org.jboss.seam.RequiredException: @In attribute requires non-null value: myListenerInitializer.myListener
-
8. Re: JMS MessageListener in a web application
nbhatia.bhatian.comcast.net Jun 3, 2009 4:23 PM (in response to nbhatia.bhatian.comcast.net)Never mind :-). myListener IS being injected in MyListenerInitializer. I had made so many changes that the application was not built correctly somewhere along the line. I did a fresh build and this issue went away.
Still not done yet. It seems that as soon as the initializer sets the message listener, messages are being picked up from the queue, but after initialization is done and application is in steady state, the listener stops picking up any new messages. Bit puzzled by this. Any ideas?
-
9. Re: JMS MessageListener in a web application
nbhatia.bhatian.comcast.net Jun 3, 2009 6:15 PM (in response to nbhatia.bhatian.comcast.net)Some more insight into the problem. It appears that the session is already closed when the listener is trying to use it. Here's the exception:
[MessageListenerThread - myqueue] [org.jboss.mq.SpyMessageConsumer] Message consumer closing due to error in listening thread. javax.jms.IllegalStateException: The session is closed at org.jboss.mq.SpySession.checkClosed(SpySession.java:1149) at org.jboss.mq.SpySession.doAcknowledge(SpySession.java:175) at org.jboss.mq.SpyMessage.doAcknowledge(SpyMessage.java:353) at org.jboss.mq.SpyMessageConsumer.run(SpyMessageConsumer.java:719) at java.lang.Thread.run(Thread.java:619)
Any ideas?
(P.S. I request the Seam developers to provide an example of this use case - listening to JMS messages using POJO beans)
-
10. Re: JMS MessageListener in a web application
nbhatia.bhatian.comcast.net Jun 3, 2009 10:19 PM (in response to nbhatia.bhatian.comcast.net)This is a pretty hard problem. Turns out that QueueSession is managed by seam and has event scope - it is being closed right after my init function returns. To solve this issue, I created my own QueueSession - this gets me past the problem, but now another problem shows up.
Since MessageListner is invoked on its own thread, seam knows nothing about it and hence no contexts are created. Hence I cannot call any Seam components from this thread. Any attempt to get a component using Component.getInstance() throws this exception:
java.lang.IllegalStateException: No application context active at org.jboss.seam.Component.forName(Component.java:1902) at org.jboss.seam.Component.getInstance(Component.java:1962) at org.jboss.seam.Component.getInstance(Component.java:1940) at org.jboss.seam.Component.getInstance(Component.java:1934) at org.jboss.seam.Component.getInstance(Component.java:1929) at MyListener.getMyMessageProcessor(MyListener.java:118) at MyListener.onMessage(MyListener.java:94) at org.jboss.mq.SpyMessageConsumer.run(SpyMessageConsumer.java:697) at java.lang.Thread.run(Thread.java:619)
Is there any way to initialize the Seam container when my message listener is called?
I suppose that other people have also run into this problem (see here), but no solution has been proposed.
Please help.
Thanks.
Naresh
-
11. Re: JMS MessageListener in a web application
lvdberg Jun 4, 2009 12:05 AM (in response to nbhatia.bhatian.comcast.net)I have a similar problem. We have created an application which presents an overview of (traffic) incidents, which is viewed by different users. Whenever somebody updatss an attribute or creeates a new incident a Notification is created is and send to a JMS topic.
Incidents are created through the user-interface or come in through a RestService. This service also creates a notification.
We want to raise an event after receiving such a notification. However we don't have access to the Seam context within the OnMessage method.
Trying to get an instance with the getInstance doesn' work either. Can anybody help on this issue on how to get access the Seam context within a MesageListener. We tried it with MDB and POJO, both no-go.
Thanks
Leo
P.S. I can share the JMS Listener code if you want.
-
12. Re: JMS MessageListener in a web application
kapitanpetko Jun 4, 2009 5:00 AM (in response to nbhatia.bhatian.comcast.net)
Naresh Bhatia wrote on Jun 03, 2009 22:19:
This is a pretty hard problem. Turns out that QueueSession is managed by seam and has event scope - it is being closed right after my init function returns. To solve this issue, I created my own QueueSession - this gets me past the problem, but now another problem shows up.Looking at my code, that's what I ended up doing. Should have mentioned it earlier though.
Since MessageListner is invoked on its own thread, seam knows nothing about it and hence no contexts are created. Hence I cannot call any Seam components from this thread. Any attempt to get a component using Component.getInstance() throws this exception:My onMessage is pretty simple, so didn't run in this problem. You could try starting up the application context using Lifecycle.beginCall(), but I haven't actually tried this.
-
13. Re: JMS MessageListener in a web application
nbhatia.bhatian.comcast.net Jun 4, 2009 8:39 AM (in response to nbhatia.bhatian.comcast.net)Nikolay, thanks for the clarification. Unfortunately, my message listener needs to access the database and hence I totally need the beans.
I was earlier under the impression that this would work if I switched to MDBs (and hence to an EAR), but Leo's post suggested to the contrary. So I converted my app to an EAR and switched to MDBs but I am still getting a NullPointerException, meaning no injection is taking place. Again, I could be missing something, but at this point I would rather wait for a word from Seam developers than to put more time into this issue.
-
14. Re: JMS MessageListener in a web application
kapitanpetko Jun 4, 2009 9:03 AM (in response to nbhatia.bhatian.comcast.net)If you have an MDB, things should be easy. You can inject the persistence context, or SLSB's (J2EE injection, not Seam injection).
You could look up stuff via JNDI as well, so you don't need to call Seam API's at all.Say:
@MessageDriven public class MyListener implements MessageListener { @PersistenceContext private EntityManager em; @EJB private MyProcessor procesor; public void onMessage(Message message) { // do your DB stuff } }