Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring侦听器容器-事务管理器-Spring重试-在多个事务中_Java_Spring_Rabbitmq_Spring Transactions_Spring Amqp - Fatal编程技术网

Java Spring侦听器容器-事务管理器-Spring重试-在多个事务中

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

我有一个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 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
?AFAIK
container.setDefaultRequeueRejected(false)将配置该行为。使用无状态(而不是有状态)重试侦听器进行内存内重试。