jms beginner
jms beginner

Reputation: 3

Glassfish close JMS queue connection/session resources with delay. How JMS connection pooling works?

I have a performance problem when I receive/consume messages from a JMS queue over a Servlet.
A simple request over the Servlet takes 10 seconds to execute the close method (to close the JMS resources) of the QueueSession object. The close Method takes 20-30 seconds if I use the Servlet more times in a row. A parallel execution (10 Requests at once) takes 6-7 minutes for queueConnection.close(). In a synchronized block I'm coming back to a value of 20-30 seconds for the execution of queueConnection.close().

I have the feeling that the Servlet threads taking the same QueueConnection from the pool.

Should not it be so that the Servlets taken free connection resources from the pool?

Following Pool settings of the JMS Connection Factory can be made: Initial and Minimum Pool Size, Maximum Pool Size, Pool Resize Quantity, Idle Timeout, Max Wait Time. I have tried with several settings for the Pooling but I got no better result.

I think I must also implement pooling myself to pool the connections that i get from the OpenMQ connection pool, is that right?

I have over 40,000 messages in the queue and the Messages are parameterized (using message selectors), is that the reason for the delay of the close-Method (to release JMS Ressources)? Would it matter if I switch from file based persistence to jdbc based persistence to get a better performance?

In the answer below was suggested to use the UMS Component of OpenMQ. UMS is usefull but I need to use message selectors and I think that this is not supported by UMS.

Thanks!

Coding:

public class MessageReceiver {
...
public MessageReceiver(){

        queueName = "myQueuedestination";
        jndiContext = new InitialContext();
        queue = (Queue) jndiContext.lookup(queueName);
        queueConnectionFactory = (ConnectionFactory) jndiContext
                .lookup("myQueueconnectionfactory");
        queueConnection = queueConnectionFactory.createConnection();
        queueConnection.start();
}
...
public String receive(String KEY, String keyValue) throws Exception {       


    String returnMessage = null;
    String messageSelector = getMessageSelector(KEY, keyValue);                         

    Message m = null;       


    QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    QueueReceiver queueReceiver = queueSession.createReceiver(queue, messageSelector);                  

    m = queueReceiver.receiveNoWait();

    if (queueSession != null) {
        try {
            queueSession.close();
        } catch (JMSException e) {
            logger.info("There was an error closing the queueSession");
            e.printStackTrace();
        }
    }           
    queueSession = null;

    if (m != null && m instanceof TextMessage) {
        returnMessage = ((TextMessage) m).getText();                 
    }

    return returnMessage;   
}
...
...
}

Servlet

...
public void init(ServletConfig config) throws ServletException {
...
messageReceiver = new MessageReceiver();
...
}

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException      
{  
...
...

                synchronized (this) 
                {
                    message = messageReceiver.receive(KEY,     keyValue);
                }

...
...

}

Upvotes: 0

Views: 1336

Answers (1)

fvu
fvu

Reputation: 32953

IMO if you feel you have to consume messages in a servlet there may be something wrong with your design... I most strongly advise you to receive messages in an MDB, Message Driven Bean. That's the construct in Java Enterprise that's been created to consume messages.

Upvotes: 1

Related Questions