Search code examples
javaspringjmsactivemq-classicmessaging

JAX-WS connection won't close, and stops messaging after x messages


I've got a little problem with JAX-WS. I'm using ActiveMQ as MOM and Spring. The messaging is really simple: one jar should send a soap message with some data to another.

I defined the client this way in my sender_beans.xml:

<bean id="jmsConfig-Manager" class="org.apache.cxf.transport.jms.JMSConfiguration"
    p:connectionFactory-ref="jmsConnectionFactory"
    p:targetDestination="activemq:example.manager"
    p:pubSubDomain="true" p:maxConcurrentConsumers="40" p:deliveryMode="1"
    p:explicitQosEnabled="true" p:reconnectOnException="true" />

<bean id="jmsConnectionFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="sessionCacheSize" value="40" />

    <property name="targetConnectionFactory">
        <bean class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL"

                value="tcp://localhost:61616?jms.useAsyncSend=true" />
        </bean>
    </property>
</bean>

And this is my endpoint:

<jaxws:endpoint id="ManagerService" implementor="#ManagerServ"
    implementorClass="com.example.Service"
    address="jms://">
    <jaxws:features>
        <bean class="org.apache.cxf.transport.jms.JMSConfigFeature"
            p:jmsConfig-ref="jmsConfig-Manager" />
    </jaxws:features>
</jaxws:endpoint>
<bean id="jmsConnectionFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="sessionCacheSize" value="40" />

    <property name="targetConnectionFactory">
        <bean class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL"

                value="tcp://localhost:61616?jms.useAsyncSend=true" />
        </bean>
    </property>
</bean>

So, the messaging works - but only 40 times! (Which is the value of ever p:maxConcurrentConsumers). I think the problem is that every time a message is send, a new consumer is created but never destroyed. So after 40 messages no new consumer can be created and the messaging stops working. I have to restart the complete messaging.

I only can use the declarative way to fix this problem, I never call anything from jms in my code.


Solution

  • The CachingConnectionFactory by default will cache message consumers and producers. You can disable this by setting the cacheConsumers and cacheProducers properties to 'false'.

    I.e. for your Spring xml:

    <bean id="jmsConnectionFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory">
       <property name="sessionCacheSize" value="40" />
       <property name="cacheConsumers" value="false" />
       <property name="targetConnectionFactory">
    ...
    

    I had a recent issue where programmatically created Message Consumers weren't being destroyed when calling .close() on the consumer object (I could still see the active consumers on the ActiveMQ admin console). cacheConsumers = false resolved this for me.

    Furthermore, read the Spring API on the Caching and Single connection factories to ensure you are using the correct one for your scenario - they mention all of this.