如何从两个不同的连接工厂加入Spring JMS事务?

时间:2017-10-18 17:21:13

标签: spring transactions spring-integration spring-transactions spring-jms

我使用不同的连接工厂来发送和接收消息,因为部分提交问题导致交付失败。 jms:message-driven-channel-adapter使用receiveConnectionFactory ro接收队列中的消息。 jms:outbound-channel-adapter使用deliverConnectionFactory将消息多次发送到下游队列。我们只有一个JmsTransactionManager使用receiveConnectionFactoryjms:outbound-channel-adapter使用session-transacted="true"配置。

<beans>
    <bean id="transactionManager"
        class="org.springframework.jms.connection.JmsTransactionManager">
        <property name="connectionFactory" ref="receiveConnectionFactory" />
    </bean>
    <bean id="receiveConnectionFactory"
        class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory">
            <bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
                <property name="hostName" value="${mq.host}" />
                <property name="channel" value="${mq.channel}" />
                <property name="port" value="${mq.port}" />
            </bean>
        </property>
        <property name="sessionCacheSize" value="${receive.factory.cachesize}" />
        <property name="cacheProducers" value="${receive.cache.producers.enabled}" />
        <property name="cacheConsumers" value="${receive.cache.consumers.enabled}" />
    </bean>

    <bean id="deliverConnectionFactory"
        class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory">
            <bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
                <property name="hostName" value="${mq.host}" />
                <property name="channel" value="${mq.channel}" />
                <property name="port" value="${mq.port}" />
            </bean>
        </property>
        <property name="sessionCacheSize" value="${send.factory.cachesize}" />
        <property name="cacheProducers" value="${send.cache.producers.enabled}" />
        <property name="cacheConsumers" value="${send.cache.consumers.enabled}" />
    </bean>

    <tx:advice id="txAdviceNew" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="send" propagation="REQUIRES_NEW" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:advisor advice-ref="txAdviceNew" pointcut="bean(inputChannel)" />
        <aop:advisor advice-ref="txAdviceNew" pointcut="bean(errorChannel)" />
    </aop:config>

    <jms:message-driven-channel-adapter
        id="mdchanneladapter" channel="inputChannel" task-executor="myTaskExecutor"
        connection-factory="receiveConnectionFactory" destination="inputQueue"
        error-channel="errorChannel" concurrent-consumers="${num.consumers}"
        max-concurrent-consumers="${max.num.consumers}" max-messages-per-task="${max.messagesPerTask}"
        transaction-manager="transactionManager" />

    <jms:outbound-channel-adapter
        connection-factory="deliverConnectionFactory" session-transacted="true"
        destination-expression="headers.get('Deliver')" explicit-qos-enabled="true" />
</beans>

当任何一个目标上存在MQ异常时,将发生部分提交,然后发生故障队列提交。我希望看看我是否缺少一些配置来加入事务,以便部分提交永远不会发生。

我尝试只有一个连接工厂用于发送和接收(receiveConnectionFactory)并且没有发生parital提交,一切都按预期工作。

1 个答案:

答案 0 :(得分:2)

  

我尝试只有一个连接工厂用于发送和接收(receiveConnectionFactory)并且没有发生parital提交,一切都按预期工作。

这是你的正确方法。

我看到你的两个ConnectionFactories只是因为它们的对象而不同。其余的东西看起来都像是同一个目标MQ服务器。

如果您绝对不能只使用一个ConnectionFactory,则应考虑使用JtaTransactionManager或将org.springframework.data.transaction.ChainedTransactionManager配置为两个JmsTransactionManagers - 每个连接工厂一个。< / p>

请参阅Dave Syer关于此事的文章:https://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html