Apache camel Apache camel sftp org.Apache.camel.NoTypeConversionAvailableException:没有可用于转换java.io.InputStream的类型转换器

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;

目前由于类型转换,我一直在从ftp服务器下载文件

因此,下面提到的路由是从一个管道中调用的,该管道的主体已经设置了我的自定义POJO。自定义pojo如下所示:

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&amp;streamDownload=true&amp;username={{USER}}&amp;password={{PASSWD}}"/>
        <to uri="file://{{DB_DIR_LOC}}/temp/?fileName=${body.directoryLocation}/&amp;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&amp;streamDownload=true&amp;username={{USER}}&amp;password={{PASSWD}}" timeout="0"/>
        <to uri="file://{{DB_DIR_LOC}}/temp/?fileName=${body.directoryLocation}/&amp;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
    参数指向目录。这行不通。您必须使用动态端点定义

  • 我不熟悉Camel的XML DSL。因此,我将展示如何使用JavaDSL实现这一点。对于brewity,我将避免使用SFTP,而是使用
    文件
    组件。我们将尝试一次性解决所有这些问题

    路线定义

    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&amp;username={{USER}}&amp;password={{PASSWD}}"/>
                <log id="_log18" message="${body}"/>
                <to id="_to2" uri="file://{{DB_DIR_LOC}}/temp/?fileName=${exchangeProperty.ftpGetDirectory}&amp;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&amp;username={{USER}}&amp;password={{PASSWD}}"/>
                <log id="_log18" message="${body}"/>
                <to id="_to2" uri="file://{{DB_DIR_LOC}}/temp/?fileName=${exchangeProperty.ftpGetDirectory}&amp;autoCreate=true"/>
            </route>