Camel文件组件在失败时不会移动但会保持文件锁定

时间:2017-03-14 15:03:22

标签: java file apache-camel

我创建了一个读取xml的camel路由,并在ActiveMQ-Queue中为xml中的每个元素放置一条消息。一切正常,但错误处理不起作用。这是路线:

@Override
public void configure() throws Exception {
    from(fileIn)
        .routeId(IN_ROUTE_ID)
        .onCompletion()
            .to(CommonRoutes.ENDPOINT_DIRECT_LOGGING)
        .end()
        .onException(UncategorizedJmsException.class)
            .maximumRedeliveries(maxRetries)
            .backOffMultiplier(multiplier)
            .redeliveryDelay(initialDelay)
        .end()
        .unmarshal(jaxbDataFormat)
        .process(fileProcessor)
        .split(body()).stopOnException().shareUnitOfWork()
        .process(domainWrapProcessor)
        .to(ACTIVE_MQ_OUT + ":queue:" + checkNotNull(queueName))
    .end()
    ;
}

这里是FileEndpoint的配置:

public void init(){
    this.setAutoCreate(false);
    this.setFile(new File(checkNotNull(csvFolder)));
    this.setCamelContext(checkNotNull(context));
    this.setAntInclude(ANT_INCLUDE);
    this.setMove(doneFolder);
    this.setMoveFailed(errorFolder);
}

目的是在每个异常上将文件移动到moveFailed文件夹,并且在JMSException(ActiveMQ离线)的情况下,camel应该重试,如果最终失败也会移动到moveFailed。

我已经为这两种情况创建了单元测试。这是任何例外的测试:

@Test
public void testException throws InterruptedException {
    amqMmock.setExpectedMessageCount(3);
    amqMock.whenAnyExchangeReceived((e) -> {
        throw new RuntimeException("");
    });
    assertMockEndpointsSatisfied();

    Thread.sleep(1000);
    errorContainsFile(true);
}

此测试是将文件传递到错误文件夹集中。但是,如果我真实地运行这条路线(保险丝上的骆驼蓝图),这是行不通的:

问题是在任何(不是UncategorizedJmsException)异常上,文件只是保持锁定(创建.camelLock文件)。 (感谢stopOnException,JMSExceptions所需的行为正在运行) 那么如何让camel将文件移动到moveFailed文件夹上的任何异常?

1 个答案:

答案 0 :(得分:0)

据我所知,如果文件组件本身出现问题({至少我经历过的话),moveFailed实际上只会将文件移动到error-dir。这可以解释为什么在遇到异常时你的文件没有被移动到error-dir。

你可以尝试做的事情可能是这样的:

.onException(UncategorizedJmsException.class)
    .maximumRedeliveries(maxRetries)
    .backOffMultiplier(multiplier)
    .redeliveryDelay(initialDelay)
    .to(errorFolder)
.end()

以下是我如何使用蓝图与XML而不是Java DSL建立您的路线(嗯,粗略地说,只是为了得到它的要点):

<!-- Redelivery Policy -->
<bean id="redeliveryPolicyConfig" class="org.apache.camel.processor.RedeliveryPolicy">
    <property name="maximumRedeliveries" value="${redelivery.max.attempts}" />
    <property name="redeliveryDelay" value="${redelivery.delay.ms}" />
    <property name="logRetryAttempted" value="${redelivery.log.attempts}" />
</bean>

<!-- Error Handler -->
<bean id="errorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
    <property name="deadLetterUri" value="direct:error" />
    <property name="useOriginalMessage" value="true" />
    <property name="redeliveryPolicy" ref="redeliveryPolicyConfig" />
</bean>

<camelContext>
    <route id="IN_ROUTE_ID">
        <from uri="file://{{fileIn}}?move={{doneFolder}}&amp;moveFailed={{errorFolder}}" />
        ...
        <to uri="activemq:queue:{{queueName}}" />
    </route>

    <route id="error-route">
        <from uri="direct:error" />
        <to uri="file://{{errorFolder}}" />
    </route>
</camelContext>