Java Spring侦听器容器-事务管理器-Spring重试-在多个事务中
我有一个Spring引导服务,使用RabbitMQ 我正在开发一个测试,以确保一个进程在多个事务之间保持事务状态 例如:Java Spring侦听器容器-事务管理器-Spring重试-在多个事务中,java,spring,rabbitmq,spring-transactions,spring-amqp,Java,Spring,Rabbitmq,Spring Transactions,Spring Amqp,我有一个Spring引导服务,使用RabbitMQ 我正在开发一个测试,以确保一个进程在多个事务之间保持事务状态 例如: @Transactional @RabbitListener Queue Listener 1 1- receive message 2- call to Class 1 Method 1 @Transactional Class 1 Method 1 1- Persist some data in data base 2- Publish a Message in a 2
@Transactional
@RabbitListener
Queue Listener 1
1- receive message
2- call to Class 1 Method 1
@Transactional
Class 1 Method 1
1- Persist some data in data base
2- Publish a Message in a 2nd Queue
@Transactional
@RabbitListener
Queue Listener 2
- read message
- doStuff()
我希望我的服务具有以下行为
如果在队列侦听器2中
抛出异常(例如在doStuff()
中),我也想回滚类1方法1
事务。
我也想要重试
使用传播配置事务。支持或传播。必需的似乎也不起作用
Rabbit侦听器被注释为@Transactional
为此,我将我的SimpleRableBitListenerContainerFactory
建议链配置为StatefulRetryOperationsInterceptor
我配置了事务管理器,在我的应用程序中它是JpaTransactionManager
Rabbit templates通道事务被设置为true
还有带有jackson2JsonMessageConverter.setCreateMessageId的消息转换器(true)代码>,以保留消息ID
这里我附上我的SimpleRableBitListenerContainerFactory
config:
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(final SimpleRabbitListenerContainerFactoryConfigurer configurer,
final PlatformTransactionManager platformTransactionManager) throws IOException {
final SimpleRabbitListenerContainerFactory container = new SimpleRabbitListenerContainerFactory();
final CachingConnectionFactory cachingConnectionFactory = cachingConnectionFactory();
container.setConnectionFactory(cachingConnectionFactory);
container.setMessageConverter(jackson2JsonMessageConverter());
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
container.setDefaultRequeueRejected(false);
container.setConsecutiveIdleTrigger(1);
container.setConcurrentConsumers(1);
container.setMaxConcurrentConsumers(1);
container.setChannelTransacted(true);
container.setTransactionManager(platformTransactionManager);
container.setConcurrentConsumers(listenerConcurrency);
container.setMaxConcurrentConsumers(maxListenerConcurrency);
final StatefulRetryOperationsInterceptor statefulRetryOperationsInterceptor = RetryInterceptorBuilder.stateful()
.retryPolicy(new SimpleRetryPolicy(maxAttempts, exceptionsTriggeringRetry()))
.backOffPolicy(backOffPolicy())
.build();
container.setAdviceChain(statefulRetryOperationsInterceptor);
configurer.configure(container, cachingConnectionFactory);
return container;
}
@Bean
public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(objectMapper);
jackson2JsonMessageConverter.setCreateMessageIds(true);
return jackson2JsonMessageConverter;
}
@Bean
public RabbitTemplate transactedRabbitTemplate(@Named("cachingConnectionFactory") final ConnectionFactory connectionFactory,
@Named("jackson2JsonMessageConverter") final Jackson2JsonMessageConverter jackson2MessageConverter){
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(jackson2MessageConverter);
rabbitTemplate.setChannelTransacted(true);
return rabbitTemplate;
}
重试策略及其重试次数似乎得到了尊重
但是事务完整性(具有回滚)似乎没有被执行(因此在以前的事务中没有回滚。即:第三个事务失败不会触发第二个事务回滚),但是同一事务单元中的错误当然可以正常工作
编辑
还审判了:
container.setAdviceChain(新TransactionInterceptor(platformTransactionManager,新属性())代码>
但似乎无论如何都不起作用。事务不能跨越这样的队列;发布到队列是第一个事务的终点
生产者和消费者彼此孤立
由于您也在使用Rabbit事务,Listener 2甚至在第一个事务提交之前都不会看到消息。明白了,非常感谢,所以我需要换一种方法。顺便说一句,在共享该配置的情况下,当重试发生时,它们似乎正在发生,但会再次将其发送到队列,因为它们具有redelivered=true
属性,这将是不需要重新请求相同消息而仅重试的另一种方式?因此使用redelivered=false
?AFAIKcontainer.setDefaultRequeueRejected(false)代码>将配置该行为。使用无状态(而不是有状态)重试侦听器进行内存内重试。