1 2 Previous Next 16 Replies Latest reply on May 4, 2010 6:47 PM by unsavory

    Confusion on how to use ClientSessionFactory...

    unsavory

      All the examples seem to create new sessions every time a message is published or consumed.  Such as below:

       

      ClientSessionFactory factory =  HornetQClient.createClientSessionFactory(
                      new TransportConfiguration(
                         InVMConnectorFactory.class.getName()));

       

      ClientSession session = factory.createSession();
              session.start();
         
              ClientConsumer consumer = session.createConsumer("example");
          boolean run = true;
              while(run) {
              ClientMessage msgReceived = consumer.receive();
              // Important... acknowledge message.
              msgReceived.acknowledge();
         
              System.out.println("message = " + msgReceived.getStringProperty("msg"));
             
              }
         
              session.close();

       

      If I am consuming thousands of messages, do I want to create, start and close the session each time?  Or perform it all within the same session?

       

      And in the case of producers, should all the producers use the same ClientSession?  Or use the ClientSessionFactory to create a new session for each message?

        • 2. Re: Confusion on how to use ClientSessionFactory...
          unsavory

          Thanks for the link.  However, from your comment at the bottom...

           

          i think it's very clear. One thing should  be noted is when you reuse sessions, be aware of the thread safe issue.  JMS doesn't guarantee session's thread safety.

           

          So if my producers are running inside a web application with multiple threads, how could I possibly re-use the sessions if they are not thread-safe?  In this situation, should I be creating new sessions for each request?

          • 3. Re: Confusion on how to use ClientSessionFactory...
            gaohoward

            I think that needs some work to solve this. for example, you can create a class dedicated to messaging sending/receiving. Instead of handling the messaging related task directly inside a request, you put the messaging related task to the dedicated class, which can cache the session and synchronize the message handling. or you can keep a session per thread and handle messaging concurrently.

            • 4. Re: Confusion on how to use ClientSessionFactory...
              gaohoward

              Preferrably you can use JCA, as desribed in the wiki.

              1 of 1 people found this helpful
              • 5. Re: Confusion on how to use ClientSessionFactory...
                unsavory

                Thanks for the suggestions.  I would say the JBoss documentation is misleading then if it says...

                 

                If you're using just raw JMS - i.e you have a simple JMS client which  connects directly to a JMS server using the JMS API, then you should  always re-use JMS objects.

                 

                JMS objects like connection, session, consumer  and producer were designed to be re-used.

                 

                 

                The information may be factual, but nowhere does it say or imply that the JMS objects are not thread-safe and should be treated with care in highly concurrent environments.

                 

                I'm not running in a JEE appserver so do not have JCA available that I know of unless there is some way to configure a JCA provider inside Tomcat.  I suppose synchronization might work but it would severely impact multi-threaded performance.

                • 6. Re: Confusion on how to use ClientSessionFactory...
                  unsavory

                  As I think about this, perhaps I could initialize the factories and client sessions inside my servlet's init method?

                  • 7. Re: Confusion on how to use ClientSessionFactory...
                    timfox

                    Caine Lai wrote:

                     

                    All the examples seem to create new sessions every time a message is published or consumed.  Such as below:

                     

                    ClientSessionFactory factory =  HornetQClient.createClientSessionFactory(
                                    new TransportConfiguration(
                                       InVMConnectorFactory.class.getName()));

                     

                    ClientSession session = factory.createSession();
                            session.start();
                       
                            ClientConsumer consumer = session.createConsumer("example");
                        boolean run = true;
                            while(run) {
                            ClientMessage msgReceived = consumer.receive();
                            // Important... acknowledge message.
                            msgReceived.acknowledge();
                       
                            System.out.println("message = " + msgReceived.getStringProperty("msg"));
                           
                            }
                       
                            session.close();

                     

                    If I am consuming thousands of messages, do I want to create, start and close the session each time?  Or perform it all within the same session?

                     

                    And in the case of producers, should all the producers use the same ClientSession?  Or use the ClientSessionFactory to create a new session for each message?

                    Read the performance tuning section in the user manual.

                     

                    Session, consumers, producers etc should always be re-used. It is a classic *anti-pattern* to create them each time. This has also been discussed many times on other threads.

                     

                    There's also a wiki page that touches on this (should i use spring jms template)

                     

                    The examples are ok, since they only send a single message.

                    • 8. Re: Confusion on how to use ClientSessionFactory...
                      timfox

                      Caine Lai wrote:

                      So if my producers are running inside a web application with multiple threads, how could I possibly re-use the sessions if they are not thread-safe?

                      Re-using sessions has nothing to do with thread safety.

                       

                      The following code re-uses a session and a producer to send 1000 messages

                       

                      Session session = connection.createSession(..);

                       

                      MessageProducer prod = session.createProducer(...);

                       

                      for (int i = 0; i < 1000; i++)

                      {

                          prod.send(session.createMessage());

                      }

                       

                      You can also maintain references to your session, consumers, producers etc and pass them around your application, you just need to make sure they are not used *concurrently*.

                      • 9. Re: Confusion on how to use ClientSessionFactory...
                        timfox

                        Caine Lai wrote:

                         

                        The information may be factual, but nowhere does it say or imply that the JMS objects are not thread-safe and should be treated with care in highly concurrent environments.


                        It's in the JMS spec. Section 4.4.6:

                         

                        "Sessions are designed for serial use by one thread at a time."

                        • 10. Re: Confusion on how to use ClientSessionFactory...
                          timfox

                          Caine Lai wrote:

                           

                          So if my producers are running inside a web application with multiple threads, how could I possibly re-use the sessions if they are not thread-safe?  In this situation, should I be creating new sessions for each request?

                          No, do not create new sessions for each request.

                           

                          If you are running tomcat in JBoss then you can just use the JCA adaptor - it DOES work in the embedded tomcat.

                           

                          If you are using Tomcat outside JBoss use a pool to cache sessions, producers etc. The checkout + return semantics of the pool will ensure the session is never used by more than one thread concurrently.

                          • 11. Re: Confusion on how to use ClientSessionFactory...
                            timfox

                            You can also use the Spring message listener container in tomcat

                            • 12. Re: Confusion on how to use ClientSessionFactory...
                              unsavory

                              First Tim, thank you very much for taking the time.  Your answers have given a lot of insight into how I should go about implementing this.  I do have some questions though.

                               

                              You can also maintain references to your session, consumers, producers  etc and pass them around your application, you just need to make sure  they are not used *concurrently*.

                              OK, got it.  But I still have a question around session.start and session.end.  Do I maintain the reference to a session throughout my application and call session.start() and session.end() for each sent message?  Or do I call session.start() on application startup, and session.end() on application shutdown?

                               

                              It's in the JMS spec. Section 4.4.6:

                               

                              "Sessions are designed for serial  use by one thread at a time."

                              OK, but I am not using JMS.  I am using the HornetQ API.  Isn't JMS a layer on top of the HornetQ API?  How is one to know that the HornetQ API is not thread-safe by looking at the JMS spec?

                               

                              If you are using Tomcat outside JBoss use a pool to cache sessions,  producers etc. The checkout + return semantics of the pool will ensure  the session is never used by more than one thread concurrently.

                              Yes, I am using Tomcat outside Jboss.  I will definitely look into creating a pool, however because I don't have any experience with HornetQ, I am a bit concerned around what gotchas I would have to watch out for with the pool.  In other words, do I ever need to re-create a new session under some circumstances?  Would sessions ever die unexpectedly leaving me with a bad pool thread?  Etc., Etc.

                               

                              You can also use the Spring message listener container in tomcat

                              Again, I'm not using JMS.  Should I be?  I was going to use the HornetQ API for simplicity.  Also, my message listener will be a single thread since I need to process messages in the order they are received.  It is the message producers that need to be multi-threaded.

                               

                              Given this, does it sound like the thread pool approach would be the best way to go?  Or would it be simpler to use something like a thread-local instance of ClientProducer for my servlets?

                               

                              Thanks again for your helpful responses.

                              • 13. Re: Confusion on how to use ClientSessionFactory...
                                timfox

                                I assumed you were using JMS since you were talking about using JCA which of course only works with JMS.

                                • 14. Re: Confusion on how to use ClientSessionFactory...
                                  unsavory

                                  Sorry about the confusion.  Yong suggested I use JCA, so I was responding to that.  I am not apposed to using JMS if there is a reason to do it, but our needs are pretty simple so was hoping to stay with the HornetQ API.

                                  1 2 Previous Next