简体   繁体   English

Apache Camel文件组件 - 如何仅扫描新文件?

[英]Apache Camel File Component - how to scan for new files only?

I set up a simple Apache Camel Route in Scala like this : 我在Scala中设置了一个简单的Apache Camel Route,如下所示:

import org.apache.camel.builder.RouteBuilder
import akka.actor.ActorRef
import akka.camel._

    class SimpleRouteBuilder(val responder: ActorRef) extends RouteBuilder  {
      def configure  {
        from("file:C:\\datafiles\\input?noop=true&readLock=changed").to(responder)
      }
    }

My question is how do I make this only scan for new files ? 我的问题是如何扫描新文件 Right now , it sends one message per every file in the directory. 现在,它为目录中的每个文件发送一条消息。 I want to have it in such a way that it only sends messages for files created after my camel application was started. 我想以这样的方式让它只发送我的camel应用程序启动创建的文件的消息。

Cheers ! 干杯!

UPDATE : 更新

OK I found a solution ... Implement a time stamp actor whose only purpose if to check if the ( file creation time > application start time ) and forward the file message to the round robin router. 好的我找到了一个解决方案...实现一个时间戳actor,其唯一目的是检查(文件创建时间>应用程序启动时间)并将文件消息转发给循环路由器。

The route is now : 现在的路线是:

 from(s"file:$directoryName?noop=true&readLock=changed&delay=$delay&recursive=true&include=$include").
  convertBodyTo(classOf[java.io.File]).to(timestampActor)

My code for the time stamp actor is approximately : 我的时间戳演员的代码是:

object TimestampActor {
  def apply(timeMillis0: Long): Props = Props(new TimestampActor(timeMillis0))
}

// timeMillis0 is the time when the application has started
class TimestampActor(timeMillis0: Long ) extends Actor {

  val messageRouterActor: ActorRef = context.system.actorFor(s"akka://${Constants.ActorSystemName}/user/${Constants.MessageRouterActorName}")
  val logger: Logger = LoggerFactory.getLogger(classOf[TimestampActor])


  def receive = {

      case camelMessage: CamelMessage => {
       // Need to unbox
        self ! camelMessage.body.asInstanceOf[java.io.File]
      }

      case file: File => {
        try {
          val attrs: BasicFileAttributes  = Files.readAttributes(file.toPath, classOf[BasicFileAttributes])
          if (attrs.creationTime().toMillis  >= timeMillis0) {
            // Forward the message to the Round Robin message router
            messageRouterActor ! file
          }
        }
        catch {
          case ioe:IOException => {
            logger.error(s"Failed to get creation time for file ${file.getCanonicalPath}", ioe)
            // Retry in 20 minutes
            import context.dispatcher
            context.system.scheduler.scheduleOnce(Duration.create(20, TimeUnit.MINUTES), self, file)

          }
        }
      }
  }

}

You need to use the idempotent option of the Apache Camel File Component . 您需要使用Apache Camel文件组件idempotent选项。 It will remember the already processed files and will only use the new ones. 它将记住已处理的文件,并仅使用新文件。 By default it will remember 1000 entries and the key will be the absolute path of the file but you can change it to what you need. 默认情况下,它会记住1000个条目,密钥将是文件的绝对路径,但您可以将其更改为您需要的内容。 It would be something like: 它会是这样的:

from("file:C:\\datafiles\\input?noop=true&readLock=changed&idempotent=true").to(responder)

Also you can use different types of Idempotent Repositories to do more fancy stuff. 此外,您可以使用不同类型的Idempotent存储库来做更多花哨的东西。

If you are concerned about losing the original file I would suggest that you use multicast. 如果您担心丢失原始文件,我建议您使用多播。 This way you could send a copy of the file to a backup folder. 这样,您可以将文件的副本发送到备份文件夹。

from("file:C:\\datafiles\\input").multicast().to("backuplocation", "responder");

By default camel will process any file that is placed in the input folder 默认情况下,camel将处理放置在输入文件夹中的任何文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM