users@glassfish.java.net

Produce Message From Message Driven Bean - createQueueConnection

From: <glassfish_at_javadesktop.org>
Date: Tue, 16 Oct 2007 13:02:21 PDT

We are using Message Driven Bean to
- get the message from a Queue
- process it
- and Produce the processed messages to a Queue

This question is regarding producing message from a Message Driven Bean

In the Sun Java System App Server 9.1 performance tunning guide's "Tuning Message-Driven Beans" section it is mentioned

http://docs.sun.com/app/docs/doc/819-3681/abebw?a=view

[u][b]Caution[/b][/u]:
Previous to version 8.1, it was possible to reuse a connection with a servlet or EJB component.That is, the servlet could call getConnection() in its init() method and then continually call getSession() for each servlet invocation. If you use JMS within a global transaction, that no longer works: [i]applications can only call getSession() once for each connection.[/i] After than, the connection must be closed (which doesn’t actually close the connection; it merely returns it to the pool). This is a general feature of portable J2EE 1.4 applications; the Sun Java System
Application Server enforces that restriction where previous (J2EE 1.3-based) application servers did not.

and also in the next paragraph "[u][b]Limit Use of JMS Connections[/b][/u]"
When designing an application that uses JMS connections make sure you use a methodology that sparingly uses connections, by either pooling them or using the same connection for multiple sessions.

[u][b]The above two seem contradictory[/b][/u].

In our scenario what would be the best suited option to produce a message from MDB:

1. create a static connection object from the QueueConnectionFactory in the ejbCreate() method
put a synchronised lock on it and use this in all the instances of the Bean to create QueueSession

instance level declarations

    @Resource(mappedName = "jms/ConnectionFactory")
    private QueueConnectionFactory queueConnectionFactory;
    private static QueueConnection queueConnection = null;
    private static Object lockCon = new Object();
    private static Object lockSession = new Object();
    
    in ejbCreate()
         synchronized(lockCon){
              if(queueConnection == null){
        queueConnection = queueConnectionFactory.createQueueConnection();
        queueConnection.start();
             }
       }
            
      
      while producing the message on to the queue
      
synchronized(lockSession){
qSession = queueConnection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
}
        
[b]Advantage[/b]:
- we are just using one connection per application.
- recommended approach in the "Limit Use of JMS Connections" section

[b]Disadvantage[/b]:
- connection is not pooled and contradicts the caution statement.
- In this approach we see few of the messages getting orphaned on the "mq.sys.dmq" queue
- where and when do we close the connection as it is shared by all the instances.

2. create a new connection(non static) object from the QueueConnectionFactory in the ejbCreate() and close the connection in the ejbRemove()
 
 [u][b]Advantage[/b][/u]:
 - we do not get any orphaned messages on the "mq.sys.dmq" queue.
 - appears to perform better than #1 approach
 [u][b]Disadvantage[/b][/u]:
 - the bean hangs on to the connection till its instance is created.So not a very efficient use of Connection Pooling
 
3. create a connection object in the onMessage() get a session out of it produce message and close the connection in the finally.

[b]Advantage[/b]:
- onMessage always gets a refreshed connection from the QueueConnectionFactory.

[b]Disadvantage[/b]:
- contradicts the statement in the "Limit Use of JMS Connections" block.

Please suggest what should be the best approach. we need lot of processing through put in this system.
[Message sent by forum member 'singhrvijay2007' (singhrvijay2007)]

http://forums.java.net/jive/thread.jspa?messageID=240497