Spring integration 将消息从处理程序回滚到通道

Spring integration 将消息从处理程序回滚到通道,spring-integration,Spring Integration,我正在尝试为将在SI流中使用的所有消息处理程序创建一个通用错误处理过程。这将,, 1.连接异常时重试。 2.使用断路器停止SI流。 3.将失败的消息回滚到通道 我已经实现了重试和断路功能。但是,我无法将消息回滚到频道。 我尝试使用交易建议。但它不起作用 这是代码 <bean id="retryAdvice" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">

我正在尝试为将在SI流中使用的所有消息处理程序创建一个通用错误处理过程。这将,, 1.连接异常时重试。 2.使用断路器停止SI流。 3.将失败的消息回滚到通道

我已经实现了重试和断路功能。但是,我无法将消息回滚到频道。 我尝试使用交易建议。但它不起作用

这是代码

<bean id="retryAdvice"
    class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">
    <property name="retryTemplate">
        <bean class="org.springframework.retry.support.RetryTemplate">
            <property name="backOffPolicy">
                <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
                    <property name="initialInterval" value="2000" />
                    <property name="multiplier" value="2" />
                </bean>
            </property>
        </bean>
    </property>
    <property name="recoveryCallback">
        <bean
            class="org.springframework.integration.handler.advice.ErrorMessageSendingRecoverer">
            <constructor-arg ref="recoveryChannel" />
        </bean>
    </property>
    <property name="retryStateGenerator">
        <bean
            class="org.springframework.integration.handler.advice.SpelExpressionRetryStateGenerator">
            <constructor-arg value="headers['uniqueId']" />
        </bean>
    </property>
</bean>

<int:channel id="recoveryChannel" />
<int:transformer id="defaultTransformer" input-channel="recoveryChannel"
    output-channel="loggerChannel" ref="defaultTransformer" method="transform">
</int:transformer>

<int:logging-channel-adapter id="loggerChannel"
    level="INFO" log-full-message="true" auto-startup="true">
</int:logging-channel-adapter>

<bean id="defaultTransformer"
    class="com.bestbuy.ingestion.foundation.core.util.DefaultTransformer" />

<bean id="circuitBreakerAdvice"
    class="org.springframework.integration.handler.advice.RequestHandlerCircuitBreakerAdvice">
    <property name="threshold" value="2" />             <!-- close after 2 failures -->
    <property name="halfOpenAfter" value="60000" />     <!-- half open after 15 seconds -->
</bean>

<tx:advice id="txansactionAdvice" transaction-manager="transactionManager">
</tx:advice>

我需要使用哪种类型的事务管理器。 我可能在不同的数据源上使用不同的消息处理程序

下面是我如何将这些建议添加到消息处理程序中的

