Apache camel Apache camel sftp org.Apache.camel.NoTypeConversionAvailableException:没有可用于转换java.io.InputStream的类型转换器
目前由于类型转换,我一直在从ftp服务器下载文件 因此,下面提到的路由是从一个管道中调用的,该管道的主体已经设置了我的自定义POJO。自定义pojo如下所示:Apache camel Apache camel sftp org.Apache.camel.NoTypeConversionAvailableException:没有可用于转换java.io.InputStream的类型转换器,apache-camel,camel-ftp,Apache Camel,Camel Ftp,目前由于类型转换,我一直在从ftp服务器下载文件 因此,下面提到的路由是从一个管道中调用的,该管道的主体已经设置了我的自定义POJO。自定义pojo如下所示: public class DirectoryLocationListing { private String domainName; private String countryCode; private String productName; private String profileId;
public class DirectoryLocationListing {
private String domainName;
private String countryCode;
private String productName;
private String profileId;
private String directoryLocation;
sftp的路径如下所示,其中我从特定服务器的目录获取所有文件,并将它们保留在本地文件路径上
<route id="route5">
<from uri="direct:sftpGetCDRs"/>
<from uri="sftp://{{HOST}}//home/admin/ROSS_PULL_CDR/resellers/${body.directoryLocation}/?noop=true&streamDownload=true&username={{USER}}&password={{PASSWD}}"/>
<to uri="file://{{DB_DIR_LOC}}/temp/?fileName=${body.directoryLocation}/&autoCreate=true"/>
</route>
如果有人遇到同样的问题,请提供指导。
所以类型转换可能是必需的,但我认为在这种情况下不需要
**更新**
使用Poll后,我的路线如下:
<route id="route5">
<from uri="direct:sftpGetCDRs"/>
<process ref="sftpGetDirLocation"/>
<log message="property ${exchangeProperty.ftpGetDirectory}"/>
<pollEnrich uri="sftp://{{HOST}}//home/admin/ROSS_PULL_CDR/resellers/${exchangeProperty.ftpGetDirectory}/?noop=true&streamDownload=true&username={{USER}}&password={{PASSWD}}" timeout="0"/>
<to uri="file://{{DB_DIR_LOC}}/temp/?fileName=${body.directoryLocation}/&autoCreate=true"/>
</route>
然而,我的假设是,在这次更改之后,它将保留它从URI获得的用于sftp的任何内容(可能是文件),并将其作为主体保留。
相反,我看到身体是空的
Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[_route1 ] [_route1 ] [quartz2://spring?cron=0+*+*+%3F+*+* ] [ 657]
[_route2 ] [_choice1 ] [when[simple{${body.domainName} != null and ${body.countryCode} !=
null] [ 572]
[_route2 ] [_to4 ] [bean:pullCDRProcessorWithFTP?method=createTemporaryDirectoryWithDirLoc ] [ 2]
[_route2 ] [_log6 ] [log ] [ 7]
[_route2 ] [_to4 ] [direct:sftpGetCDRs ] [ 523]
[route5 ] [process1 ] [ref:sftpGetDirLocation ] [ 0]
[route5 ] [log1 ] [log ] [ 1]
[route5 ] [pollEnrich1 ] [pollEnrich[sftp://10.91.142.11//home/admin/ROSS_PULL_CDR/resellers/${exchangeP] [ 514]
[route5 ] [log2 ] [log ] [ 0]
[route5 ] [to1 ] [file://C:/EXAMPLE/export/home/resellerid/wmcdr/cdr/temp/?fileName=${body.director] [ 0]
Exchange
---------------------------------------------------------------------------------------------------------------------------------------
Exchange[
Id ID-IGL70051-57920-1550721464331-0-4
ExchangePattern InOnly
Headers {breadcrumbId=ID-IGL70051-57920-1550721464331-0-1, calendar=null, CamelFileName=null, CamelRedelivered=false, CamelRedeliveryCounter=0, CamelToEndpoint=sftp://10.91.142.11//home/admin/ROSS_PULL_CDR/resellers/$%7BexchangeProperty.ftpGetDirectory%7D/?noop=true&password=tcpip123&streamDownload=true&username=admin, fireTime=Thu Feb 21 09:28:00 IST 2019, jobDetail=JobDetail 'Camel_camelContext-f6f63d02-4688-4b3f-b3ca-b206a61cbe9f.spring': jobClass: 'org.apache.camel.component.quartz2.CamelJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false, jobInstance=org.apache.camel.component.quartz2.CamelJob@363935fd, jobRunTime=-1, mergedJobDataMap=org.quartz.JobDataMap@f7fbba19, nextFireTime=Thu Feb 21 09:29:00 IST 2019, previousFireTime=null, refireCount=0, result=null, scheduledFireTime=Thu Feb 21 09:28:00 IST 2019, scheduler=org.quartz.impl.StdScheduler@5bf7fd08, trigger=Trigger 'Camel_camelContext-f6f63d02-4688-4b3f-b3ca-b206a61cbe9f.spring': triggerClass: 'org.quartz.impl.triggers.CronTriggerImpl calendar: 'null' misfireInstruction: 1 nextFireTime: Thu Feb 21 09:29:00 IST 2019, triggerGroup=Camel_camelContext-f6f63d02-4688-4b3f-b3ca-b206a61cbe9f, triggerName=spring}
BodyType null
Body [Body is null]
]
因此,例外情况是
Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
org.apache.camel.component.file.GenericFileOperationFailedException: Cannot write null body to file: C:\EXAMPLE\export\home\resellerid\wmcdr\cdr\temp
at org.apache.camel.component.file.FileOperations.storeFile(FileOperations.java:205)
在我看来,代码中有三个问题
route5
发送类型为DirectoryLocationListing
的交换,您希望sftp
组件将该消息与来自定义的第二条一起使用。它坏了。当SFTP
组件下载文件时,exchange上的主体将被实际文件(类型为org.apache.camel.component.file.GenericFile
)替换,并且您将丢失上一次交换中的DirectoryLocationListing
对象。如果您的pojo cam设置在车身以外的其他位置,这是一个很好的选择
sftp
端点获得一个文件,但实际交付给您的是与DirectoryLocationListing
类型的主体进行的交换(您的sftp组件不起作用)。对于Camel来说,没有办法做到这一点并将其持久化到磁盘。这正是它所抱怨的
2.1。一旦您解决了这个问题(并且您的SFTP组件开始工作),您将遇到下一种情况,即传递到to
端点的消息现在是一个文件,您需要以某种方式在exchange中保留directoryLocation
,直到路由结束to
定义中的fileName
参数指向目录。这行不通。您必须使用动态端点定义文件
组件。我们将尝试一次性解决所有这些问题
路线定义
from("direct:test")
.routeId("route5")
.log("=> body.directoryLocation is: ${body.directoryLocation}") //Just to see if we can read the directoryLocation property from the POJO
.process(exchange -> exchange.setProperty("WriteTargetDirectory",exchange.getIn().getBody(DirectoryListing.class).directoryLocation)) //Move directoryLocation property to an exchange property named WriteTargetDirectory
.pollEnrich()
.simple("file://source/${exchangeProperty.WriteTargetDirectory}/?noop=true")//Poll enrich magic here!
.log("=> I still have the target directory location as : ${exchangeProperty.WriteTargetDirectory}")
.log("=> I just received file [${in.header." + Exchange.FILE_NAME + "}] and will write it as [${exchangeProperty.WriteTargetDirectory}/${in.header." + Exchange.FILE_NAME + "}]" )
.toD("file://destination/${exchangeProperty.WriteTargetDirectory}/");
目录列表
类
public class DirectoryListing {
String directoryLocation;
public DirectoryListing(String directoryLocation) {
this.directoryLocation = directoryLocation;
}
public String getDirectoryLocation() {
return directoryLocation;
}
}
路由测试代码
template.sendBody("direct:test",new DirectoryListing("IN/healthyindia/"));
测试日志
[ main] DefaultCamelContext INFO Apache Camel 2.23.1 (CamelContext: camel-1) started in 0.203 seconds
[ main] route5 INFO => body.directoryLocation is: IN/healthyindia/
[ main] FileEndpoint INFO Endpoint is configured with noop=true so forcing endpoint to be idempotent as well
[ main] FileEndpoint INFO Using default memory based idempotent repository with cache max size: 1000
[ main] route5 INFO => I still have the target directory location as : IN/healthyindia/
[ main] route5 INFO => I just received file [test.txt] and will write it as [destination/IN/healthyindia//test.txt]
[ main] MainRouteBuilderTest INFO ********************************************************************************
[ main] MainRouteBuilderTest INFO Testing done: testRouteBuilder(JustTest.MainRouteBuilderTest)
[ main] MainRouteBuilderTest INFO Took: 0.125 seconds (125 millis)
最后,在shelldragon的指导下,以下骆驼路线对我有效:
<route id="route5">
<from id="_from5" uri="direct:sftpGetCDRs"/>
<process id="_process1" ref="sftpGetDirLocation"/>
<log id="_log17" message="property ${exchangeProperty.ftpGetDirectory}"/>
<pollEnrich id="_pollEnrich1" timeout="0" uri="sftp://{{HOST}}//home/admin/ROSS_PULL_CDR/resellers/temp/${body.directoryLocation}/?consumer.delay=60000&username={{USER}}&password={{PASSWD}}"/>
<log id="_log18" message="${body}"/>
<to id="_to2" uri="file://{{DB_DIR_LOC}}/temp/?fileName=${exchangeProperty.ftpGetDirectory}&autoCreate=true"/>
</route>
刚刚意识到WriteTargetDirectory
是个坏名字。请用一些有意义的东西感谢雪龙提供的建议和纠正措施。我尝试将骆驼上下文XML DSL更新为问题中更新的内容。现在我面对的身体是空的错误。所以我身体上的内容必须为空,因为SFTP URI不起作用?或者我做得不正确?您可以通过将最后一个上的设置为来查看发生了什么,从而允许写入空正文。您的源目录中是否有0个长度的文件?现在使用consumerDelay=60000解决了此问题。似乎远程服务器没有快速响应,我的属性也没有给它足够的时间响应。太好了!很高兴知道你终于成功了。
[ main] DefaultCamelContext INFO Apache Camel 2.23.1 (CamelContext: camel-1) started in 0.203 seconds
[ main] route5 INFO => body.directoryLocation is: IN/healthyindia/
[ main] FileEndpoint INFO Endpoint is configured with noop=true so forcing endpoint to be idempotent as well
[ main] FileEndpoint INFO Using default memory based idempotent repository with cache max size: 1000
[ main] route5 INFO => I still have the target directory location as : IN/healthyindia/
[ main] route5 INFO => I just received file [test.txt] and will write it as [destination/IN/healthyindia//test.txt]
[ main] MainRouteBuilderTest INFO ********************************************************************************
[ main] MainRouteBuilderTest INFO Testing done: testRouteBuilder(JustTest.MainRouteBuilderTest)
[ main] MainRouteBuilderTest INFO Took: 0.125 seconds (125 millis)
<route id="route5">
<from id="_from5" uri="direct:sftpGetCDRs"/>
<process id="_process1" ref="sftpGetDirLocation"/>
<log id="_log17" message="property ${exchangeProperty.ftpGetDirectory}"/>
<pollEnrich id="_pollEnrich1" timeout="0" uri="sftp://{{HOST}}//home/admin/ROSS_PULL_CDR/resellers/temp/${body.directoryLocation}/?consumer.delay=60000&username={{USER}}&password={{PASSWD}}"/>
<log id="_log18" message="${body}"/>
<to id="_to2" uri="file://{{DB_DIR_LOC}}/temp/?fileName=${exchangeProperty.ftpGetDirectory}&autoCreate=true"/>
</route>