请参阅附图进行设置。以下说明。
有一个公共输入通道可以接收请求。从这个输入通道,有两个流:
流1-将请求存储到DB
流程2-将业务处理/转发请求发送到其他外部系统
我希望流程1和流程2彼此独立。因此,我将流程1放在执行程序通道上。这样,流程1中的错误不会中断流程2。
流程1的说明:
我所拥有的:
在绿色框中的代码中,我定义了ExpressionEvaluatingRequestHandlerAdvice,以便将执行程序通道上的任何错误发送到错误通道。我假设ExpressionEvaluatingRequestHandlerAdvice将自动应用于执行者通道。
相反,如果出现错误,它将被重新发布到“公共输入通道”并重复处理,直到队列填满。
我需要什么
我希望将执行程序通道上的任何错误发送到错误通道,在该通道中将对其进行静默记录并处理消息。
从公用输入通道读取并在执行器通道上读取的代码:
@Configuration
@EnableIntegration
public class InputChanneltoExecutorChannelConfig {
//DEFINING THE EXECUTOR CHANNEL
@Bean
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
@Bean(name="executorChannelToDB")
public ExecutorChannel outboundRequests() {
return new ExecutorChannel(taskExecutor());
}
//DEFINE FAILURE CHANNEL FOR USE IN ExpressionEvaluatingRequestHandlerAdvice
@Bean(name = "DBFailureChannel")
public static MessageChannel getFailureChannel() {
return new DirectChannel();
}
//MAIN METHOD THAT READS FROM INPUT CHANNEL AND SENDS TO EXECUTOR CHANNEL
@Bean
public IntegrationFlow outboundtoDB() {
return IntegrationFlows
.from("commonInputChannel")
/*
* We publish the msg to be stored into the DB onto a executor
* channel (so that the DB operation is processed on a separate
* thread).
*/
.channel("executorChannelToDB").get();
/****************************************************************************
*********************************************************
* How do I route the error from executor channel to error channel over here?
**********************************************************
****************************************************************************/
}
/*
* Create an advice bean to handle DB errors. In case of failure, send
* response to a separate channel.
*/
@Bean
public ExpressionEvaluatingRequestHandlerAdvice expressionAdvice() {
ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
advice.setFailureChannelName("DBFailureChannel");
advice.setOnFailureExpressionString("'##Error while storing request into DB'");
advice.setTrapException(true);
return advice;
}
/*
* We create a separate flow for DB failure because in future we may need
* other actions such as retries/notify support in addition to logging.
*/
@Bean
public IntegrationFlow failure() {
return IntegrationFlows.from("DBFailureChannel")
.channel("errorChannel").get();
}
}
更新: 按照加里的建议,更新了ERROR_CHANNEL和REPLY_CHANNEL。
@Bean
public IntegrationFlow outboundtoDB() {
return IntegrationFlows
.from("commonInputChannel")
//Setting Headers
.enrichHeaders(h -> h.header(MessageHeaders.ERROR_CHANNEL, "errorChannel", true))
.enrichHeaders(h -> h.header(MessageHeaders.REPLY_CHANNEL, "DBSuccessChannel", true))
.channel("executorChannelToDB").get();
DBSuccess通道设置为处理如下响应:
@Bean
public IntegrationFlow success() {
return IntegrationFlows
.from("DBSuccessChannel")
.wireTap(
flow -> flow.handle(msg -> logger
.info("Response from storing in DB : "
+ msg.getPayload()))).get();
}
但是我仍然会收到错误消息,
2018-09-26 23:34:47.398错误17186 --- [SimpleAsyncTaskExecutor-465] o.s.integration.handler.LoggingHandler: org.springframework.messaging.MessageHandlingException:嵌套 异常是java.time.format.DateTimeParseException:文本'sample “创建时间戳记”无法在索引0处解析, failedMessage = GenericMessage [payload=com.td.sba.iep.schema.InstructionRs@37919153, 标头= {errorChannel = errorChannel, jms_destination = commonInputChannel ,Solace_JMS_Prop_IS_Reply_Message = false,优先级= 0, jms_timestamp = 1538018141672,JMS_Solace_isXML = true, replyChannel = DBSuccessChannel,jms_redelivered = true, JMS_Solace_DeliverToOne = false,JMS_Solace_ElidingEligible = false, JMS_Solace_DeadMsgQueueEligible = false, id = ff6c2ea6-b6d6-c67a-7943-6b7db33bb977, jms_messageId = ID:49.37.4.163d608166190664e70:0, timestamp = 1538019287394}]
在这里,仍然将jms_destination设置为输入通道,并且错误不断被重新发布到commonInputChannel。 你能帮忙吗?
答案 0 :(得分:0)
该建议将无济于事,因为它仅适用于该终结点-不适用于下游流,无论如何,即使这样做,也将成功移交给执行程序,并且所有下游异常均由执行程序处理(并用ErrorHandlingTaskExecutor
包装在MessagePublishingErrorHandler
中。
尝试用标题增强器替换该组件,然后设置errorChannel
标题。或者,您也可以使用配置了错误通道的MPEH自己包装TE(执行程序通道将检测到TE已经是EHTE)。
编辑
这对我来说很好...
@SpringBootApplication
public class So52526134Application {
public static void main(String[] args) {
SpringApplication.run(So52526134Application.class, args);
}
@Bean
public IntegrationFlow mainFlow() {
return IntegrationFlows.from(() -> "foo", e -> e.poller(Pollers.fixedDelay(5000)))
.enrichHeaders(h -> h.header(MessageHeaders.ERROR_CHANNEL, "myErrors.input"))
.channel(MessageChannels.executor(executor()))
.handle((p, h) -> {
throw new RuntimeException("foo");
})
.get();
}
@Bean
public IntegrationFlow myErrors() {
return f -> f.handle((p, h) -> {
System.out.println("in my error flow");
return p;
})
.handle(System.out::println);
}
@Bean
public TaskExecutor executor() {
return new ThreadPoolTaskExecutor();
}
}
和
in my error flow
ErrorMessage [payload=org.springframework.messaging.MessageHandlingException: ...