Announcement Announcement Module
Collapse
No announcement yet.
MQSeries problem : receive messages in a transaction Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • MQSeries problem : receive messages in a transaction

    Hi ,

    I'm working with Spring Batch/Spring JMS to read messages from an MQ Series Queue and i'm struggling to make my JMSItemReader rollback the receive transaction in case of an exception.
    it works fine with ActiveMQ but with MQSeries , once the message is consumed , no way to get it back to the queue if an exception occurs.
    Here is my configuration file :

    <bean id="jmsMQConnectionFactory"
    class="com.ibm.mq.jms.MQConnectionFactory">
    <property name="queueManager">
    <value>${queue.queueManager}</value>
    </property>
    <property name="hostName">
    <value>${queue.hostName}</value>
    </property>
    <property name="port">
    <value>${queue.port}</value>
    </property>
    <property name="transportType" value="1" />
    <property name="channel" value="${queue.channel}" />
    </bean>
    <bean id="jmsFactory"
    class="org.springframework.jms.connection.UserCred entialsConnectionFactoryAdapter">
    <property name="targetConnectionFactory"
    ref="jmsMQConnectionFactory" />
    <property name="username" value="${queue.userid}" />
    <property name="password" value="${queue.pass}" />
    </bean>
    <bean id="jmsTemplate"
    class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory">
    <ref local="jmsFactory" />
    </property>
    <property name="defaultDestination" ref="destinationMQ" />
    <property name="messageConverter" ref="messageConverter" />
    <property name="receiveTimeout" value="500" />
    <property name="sessionTransacted" value="false" />
    </bean>
    <bean id="destinationMQ" class="com.ibm.mq.jms.MQQueue">
    <property name="baseQueueManagerName"
    value="${queue.queueManager}" />
    <property name="baseQueueName" value="${queue.baseQueueName}" />
    </bean>
    <bean id="messageConverter"
    class="com.converters.MessageToEntityConverter">
    </bean>
    <bean id="taskletStep" abstract="true"
    class="org.springframework.batch.core.step.item.Si mpleStepFactoryBean">
    <property name="jobRepository" ref="jobRepository" />
    <property name="transactionManager" ref="jmsTransactionManager" />
    <property name="commitInterval" value="1" />
    </bean>
    <bean id="queueReaderJob"
    class="org.springframework.batch.core.job.SimpleJo b">
    <property name="name" value="simpleJob" />
    <property name="restartable" value="true" />
    <property name="steps">
    <list>
    <bean id="step1" parent="taskletStep">
    <property name="itemReader" ref="itemReader" />
    <property name="itemWriter" ref="fileWriter" />
    </bean>
    </list>
    </property>
    <property name="jobRepository" ref="jobRepository" />
    </bean>
    <bean id="fileWriter"
    class="org.springframework.batch.item.file.FlatFil eItemWriter">
    <property name="resource" value="file:c:/result/result.txt" />
    <property name="fieldSetCreator">
    <bean
    class="org.springframework.batch.item.file.mapping .PassThroughFieldSetMapper" />
    </property>
    </bean>
    <bean id="itemReader"
    class="org.springframework.batch.item.jms.JmsItemR eader">
    <property name="jmsTemplate" ref="jmsTemplate" />
    </bean>
    <bean id="jmsTransactionManager"
    class="org.springframework.jms.connection.JmsTrans actionManager">
    <property name="connectionFactory" ref="jmsMQConnectionFactory" />
    </bean>

    I Hope someone resolved this problem before, thanks in advance.
    Last edited by kobaski; Nov 5th, 2008, 10:24 AM.

  • #2
    There's almost no chance that JMS will behave as you wish unless you use a single transaction manager (there is only one above, but the you didn't include the configuration of the JobRepository which also requires one). You also have sessionTransacted="false" which is unlikely to lead to transactional behaviour in JMS, unless I'm missing something. So it doesn't look like an MQSeries specific issue to me, but maybe I haven't understood something yet.

    Comment


    • #3
      Hi ,

      Thank you for your reply.

      I solved the problem finally, it was my transactionManager that is pointing to the MQConnectionFactory instead of UserCredentialsConnectionFactoryAdapter.
      (I purposely ommitted to put the jobRepositry so my question wont be too long).
      you mention that putting sessionTransacted="false" wont lead to a transactional behavior in JMS , but while debugging i found that in the JMSTemplate the receive transaction is committed just after calling receive on consumer if sessionTransacted="true" and the session was "bound to the current thread by Spring's transaction facilities." , but this is not the behavior i wish to have , what i want is that the commit is done once the step ended( means my itemWriter is executed). In my case the MQSession is never bounded to the local thread ( i dont know why and i don't really understand what does it mean ).
      But now i'm faced to a new Problem , when i receive my message i want to write it to a database with my itemWriter. but i have configured only one transactionManager ( a jms transaction manager) at Step Level and this won't rollback any database transaction if any exception occurs in my itemWriter. So the question is : is it possible to have a global transaction manager at Step Level that can do commit/rollback on both JMS and database if somthing goes wrong inside my itemReader or itemWriter.
      I found many responses talking about JTA , Atomikos but didn't find a way to make the right configuration.

      thank you again for your response.

      Comment


      • #4
        Hi folks,

        I have a similar problem (the second one) so I'm interested by the answer , I extract data from a database and put them in a MQSeries queue.

        My newbie problem is that I don't know how to encapsulate my JDBCItemReader and my JMSITemWriter in the same transaction?

        Do I only need a JTATransactionManager? Or I have to declare one for every connector I have and maybe configure them in such a way that they go well with each other?

        Comment


        • #5
          JMS and JDBC in one JTA tx

          Originally posted by kobaski View Post
          Hi ,

          you mention that putting sessionTransacted="false" wont lead to a transactional behavior in JMS , but while debugging i found that in the JMSTemplate the receive transaction is committed just after calling receive on consumer if sessionTransacted="true"
          It commits on the session, but in a JTA context the commit will be ignored with an exception caught in Spring.

          So the question is : is it possible to have a global transaction manager at Step Level that can do commit/rollback on both JMS and database if somthing goes wrong inside my itemReader or itemWriter.
          I found many responses talking about JTA , Atomikos but didn't find a way to make the right configuration.
          Use a JTA transaction manager, not a JmsTransactionManager or JdbcTransactionManager in Spring. See http://www.atomikos.com/Publications...ionsWithSpring for a presentation on the mechanics of this, or get developer support at Atomikos to configure your XML files. Also make sure to use the Atomikos JDBC and JMS connection factories or it will not work.

          Comment


          • #6
            Thank you all for your help,

            I got it work like a charm finally with ActiveMQ, ( Still have problems with MQSeries but i'm sure it's an MQ issue , have to configure it to work with XA ).

            Now when something goes wrong in my database itemwriter the JTA transaction manager rollback both database and performed JMS receive in my JMSItemReader.

            I attached a sample configuration .

            Thank you again.

            Comment

            Working...
            X