Apache camel ftp使用者异常后聚合:FatalFallbackErrorHandler

Apache camel ftp使用者异常后聚合:FatalFallbackErrorHandler,apache-camel,sftp,Apache Camel,Sftp,我的驼峰路由尝试从sftp中提取一些文件,将它们传输到网络,然后从sftp中删除它们。如果3次尝试后无法访问sftp,我希望路由发送一封电子邮件,警告管理员该问题 因此,我的sftp地址具有以下参数: maximumReconnectAttempts=2&throwExceptionOnConnectFailed=true&consumer.bridgeErrorHandler=true 如果网络位置不可用,我希望路由通知管理员并不从sftp中删除文件。 因此,我在OneExc

我的驼峰路由尝试从sftp中提取一些文件,将它们传输到网络,然后从sftp中删除它们。如果3次尝试后无法访问sftp,我希望路由发送一封电子邮件,警告管理员该问题

因此,我的sftp地址具有以下参数:

maximumReconnectAttempts=2&throwExceptionOnConnectFailed=true&consumer.bridgeErrorHandler=true
如果网络位置不可用,我希望路由通知管理员并从sftp中删除文件。 因此,我在OneException中设置了.handled(false)

然而,当连接到sftp失败时,聚合也会失败,并且没有电子邮件出现。我在下面举了一个极简主义的例子:

/configure
  onException(Throwable.class)
    .retryAttemptedLogLevel(LoggingLevel.WARN)
    .redeliveryDelay(1000)
    .handled(false)
    .log(LoggingLevel.ERROR, LOG, "XXX - Error moving files")
    .to(AGGREGATEROUTE)
    .end();

  from(downloadFrom)
  .to(to)
  .log(LoggingLevel.INFO, LOG, "XXX - Moving file OK")
  .to(AGGREGATEROUTE);

  from(AGGREGATEROUTE)
  .log(LoggingLevel.INFO, LOG, "XXX - Starting aggregation.")
  .aggregate(constant(true), new GroupedExchangeAggregationStrategy())
      .completionFromBatchConsumer()
      .completionTimeout(10000)
  .log(LoggingLevel.INFO, LOG, "XXX - Aggregation completed, sending mail.");
在日志中,我看到:

16:02| ERROR | CamelLogger.java 156 | XXX - Error moving files
然后查看连接期间发生的异常的日志

然后这个:

16:02| ERROR | FatalFallbackErrorHandler.java 174 | Exception occurred while trying to handle previously thrown exception on exchangeId: ID-LP0641-1552662095664-0-2 using: [Pipeline[[Channel[Log(proefjes.camel_cursus.routebuilders.MoveWithPickupExceptions)[XXX - Error moving files]], Channel[sendTo(direct://aggregate)]]]].
16:02| ERROR | FatalFallbackErrorHandler.java 172 | \--> New exception on exchangeId: ID-LP0641-1552662095664-0-2
   org.apache.camel.component.file.GenericFileOperationFailedException: Cannot connect to sftp://user@mycompany.nl:22
    at org.apache.camel.component.file.remote.SftpOperations.connect(SftpOperations.java:149)

我没有在日志中看到“XXX-正在启动聚合”。聚合之前是否发生了某种错误?聚合(*,*)上的断点从未到达。

首先,我只想澄清一些事情。你写“如果网络位置不可用,我希望路由通知管理员,而不是从sftp中删除文件”,但这不是显而易见的吗?我的意思是,如果网络位置不可用,那么从sftp中删除文件不是不可能的吗

异常处理程序也将
路由到(AGGREGATEROUTE)
,这有点令人困惑。如果你想给管理员发电子邮件,那不应该在异常处理程序中,而不是在快乐路径中吗?为什么要以及如何“聚合”连接失败

最后,我认为您的实现存在一个真正的问题,您可能误解了
处理(false)
的功能。将此设置为false意味着路由应该停止并传播返回给调用方的异常。我不确定在这种情况下必须使用
.to(AGGREGATEROUTE)
做什么,但我并不奇怪它没有被调用

我建议尝试一些东西。我没有你的代码,所以我不确定哪一个最好。这些都是相关的,任何方法都可能奏效:

  • handled(false)
    更改为
    handled(true)
  • continued(true)
    替换
    handled
  • 使用死信频道
参考:


由于错误处理取决于导致错误的端点,因此我通过使用两种不同版本的OneException解决了这个问题:

     //configure exception on sft end
    onException(Throwable.class)
    .maximumRedeliveries(2)
    .retryAttemptedLogLevel(LoggingLevel.WARN)
    .redeliveryDelay(1000)
    .onWhen(new hasSFTPErrorPredicate())
     // .continued(true) //  tries to connect once, mails and continues to aggregation with empty exchange
    //.handled(false) // tries to connect twice but does not reach mail
      .handled(true)  // tries to connect once, does reach mail
    // handled not defined: tries to connect twice but does not reach mail
      .log(LoggingLevel.INFO, LOG, "XXX - SFTP exception")
      .to(MAIL_ROUTE)
      .end();

   // exception anywhere else
    onException(Throwable.class)
     .maximumRedeliveries(2)
     .retryAttemptedLogLevel(LoggingLevel.WARN)
     .redeliveryDelay(1000)
     .log(LoggingLevel.ERROR, LOG, "XXX - Error moving file ${file:name}: ${exception}")
     .to(AGGREGATEROUTE)
     .handled(false)
     .end();
在sftp端发生的异常在第一个OneException中处理,因为在那里HassftPerorPredicate返回“true”。该谓词所做的只是检查消息中是否存在异常或其原因为“无法连接到sftp:”。 在这种情况下不需要回滚,因为还没有发生任何事情


任何其他异常都由第二个OneException处理。

任何一端都可能不可用,如果to端点不可用,我希望回滚,因此我已处理(错误),我更喜欢聚合,因此我不会为无法传递的每个文件都收到电子邮件。在任何情况下,我都不想接受异常,据我所知,handled(true)就是这样做的。我可以继续,但如何确保不删除任何文件?