0
votes

I have an application in JAVA that uses ActiveMQ. Following the suggestions of using a specific "session" for each consumer (to avoid problem with session concurrency from different threads) I am creating a new session before creating each new consumer. These consumers are using a MessageListener to gather their messages in an asynchronous way.

When a consumer closes I also want to close the session that was used (and explicitly created) to create this consumer, but I don´t have access to the session that was used to create the specific consumer I am going to close (this method does not exists in the "MessageConsumer" object of the consumer). I don´t want to keep all these sessions opened because the consumers are connecting and disconnecting dynamically and the final number of opened (and unused) sessions will be very high.

Is there a way to have access to the "session" that was used to create an specific "consumer" (MessageConsumer object) that uses a MessageListener?

Any other way to close the session when its consumer that uses a MessageListerner closes?

Could another possibility be a kind of automatic purge of "sessions" that do not have any resource associated with them (consumer, producer, etc.)?

Here is a snippet of my code:

    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    MessageConsumer consumer = session.createConsumer(session.createQueue(queueName));
    consumer.setMessageListener(new CustomMessageListener(locWSInstance));
1

1 Answers

0
votes

You can pass the session and consumer down to your CustomerMessageListener and it can call the close during its shutdown lifecycle of your CustomMessageListener. Otherwise, you'd need some sort of Manager/Tracker class to keep up with all the objects to prevent resource / memory leaks. This is no different than JDBC! With stateful communication comes performance and benefits, but you have to track your clean-up as a trade-off.

  1. Use a PooledConnectionFactory

  2. Be sure to unit test the lifecycle logic. This is a resource leak / memory leak waiting to happen.

  3. Do proper try { } catch {} finally {} logic around each object to ensure the close gets called on all of them, and you do not have a leak on .close() methods throwing an exception and exiting the code path before all .close() are called (see below)

     public void deactivate() {
    
         if(consumer != null) {
            try {
                consumer.close();
            } catch (JMSException e) {
                // do some logging
            } finally {
                consumer = null;
            } 
         }
    
        if(session != null) {
            try {
                session.close();
            } catch (JMSException e) {
                // do some logging
            } finally {
                session = null;
            } 
         }
     }