public Object postProcessBeforeInitialization(Object bean, String beanName)
        throws BeansException {

    logger.error("called for bean id :: "+beanName+" with bean class "+bean.getClass().getName());
    if(bean instanceof AbstractSimpleMessageHandlerFactoryBean){
        logger.error("************ Bean "+beanName+" is instance of AbstractSimpleMessageHandlerFactoryBean **********");
    }
    if(bean instanceof ConsumerEndpointFactoryBean){
        logger.error("Bean is of type ConsumerEndpointFactoryBean");
        return populateRequestHandlerAdviceChain((ConsumerEndpointFactoryBean)bean);
    }
    if(bean instanceof AbstractSimpleMessageHandlerFactoryBean){
        logger.error("Bean is of type AbstractSimpleMessageHandlerFactoryBean");
        return populateRequestHandlerAdviceChain((AbstractSimpleMessageHandlerFactoryBean<?>)bean);
    }
    return bean;
}
private Object populateRequestHandlerAdviceChain(ConsumerEndpointFactoryBean bean){
    ArrayList<Advice> list = new ArrayList<Advice>();
    logger.error("Adding Retry Advice");
    list.add((Advice)factory.getBean("retryAdvice"));
    logger.error("Adding Cricuit Breaker Advice");
    list.add((Advice)factory.getBean("circuitBreakerAdvice"));
    logger.error("Adding Transactional Advice");
    list.add((Advice)factory.getBean("txansactionAdvice"));
    bean.setAdviceChain(list);
    return bean;
}
初始化前的公共对象后处理(对象bean、字符串bean名称)
抛出BeansException{
错误(“调用bean id::“+beanName+”和bean类“+bean.getClass().getName()”);
if(AbstractSimpleMessageHandlerFactoryBean的bean实例){
logger.error(“************Bean”+beanName+”是AbstractSimpleMessageHandlerFactoryBean*********”的实例);
}
if(ConsumerEndpointFactoryBean的bean实例){
错误(“Bean的类型为ConsumerEndpointFactoryBean”);
返回populateRequestHandlerAdviceChain((ConsumerEndpointFactoryBean)bean);
}
if(AbstractSimpleMessageHandlerFactoryBean的bean实例){
error(“Bean的类型为AbstractSimpleMessageHandlerFactoryBean”);
返回populateRequestHandlerAdviceChain((AbstractSimpleMessageHandlerFactoryBean)bean);
}
返回豆;
}
私有对象populateRequestHandlerAdviceChain(ConsumerEndpointFactoryBean){
ArrayList=新建ArrayList();
logger.error(“添加重试建议”);
add((Advice)factory.getBean(“retryAdvice”);
记录器错误(“添加断路器建议”);
添加((Advice)factory.getBean(“circuitBreakerAdvice”);
logger.error(“添加事务通知”);
add((Advice)factory.getBean(“txansactionAdvice”);
setAdviceChain(列表);
返回豆;
}

如果类型为ConsumerEndpointFactoryBean的bean,我会添加这些建议。我需要在所有这些处理程序中进行事务管理。

首先:由于您的
txansactionAdvice
嵌套在
retryAdvice
中,因此每次重试都要在这里回滚

public Object postProcessBeforeInitialization(Object bean, String beanName)
        throws BeansException {

    logger.error("called for bean id :: "+beanName+" with bean class "+bean.getClass().getName());
    if(bean instanceof AbstractSimpleMessageHandlerFactoryBean){
        logger.error("************ Bean "+beanName+" is instance of AbstractSimpleMessageHandlerFactoryBean **********");
    }
    if(bean instanceof ConsumerEndpointFactoryBean){
        logger.error("Bean is of type ConsumerEndpointFactoryBean");
        return populateRequestHandlerAdviceChain((ConsumerEndpointFactoryBean)bean);
    }
    if(bean instanceof AbstractSimpleMessageHandlerFactoryBean){
        logger.error("Bean is of type AbstractSimpleMessageHandlerFactoryBean");
        return populateRequestHandlerAdviceChain((AbstractSimpleMessageHandlerFactoryBean<?>)bean);
    }
    return bean;
}
private Object populateRequestHandlerAdviceChain(ConsumerEndpointFactoryBean bean){
    ArrayList<Advice> list = new ArrayList<Advice>();
    logger.error("Adding Retry Advice");
    list.add((Advice)factory.getBean("retryAdvice"));
    logger.error("Adding Cricuit Breaker Advice");
    list.add((Advice)factory.getBean("circuitBreakerAdvice"));
    logger.error("Adding Transactional Advice");
    list.add((Advice)factory.getBean("txansactionAdvice"));
    bean.setAdviceChain(list);
    return bean;
}
从另一方面看,不清楚为什么每次重试都要应用
circuitBreakerAdvice
。我想说这种模式最好使用“around”
retryAdvice

txansactionAdvice
应该位于顶部。所以,它可能看起来像这样:

txansactionAdvice
circuitBreakerAdvice
retryAdvice
还有一点:您的事务不会回滚,因为您使用的是
recoveryCallback
,它只会发送
ErrorMessage
并扼杀异常


你会改变主意的。

请展示一下你是如何应用这些
建议的。
端点
配置。
TransactionManager
应该是一个
PlatformTransactionManager
Hi-Artem,用代码更新了问题。感谢Artem,这很有用。现在我没有看到任何消息丢失。