Apache Camel JMS组件:bridgeErrorHandler无法按记录工作

时间:2019-10-16 07:29:00

标签: java spring-boot apache-camel

问题

您好,我尝试通过使用标志bridgeErrorHandler=true但使用{{1},将JMS使用者的错误处理桥接到DLC我的骆驼路线的错误处理程序,该骆驼路线是DLC。 },当我使用一条消息时,它不会由DLC JMSException处理,而是由ErrorHandler处理,因此仅被记录和忽略。

在我的DLC中,我配置了当异常发生时应该执行的附加步骤,但现在却被忽略了。 也许您可以告诉我我做错了什么?

以下是详细信息:

项目设置

我正在使用:

  • spring-boot:2.1.0.RELEASE
  • Apache骆驼:2.23.3
  • camel-jms-starter:2.23.3

路线:

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 bean

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

3 个答案:

答案 0 :(得分:1)

好的,我们在Camel 3上对此进行了改进,您可以在其中打开eagerLoadingOfProperties(组件级别或每个端点),然后将检测到此类JMS有效负载错误,并使用异常消息设置消息主体;您可以对其进行配置,以及在Exchange上引起的异常。这样一来,骆驼的路由错误处理程序就可以将其检测为异常并路由至死信通道。

查看JIRA票证:https://issues.apache.org/jira/browse/CAMEL-14083

答案 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