1 2 Previous Next 28 Replies Latest reply on Jan 18, 2010 7:41 AM by sathish avunoori

    JMS and session scoped Seam component

    Daniel Lopes Newbie

      Hi there,


      here is my situation:


      I've got a SFSB with ScopeType.SESSION and a MDB which receives messages from the JMS (sent from another application). Is there a way to get this message (the message object inside) to the SFSB? I tried it via raising an event with the message as parameter but it didn't work. Also injecting the SFSB didn't work (seems Seam tries to create a new one instead of injecting an existing one). It looks like the session context or components in this context aren't reachable? If someone has a hint I would be very thankful.


      Best regards,
      Daniel

        • 1. Re: JMS and session scoped Seam component
          Arbi Sookazian Master

          post your code for all relevant classes...

          • 2. Re: JMS and session scoped Seam component
            Leo van den berg Master

            Hi Daniel,


            Search this forum for JMS solutions, because we had different discussion about this subject. It's not very difficult as long as you configure evrything corect (SeamInterceptor and the JNDI-Name annotations or otherwise configured) At the moment Seam interacts with the MDB you can inject the Events comonent and send whatever event to the rest of your application.


            I've included a simple example:



            @MessageDriven(activationConfig = {
            @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
            @ActivationConfigProperty(propertyName = "destination", propertyValue = "topic/events") })
            @Name("SeamMDBEventListener")
            @JndiName("SeamMDBEventListener")
            public class EventMDB implements MessageListener {
            
            private Log log = LogFactory.getLog(EventMDB.class);
            
            @PersistenceContext
            EntityManager em;
            
            /** This is the event link to SEAM, whatever you receive will be notified. */ 
            @In Events events;
                 
            @Override
            public void onMessage(Message message) {
                      
                 String type;
                 try {
                      type = message.getStringProperty("eventType");
                      log.info("Received an event message: " + type);
                      if (events != null) {
                           events.raiseEvent(type);
                           log.info("We will notify SEAM of an event.");
                      }
                      else log.error("Impossible to transmit something events is very NULL");
                           
                      } catch (JMSException e) {
                           log.error("Error while receiving an event");
                      }
                 }
            }
            



            I use it to relay specific events over JMS back the different sessions, because you can't  send events across different user-session.


            Leo



            • 3. Re: JMS and session scoped Seam component
              Leo van den berg Master

              Hi,


              saved to fast forgot some cleaning up.


              Replace the Logger with an injected one @Logger and get rid of the entityManager. Furthermore you can add additional messagefiltering in the JMS configuration.



              For instance:




              @ActivationConfigProperty(propertyName="messageSelector",propertyValue="YourType = 'yourValue'"
              



              • 4. Re: JMS and session scoped Seam component
                Leo van den berg Master

                Hi,


                I looked it up.


                This was the best thrad about the subject, thanks to Dan Allen !!


                http://seamframework.org/Community/JMSMessageListenerInAWebApplication


                Leo

                • 5. Re: JMS and session scoped Seam component
                  Daniel Lopes Newbie

                  Thx for the replies,


                  mhm ok the SFSB is in session scope and instantiated when the user logs in (pretty normal) and observes an event. The MDB raised event instantiates a new SFSB instead of using the already existing one. I would to transport the message from the MDB to an already existing SFSB in session scope. Maybe i don't understand your hint :(.

                  • 6. Re: JMS and session scoped Seam component
                    Nikolay Elenkov Master

                    Daniel Lopes wrote on Nov 07, 2009 00:39:


                    mhm ok the SFSB is in session scope and instantiated when the user logs in (pretty normal) and observes an event. The MDB raised event instantiates a new SFSB instead of using the already existing one. I would to transport the message from the MDB to an already existing SFSB in session scope. Maybe i don't understand your hint :(.


                    Your MDB does not have access to the Session, to there is no way to use your existing SFSB, that's why a new one gets created.

                    • 7. Re: JMS and session scoped Seam component
                      Nikolay Elenkov Master

                      Leo van den Berg wrote on Nov 07, 2009 00:12:


                      I use it to relay specific events over JMS back the different sessions, because you can't  send events across different user-session.



                      How exactly do you accomplish this? Do you mean all sessions receive the event if you send it from your MDB?


                      • 8. Re: JMS and session scoped Seam component
                        Daniel Lopes Newbie

                        Nikolay Elenkov wrote on Nov 07, 2009 06:47:



                        Leo van den Berg wrote on Nov 07, 2009 00:12:


                        I use it to relay specific events over JMS back the different sessions, because you can't  send events across different user-session.



                        How exactly do you accomplish this? Do you mean all sessions receive the event if you send it from your MDB?




                        That's what I would like to know to, as it would solve my problem ;).

                        • 9. Re: JMS and session scoped Seam component
                          Leo van den berg Master

                          Hi,


                          You can't send events between sessions, but you can receive it in a application-scoped bean whic relays it further.


                          Another option I used (look in previous threads) is to wait for messages in a speciic session bean (make it a listener). Its a bit difficult with a POJO because you need to make direct calls to JMS to receive messages, but it can be done.


                          There is also the JMS client receiver as a sort of web remote functionality, but i don't use it because of the restrictions of JavaScript and the need to capture whatever happens within the client because the client will hang if not failure proof.


                          I personally prefer the JMS-listener per session.


                          Leo

                          • 10. Re: JMS and session scoped Seam component
                            Nikolay Elenkov Master

                            Leo van den Berg wrote on Nov 07, 2009 19:46:


                            You can't send events between sessions, but you can receive it in a application-scoped bean whic relays it further.



                            So your app-scoped bean has a list of sessions then? Do you switch sessions to send an event? Or you use some other notification mechanism?



                            Another option I used (look in previous threads) is to wait for messages in a speciic session bean (make it a listener). Its a bit difficult with a POJO because you need to make direct calls to JMS to receive messages, but it can be done.


                            I tried searching, but couldn't find it (forum search could use a few improvements...). Do you mean registering it as a listener by using MessageConsumer.setMessageListener? I tried something similar a while back, but JMS failover (in JBoss 4.2) didn't work. Could you show some code?


                            • 11. Re: JMS and session scoped Seam component
                              Nikolay Elenkov Master

                              So I've been playing with the idea of inter-session events, and here's what I've come up with. Quite hackish, but it works. If Seam gave you easy access to the actual HttpSession, could be implemented with ServletLifecycle.beginSession() instead of the reflection hack.


                              The idea is:



                              1. create a session-scoped JMS listener, subscribe to a topic

                              2. in the @Create method save a reference to the session Context (this works because @Create is called when the first HTTP request is made)

                              3. to send an event to all sessions, send a JMS message to the topic

                              4. in the onMessage method, replace the empty session context created by Lifecycle.beginCall() with the one saved in 2.

                              5. raise the event

                              6. replace the session Context with the original one to avoid self-destruction :)



                              Something like:


                              @Name("sessionListener")
                              @Scope(ScopeType.SESSION)
                              @AutoCreate
                              @Startup
                              public class SessionListener implements MessageListener, HttpSessionListener {
                              
                                  @Logger
                                  private Log log;
                                   
                                  //....
                              
                                  private Context sessionContext;
                              
                                  private Context oldSessionContext;
                              
                                  @Create
                                  public void create() throws JMSException, NamingException {
                                      log.info("SessionListener created");
                                      sessionContext = Contexts.getSessionContext();
                              
                                      connectionFactory = lookupConnectionFactory();
                                      connection = connectionFactory.createConnection();
                                      session = createSession(connection);
                              
                                      destination = lookupDestination();
                              
                                      createConsumer();
                                      connection.start();
                                      log.debug("started connection");
                              
                                  }
                              
                                  public void onMessage(Message msg) {
                                      try {
                                          TextMessage txtMsg = (TextMessage) msg;
                              
                                          Field sessionCtx = Reflections.getField(
                                                  org.jboss.seam.contexts.Contexts.class, "sessionContext");
                                          sessionCtx.setAccessible(true);
                                          ThreadLocal<Context> sessionContextTl = (ThreadLocal<Context>) Reflections
                                                  .getAndWrap(sessionCtx, null);
                              
                                          try {
                                              Lifecycle.beginCall();
                              
                                              oldSessionContext = sessionContextTl.get();
                                              sessionContextTl.set(sessionContext);
                              
                                              log.info("SessionListener " + this);
                                              String txt = txtMsg.getText();
                                             
                                              Events.instance().raiseEvent("foo", txt);
                                          } finally {
                                              sessionContextTl.set(oldSessionContext);
                                              Lifecycle.endCall();
                                          }
                                      } catch (JMSException e) {
                                          throw new RuntimeException(e);
                                      }
                                  }
                              }
                              



                              Any better ideas?

                              • 12. Re: JMS and session scoped Seam component
                                Daniel Lopes Newbie

                                I had a similar idea.
                                Instead of sending messages to a queue I will use a topic. Per session then there will be a component that subscribes to the topic and periodically checks for updates. Checking would be triggered through remoting and the help of the periodicalexecuter of the prototype library.

                                • 13. Re: JMS and session scoped Seam component
                                  Leo van den berg Master

                                  Hi,


                                  this is the original thread I mentioned:




                                  http://seamframework.org/Community/JMSMessageListenerInAWebApplication#comment80113





                                  Leo

                                  • 14. Re: JMS and session scoped Seam component
                                    Nikolay Elenkov Master

                                    Leo van den Berg wrote on Nov 10, 2009 09:23:


                                    this is the original thread I mentioned:


                                    http://seamframework.org/Community/JMSMessageListenerInAWebApplication#comment80113





                                    Thanks. That one has a repeating job that polls for JMS messages. I was more interested in how you implemented the 'relay specific events over JMS back the different sessions' part. Could you shed a bit more light about this?

                                    1 2 Previous Next