在TransactionSystemException之后,SimpleMessageListenerContainer持续消耗

时间:2016-10-18 20:01:09

标签: spring-integration spring-transactions spring-amqp

当我的交易标记为回滚时,我不希望SimpleMessageListenerContainer继续使用这些消息。

我没有在配置文件中添加listener-container并尝试重新抛出AmqpRejectAndDontRequeueException。它不起作用。 这是我的代码库:

@Transactional
 public class MySecondService {

    @Resource
    private MySecondRepository mySecondRepository;

    @Transactional(propagation = Propagation.REQUIRED)
    @ServiceActivator(inputChannel = "my-first-servie-output-channel",
                      outputChannel = "my-Second-servie-output-channel")
    public String saveEntity(final MyTestEntity myTestEntity) 
        throws AmqpRejectAndDontRequeueException {
         try {
            mySecondRepository.save(myTestEntity);
         } catch (Exception e) {
            throw new AmqpRejectAndDontRequeueException("exception");
        }
    }
} 

弹簧整合-context.xml中

<int:chain input-channel="transaction-inbound-channel" output-channel="my-first-servie-input-channel">
    </int:chain>
<int-amqp:inbound-channel-adapter
            channel="transaction-inbound-channel"
            queue-names="sample.queue"
            concurrent-consumers="5"
            error-channel="failed-channel"
            connection-factory="rabbitConnectionFactory"
            mapped-request-headers="*" 
            transaction-manager="transactionManager" />

    <rabbit:connection-factory
            id="rabbitConnectionFactory"
            connection-factory="rcf"
            host="${spring.rabbitmq.host}"
            port="${spring.rabbitmq.port}"
            username="${spring.rabbitmq.username}"
            password="${spring.rabbitmq.password}"
            />
    <bean id="rcf" class="com.rabbitmq.client.ConnectionFactory">
        <property name="host" value="${spring.rabbitmq.host}"/>
        <property name="requestedHeartbeat" value="10" />
    </bean>

这是堆栈跟踪:

WARN [] org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer - Consumer raised exception, processing can restart if the connection factory supports it
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:526) ~[spring-orm-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757) ~[spring-tx-4.1.9.RELEASE.jar:4.1.9.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726) ~[spring-tx-4.1.9.RELEASE.jar:4.1.9.RELEASE]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:150) ~[spring-tx-4.1.9.RELEASE.jar:4.1.9.RELEASE]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:1062) ~[spring-rabbit-1.5.3.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1100(SimpleMessageListenerContainer.java:93) ~[spring-rabbit-1.5.3.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1203) ~[spring-rabbit-1.5.3.RELEASE.jar:na]
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_55]
Caused by: javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:74) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517) ~[spring-orm-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    ... 7 common frames omitted
2016-10-19 00:52:50,673 [SimpleAsyncTaskExecutor-1] INFO [] org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer - Restarting Consumer: tags=[{amq.ctag-QBWGIY7co5vUpXwGDXDDBg=sample.queue}], channel=Cached Rabbit Channel: AMQChannel(amqp://test@999.99.99.999:9999/,2), acknowledgeMode=AUTO local queue size=0 

我不希望这种情况发生org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer - Restarting Consumer

有人可以帮助我添加我需要添加的其他内容来重新抛出AmqpRejectAndDontRequeueException。提前谢谢。

1 个答案:

答案 0 :(得分:0)

你没有显示流程。

如果您只是调用单个服务,则不要将事务管理器添加到入站通道适配器。

事务将在调用服务时启动;只要failed-channel上的错误流不会引发异常(或抛出AmqpRejectAndDontRequeueException),该消息就不会被重新排队。

如果您有多个服务要参与单个事务,则可以使用AOP建议进行事务transaction-inbound-channel,下游流程将全部在该事务中运行。

或者,如果您从不希望邮件重新排队,请在入站适配器的容器中设置defaultRequeueRejectedfalse(您必须连接到该容器)作为<bean/>)。