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