Results 1 to 10 of 13

Thread: JMS DMLC not caching connection when using TX despite cacheLevel = CACHE_CONSUMER?

Hybrid View

  1. #1
    Join Date
    Feb 2012
    Posts
    8

    Question JMS DMLC not caching connection when using TX despite cacheLevel = CACHE_CONSUMER?

    Hello,

    The DMLC java doc 3.0.5.RELEASE says that cacheLevel can be set differently than CACHE_NONE in case of using transactions:

    "This non-caching behavior can be overridden through the "cacheLevel" / "cacheLevelName" property, enforcing caching of the Connection (or also Session and MessageConsumer) even in case of an external transaction manager being involved. "

    I am running the Spring JMS config as below [1] and configure the DMLC to use CACHE_CONSUMER and to be transacted, using the Spring JmsTransactionManager.

    Using that config [1] I would assume that the JMS connection is getting cached by DMLC.
    However while debugging I noticed that the JmsTransactionManager always calls into ConnectionFactory.createConnection() as part of the doBegin() implementation for the transaction.
    Similarly the cleanup after a commit closes the connection again.
    I do not see any JMS resource caching happening at the DMLC level when using the JmsTransactionManager.
    Turning off transactions, correctly caches the connection, consumer and session.

    Do I misunderstand the javadoc of DMLC or do I miss any further configuration in order to cache the JMS connection?
    I am well aware that a CachingConnectionFactory is recommended when using the JmsTransactionManager in order to pool the connection at that level. Still I would like to understand if that javadoc is incorrect or if I can enable JMS resource caching at the DMLC level when using transactions.

    Any feedback welcome.


    Thanks,

    Torsten Mielke
    tmielke.blogspot.com


    [1] Spring JMS config used
    <bean id="jms" class="org.apache.activemq.camel.component.ActiveM QComponent">
    <property name="configuration" ref="jmsConfigAmq" />
    </bean>


    <bean id="jmsConfigAmq" class="org.apache.activemq.camel.component.ActiveM QConfiguration" >
    <property name="connectionFactory" ref="jmsPooledConnectionFactory" />
    <property name="transacted" value="true"/>
    <property name="transactionManager" ref="jmsTransactionManager" />
    <property name="cacheLevelName" value="CACHE_CONSUMER"/>
    </bean>

    <bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTrans actionManager">
    <property name="connectionFactory" ref="jmsPooledConnectionFactory" />
    </bean>

    <bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFacto ry">
    <property name="brokerURL" value="tcp://localhost:61617" />
    <property name="watchTopicAdvisories" value="false" />
    </bean>

    <bean id="jmsPooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFa ctory" >
    <property name="maxConnections" value="3"/>
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
    </bean>

  2. #2
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,036

    Default

    Please use [ code]...[/code ] tags (no spaces inside) around code and config.

    See the javadoc for DMLC.setCacheLevel; when an external transaction manager is used, the cache level defaults to CACHE_NONE instead of CACHE_CONSUMER otherwise.

    You may also chose to set sessionTransacted to true, without specifying an external tx manager; in which case the default remains at CACHE_CONSUMER.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  3. #3
    Join Date
    Feb 2012
    Posts
    8

    Default

    Many thanks for the prompt reply Gary.

    I understand that CACHE_NONE is used by default in case of running in a transaction. However the Java doc of DMLC explicitly offers to set a different cache level with an external JMS transaction manager, which I have done in my config snippet above.
    Should it not cache the connection when using such config? Or do I misunderstand the docs?

  4. #4
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,036

    Default

    I didn't see a DMLC configuration in your example; hence my comments; now I see you are using Camel.

    I am not familiar with the camel wrapper, but I do know that setting the cache level works fine on an vanilla DMLC.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  5. #5
    Join Date
    Feb 2012
    Posts
    8

    Default

    Hello Gary,

    Yes, I am using camel-jms in my example. camel-jms sets up a DMLC instance for receiving msgs from the JMS broker. That DMLC instance uses the Spring JmsTransactionManager to begin a new transaction. And that tx manager calls into ConnectionFactory.createConnection for every transaction!
    See a sample stack trace below *1).

    At this point there is no Camel code involved yet. Camel only gets involved after a msg was received.
    The connection is closed again as part of the resource cleanup after a transaction commit.

    This procedure of calling ConnectionFactory.createConnection() Connection.close() is repeated for every new transaction (every new msg).
    Needless to say that if the JMS connection isn't cached by DMLC then other resources like consumer and session aren't cached either.

    Bottom line is I don't see any JMS resource caching happening at Spring DMLC level despite setting CACHE_CONSUMER.
    So it still seems to me the DMLC javadoc is wrong or I am missing some configuration that enables caching in DMLC.
    Any idea?

    Many thanks,
    Torsten

    *1)
    Daemon Thread [Camel (camelContext) thread #0 - JmsConsumer[adam.test]] (Suspended)
    owns: org.apache.activemq.pool.PooledConnectionFactory (id=178)
    org.apache.activemq.pool.PooledConnectionFactory.c reateConnection(java.lang.String, java.lang.String) line: 119
    org.apache.activemq.pool.PooledConnectionFactory.c reateConnection() line: 94
    org.springframework.jms.connection.JmsTransactionM anager.createConnection() line: 280
    org.springframework.jms.connection.JmsTransactionM anager.doBegin(java.lang.Object, org.springframework.transaction.TransactionDefinit ion) line: 179
    org.springframework.jms.connection.JmsTransactionM anager(org.springframework.transaction.support.Abs tractPlatformTransactionManager).getTransaction(or g.springframework.transaction.TransactionDefinitio n) line: 371
    org.apache.camel.component.jms.JmsMessageListenerC ontainer(org.springframework.jms.listener.Abstract PollingMessageListenerContainer).receiveAndExecute (java.lang.Object, javax.jms.Session, javax.jms.MessageConsumer) line: 240
    org.springframework.jms.listener.DefaultMessageLis tenerContainer$AsyncMessageListenerInvoker.invokeL istener() line: 1058
    org.springframework.jms.listener.DefaultMessageLis tenerContainer$AsyncMessageListenerInvoker.execute OngoingLoop() line: 1050
    org.springframework.jms.listener.DefaultMessageLis tenerContainer$AsyncMessageListenerInvoker.run() line: 947
    java.util.concurrent.ThreadPoolExecutor$Worker.run Task(java.lang.Runnable) line: 886
    java.util.concurrent.ThreadPoolExecutor$Worker.run () line: 908
    java.lang.Thread.run() line: 680

  6. #6
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,036

    Default

    I don't know what to tell you. I just ran another test to confirm and this works just fine...

    Code:
    <beans:bean id="lc" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    	<beans:property name="cacheLevelName" value="CACHE_CONSUMER" />
    	<beans:property name="transactionManager" ref="transactionManager" />
    	<beans:property name="sessionTransacted" value="true" />
    	<beans:property name="destination" ref="requestQueue" />
    	<beans:property name="connectionFactory" ref="connectionFactory" />
    </beans:bean>
    You can see in the log the same consumer (and hence connection) used for each poll...

    Code:
    2012-02-28 12:09:55,320 [lc-1] DEBUG: org.springframework.jms.connection.CachingConnectionFactory - Creating cached JMS MessageConsumer for destination [queue://queue.demo]: ActiveMQMessageConsumer { value=ID:myhost-42827-1330448994985-2:1:1:1, started=true }
    ...
    2012-02-28 12:09:56,329 [lc-1] TRACE: org.springframework.jms.listener.DefaultMessageListenerContainer - Consumer [Cached JMS MessageConsumer: ActiveMQMessageConsumer { value=ID:myhost-42827-1330448994985-2:1:1:1, started=true }] of session [Cached JMS Session: ActiveMQSession {id=ID:myhost-42827-1330448994985-2:1:1,started=true}] did not receive a message
    ...
    2012-02-28 12:09:57,345 [lc-1] TRACE: org.springframework.jms.listener.DefaultMessageListenerContainer - Consumer [Cached JMS MessageConsumer: ActiveMQMessageConsumer { value=ID:myhost-42827-1330448994985-2:1:1:1, started=true }] of session [Cached JMS Session: ActiveMQSession {id=ID:myhost-42827-1330448994985-2:1:1,started=true}] did not receive a message
    ...
    etc
    Are you sure Camel is propagating the configuration properly?
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •