Apache Camel:具有属性和 属性 占位符的 RecipientList 不起作用

Apache Camel: RecipientList with properties and property placeholders not working

我正在尝试使用 The Camel Java DSL 将文件路由到 SFTP 服务器,如下所示:

.recipientList(simple("sftp://{{hostname}}:{{port}}/" + exchangeProperty(destinationDir) + "?username={{username}}&preferredAuthentications=publickey&privateKeyFile={{pkfilelocation}}&privateKeyPassphrase={{pkPassphrase}}"))

然而,当消息到达此端点时,Camel 抛出以下异常:

 org.apache.camel.component.file.GenericFileOperationFailedException: Cannot change directory to: exchangeProperty{destinationDir}
    at org.apache.camel.component.file.remote.SftpOperations.doChangeDirectory(SftpOperations.java:596)
    at org.apache.camel.component.file.remote.SftpOperations.changeCurrentDirectory(SftpOperations.java:584)
    at org.apache.camel.component.file.remote.SftpOperations.storeFile(SftpOperations.java:830)
    at org.apache.camel.component.file.GenericFileProducer.writeFile(GenericFileProducer.java:277)
    at org.apache.camel.component.file.GenericFileProducer.processExchange(GenericFileProducer.java:165)
    at org.apache.camel.component.file.remote.RemoteFileProducer.process(RemoteFileProducer.java:58)
    at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
    at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:110)
    at org.apache.camel.builder.NoErrorHandlerBuilder.process(NoErrorHandlerBuilder.java:40)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.MulticastProcessor.doProcessSequential(MulticastProcessor.java:695)
    at org.apache.camel.processor.MulticastProcessor.doProcessSequential(MulticastProcessor.java:623)
    at org.apache.camel.processor.MulticastProcessor.process(MulticastProcessor.java:247)
    at org.apache.camel.processor.RecipientList.sendToRecipientList(RecipientList.java:172)
    at org.apache.camel.processor.RecipientList.process(RecipientList.java:132)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
    at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:110)
    at org.apache.camel.builder.NoErrorHandlerBuilder.process(NoErrorHandlerBuilder.java:40)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:62)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145)
    at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.MulticastProcessor.doProcessSequential(MulticastProcessor.java:695)
    at org.apache.camel.processor.MulticastProcessor.doProcessSequential(MulticastProcessor.java:623)
    at org.apache.camel.processor.MulticastProcessor.process(MulticastProcessor.java:247)
    at org.apache.camel.processor.Splitter.process(Splitter.java:114)
    at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:97)
    at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:112)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:721)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:681)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:651)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:317)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:255)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1166)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1158)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1055)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)
Caused by: 2: No such file
    at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)
    at com.jcraft.jsch.ChannelSftp._realpath(ChannelSftp.java:2367)
    at com.jcraft.jsch.ChannelSftp.cd(ChannelSftp.java:342)
    at org.apache.camel.component.file.remote.SftpOperations.doChangeDirectory(SftpOperations.java:594)
    ... 53 more

我可以看到 destinationDir 属性 在堆栈跟踪中打印的交换上设置的。如果我更换

  • exchangeProperty(destinationDir) +

在具有实际目标目录 (tmp/destination/dir1/) 的路由中,它工作正常。问题是,我需要目标目录是动态的。我曾尝试在路线 (> 2.16.0) 中使用 ${exchangeProperty.destinationDir} 并在路线中使用 ${property.destinationDir} ,但都无济于事。 "non-exchange" 属性 占位符也都解析得很好。

在调试 Camel SFTP 库时,我可以看到 at SftpOperations.class:594,路径设置为 exchangeProperty{destinationDir}。 这没有被替换,这就是它失败的原因。

注意:我在 {{port}} 之后有 /(而不是在 destinationDir 属性),否则 Camel SFTP 组件会抛出异常说主机未定义。

有人对如何获取 属性 占位符和交换属性以动态使用 SFTP 有任何建议吗?我试过 toD("..") 也没有运气。

骆驼 2.19.0

我尝试了 .toD、.inOnly、.to、.recipientList 等的多种变体,但都没有成功。我确实找到了一个简单的解决方法,但是对于任何遭受同样挫折的人来说:

.process(new Processor() {
    @Override
    public void process(Exchange exchange) throws Exception {
        exchange.setProperty("myHackProperty", String.format("sftp://{{hostname}}:{{port}}/%s)", exchange.getProperty("dest‌‌​​inationDir")) 
    }
}

.recipientList(exchangeProperty("myHackProperty"))

简单的手动动态字符串替换。奇迹般有效。有时最好的编码骆驼的方法是避免骆驼 :)