Search code examples
jbossjmsspring-jmsjmstemplate

JmsTemplate and CachingConnectionFactory


I'm finding some difficulties in trying to reduce the connection and session creation when sending messages to a Jboss Queue.

<bean name="jbmTemplate-${jbmQueue}" class="org.springframework.jms.core.JmsTemplate" lazy-init="true">
        <property name="sessionTransacted" value="true" />

    <!-- connection factory -->
    <property name="connectionFactory">
        <ref bean="jbmCachingConnectionFactory"/>
    </property>

    <property name="pubSubDomain">
        <value>false</value>
    </property>

    <property name="receiveTimeout">
        <value>${jmsReceiveTimeout}</value>
    </property>

</bean>

I'm using a JmsTemplate to send messages:

<bean id="jbmCachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
     <property name="targetConnectionFactory" ref="jbmConnectionFactory" />
</bean>

And the jbmConnectionFactory is defined as follow:

<jee:jndi-lookup id="jbmConnectionFactory" jndi-name="XAConnectionFactory"
        resource-ref="true" lookup-on-startup="false" proxy-interface="javax.jms.ConnectionFactory"
        cache="false">
    <jee:environment>
        java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
        java.naming.provider.url=${jbmURL}
        java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
    </jee:environment>
</jee:jndi-lookup>

I'm using this piece of code to send messages to Jboss:

public void send(final Serializable payload, final String correlationId) {
    log.debug("payload: {}", payload);

    try {
        jmsQueueTemplate.send(destinationName, new MessageCreator() {
            public Message createMessage(Session session)
                    throws JMSException {
                ObjectMessage msg = session.createObjectMessage(payload);

                msg.setJMSType(payload.getClass().getCanonicalName());
                msg.setJMSCorrelationID(correlationId);

                return msg;
            }

        });
    } catch (Exception e) {
        log.error("Couldn't send message");
        throw new BlockingException(e);
    }
}

What I was trying to do by using the CachingConnectionFactory is to avoid creating and closing connections and sessions every message I send but as far as I can see, when using a JmsTemplate, no matter what type of connectionFactory I use, the connection and session will always be terminated:

finally {
            JmsUtils.closeSession(sessionToClose);
            ConnectionFactoryUtils.releaseConnection(conToClose, getConnectionFactory(), startConnection);
        }

Am I calling the wrong method? Is there something that I don't get?


Solution

  • The CachingConnectionFactory returns a proxy (wrapper) for the connection which ignores the close(). Similarly, session.close() is intercepted and the session is put in the cache instead of actually closing it.

    In fact, it requires the session to be "closed" so the session can be made available for the next use.

    You may need to configure the cache size (it's only 1 by default; see the javadocs).