您好,我尝试通过使用标志bridgeErrorHandler=true
但使用{{1},将JMS使用者的错误处理桥接到DLC我的骆驼路线的错误处理程序,该骆驼路线是DLC。 },当我使用一条消息时,它不会由DLC JMSException
处理,而是由ErrorHandler
处理,因此仅被记录和忽略。
在我的DLC中,我配置了当异常发生时应该执行的附加步骤,但现在却被忽略了。 也许您可以告诉我我做错了什么?
以下是详细信息:
我正在使用:
DefaultSpringErrorHandler
端点本身是在@Component
public class BridgeErrorHandlerTestQuellRoute extends RouteBuilder{
private static final String ROUTE_ALIAS = "BridgeErrorHandlerTestQuellRoute";
public static final String ENDPOINT_QUELLE = "{{BridgeErrorHandlerTestQuelle}}";
@Override
public void configure() {
errorHandler(deadLetterChannel(DLCRoute.ENDPOINT_DLC));
// @formatter:off
from(ENDPOINT_QUELLE).routeId(ROUTE_ALIAS)
.removeHeaders("*", "JMS*") // Entfernt alle nicht notwendigen JMS-Header
.log(INFO, log, "Start Route: ${routeId}")
.to("mock:mymock")
.log(INFO, log, "Ende Route: ${routeId}")
// @formatter:on
}
}
中定义的(尽管我必须更改主题名称):
application.properties
connectionfactory适用于IBM MQ:
topic.props=subscriptionShared=true&\
transacted=true&\
recoveryInterval=-1&\
connectionFactory=#connectionFactory&\
bridgeErrorHandler=true
BridgeErrorHandlerTestQuelle=jms:topic:IBMMQSERVER/AT/ALL/MYTOPIC?durableSubscriptionName=BridgeErrorHandlerTest.bridgeerrorhandlertest&${topic.props}
该异常发生在:
@Bean
public ConnectionFactory connectionFactory() {
try {
MQConnectionFactory factory = new MQConnectionFactory();
factory.setHostName(properties.getHost());
factory.setPort(properties.getPort());
factory.setQueueManager(properties.getQueueManager());
factory.setChannel(properties.getChannel());
factory.setStringProperty(WMQConstants.USERID, properties.getUser());
factory.setStringProperty(WMQConstants.PASSWORD, properties.getPassword());
factory.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
return factory;
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
并且是com.ibm.msg.client.wmq.common.internal.WMQUtils#computeTextFromBytes(byte[], int, int, com.ibm.mq.jmqi.system.JmqiCodepage)
DetailedJMSException
答案 0 :(得分:1)
好的,我们在Camel 3上对此进行了改进,您可以在其中打开eagerLoadingOfProperties(组件级别或每个端点),然后将检测到此类JMS有效负载错误,并使用异常消息设置消息主体;您可以对其进行配置,以及在Exchange上引起的异常。这样一来,骆驼的路由错误处理程序就可以将其检测为异常并路由至死信通道。
答案 1 :(得分:0)
之后
onException
和特定于路由onException
的定义)我发现使用 camel-jms-starter:2.23.x 和 camel-jms-starter:2.24.x 该问题无法解决,因为我要保留transacted=true
标志。我认为 camel-jms-starter 中的只是一个错误,发生的异常不是由我配置的Route-ErrorHandler处理的,但是我无法更改。
所以对我来说,当前的解决方案是在链接的MQ-Broker中建立 Poison-Message 机制。这样,我就摆脱了无限循环,可以将消息路由到另一个队列。
修改:
即使我不太喜欢它,也可以在路由中内置一个解决方案。如果我在路由中添加一个定制的处理器,它仅在主体转换期间捕获异常,则将触发我配置的errorHandler,并且由于它是DLC错误处理程序,因此消息已成功使用,并且我没有无限循环。注意:使用convertBodyTo
会导致与问题中提到的行为相同的意外行为,因为它使用相同的API。
处理器之所以起作用,是因为在此之前交换主体尚未被触摸。
这是代码:
更改的路线:
@Override
public void configure() {
errorHandler(deadLetterChannel(DLCRoute.ENDPOINT_DLC));
// @formatter:off
from(ENDPOINT_QUELLE).routeId(ROUTE_ALIAS)
.removeHeaders("*", "JMS*")
.process(myCustomConverter)
.log(INFO, log, "Start Route: ${routeId}")
.to("mock:mymock")
.log(INFO, log, "Ende Route: ${routeId}")
// @formatter:on
}
这是myCustomConverter
bean(具有虚拟实现):
@Component
public class MyCustomConverter implements Processor {
private static final Logger LOG = LoggerFactory.getLogger(MyCustomConverter.class);
@Override
public void process(Exchange exchange) throws Exception {
try {
exchange.getIn().getBody(String.class);
} catch( Exception ex) {
LOG.error("Logging for the error");
exchange.getIn().setBody(""); // TODO: Do something which makes sense
}
}
}
我不喜欢这种解决方法的原因是,在将来的版本中,框架可能会很好地处理相同的情况,因此我必须对代码进行更改以删除此解决方法。所以对我来说,泊松消息配置是必经之路。
答案 2 :(得分:0)
将主体转换从 jms 消费者端点转移到路由流也对我有帮助。
在 jms 消费者中设置 mapJmsMessage=false
并添加
.setBody().method(SimpleMessageConverter.class, "fromMessage")
进入路由流工作正常。
我是说org.springframework.jms.support.converter.SimpleMessageConverter