从 Unix 读取而不使用 Spring Integration 复制到本地时发现循环引用

Posted

技术标签:

【中文标题】从 Unix 读取而不使用 Spring Integration 复制到本地时发现循环引用【英文标题】:Circular reference found while reading from Unix without copying to Local using Spring Integration 【发布时间】:2017-01-07 18:11:24 【问题描述】:

我想从 Unix 位置读取 .txt 文件,而不是使用 Spring Integration 将其复制到本地。这应该以连续模式完成,即当新文件出现时,它应该被检测和读取。

代码:

 @SpringBootApplication
    public class SftpJavaApplication 

        public static void main(String[] args) 
            new SpringApplicationBuilder(SftpJavaApplication.class)
                .web(false)
                .run(args);
        
        @Bean
        public SessionFactory<LsEntry> sftpSessionFactory() 

            DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
            factory.setHost("ip");
            factory.setPort(port);
            factory.setUser("user");
            factory.setPassword("pwd");
            factory.setAllowUnknownKeys(true);
            return new CachingSessionFactory<LsEntry>(factory);
        
      @Bean
@Transformer(inputChannel = "stream",outputChannel="data")
public org.springframework.integration.transformer.Transformer  transformer () 
    return  new org.springframework.integration.transformer.StreamTransformer("UTF-8");
            

@Bean
@InboundChannelAdapter(value = "stream", poller = @Poller(fixedDelay = "1000", maxMessagesPerPoll = "1"))
public MessageSource<InputStream> ftpMessageSource() 
    SftpStreamingMessageSource messageSource = new SftpStreamingMessageSource(template(), null);
    messageSource.setRemoteDirectory("/test1/test2/test3");
    messageSource.setFilter(new SftpPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(),
                       "streaming"));
    return messageSource;




@Bean
public SftpRemoteFileTemplate template() 
    return new SftpRemoteFileTemplate(sftpSessionFactory());



@Bean
@ServiceActivator(inputChannel = "data" )
public MessageHandler handler() 
    return new MessageHandler() 


        @Override
        public void handleMessage(Message<?> message) throws MessagingException 
            System.out.println(">>>>>>>>>>>>>"+message.getPayload()); //this prints the data in the file


        

    ;

依赖关系:

 compile("org.springframework.cloud:spring-cloud-spring-service-connector:1.2.1.RELEASE")
    compile("org.springframework.cloud:spring-cloud-cloudfoundry-connector:1.2.1.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-integration")
    compile group: 'com.jcraft', name: 'jsch', version: '0.1.44-1'
    compile group: 'org.springframework.integration', name: 'spring-integration-sftp', version: '4.3.1.RELEASE'
    compile group: 'org.springframework.integration', name: 'spring-integration-file', version: '4.3.1.RELEASE'
    compile('org.kie.modules:org-apache-commons-lang3:6.3.0.Final')
    compile("com.h2database:h2:1.4.192")

编译组:'org.springframework.integration',名称:'spring-integration-core',版本:'4.3.1.RELEASE'

堆栈跟踪:

Caused by: org.springframework.core.NestedIOException: Failed to list files; nested exception is 2: No such file
    at org.springframework.integration.sftp.session.SftpSession.list(SftpSession.java:104)
    at org.springframework.integration.sftp.session.SftpSession.list(SftpSession.java:50)
    at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.list(CachingSessionFactory.java:218)
    at org.springframework.integration.file.remote.RemoteFileTemplate$6.doInSession(RemoteFileTemplate.java:417)
    at org.springframework.integration.file.remote.RemoteFileTemplate$6.doInSession(RemoteFileTemplate.java:413)
    at org.springframework.integration.file.remote.RemoteFileTemplate.execute(RemoteFileTemplate.java:435)
    ... 24 more
Caused by: 2: No such file
    at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2297)
    at com.jcraft.jsch.ChannelSftp._stat(ChannelSftp.java:1750)
    at com.jcraft.jsch.ChannelSftp._stat(ChannelSftp.java:1767)
    at com.jcraft.jsch.ChannelSftp.ls(ChannelSftp.java:1205)
    at org.springframework.integration.sftp.session.SftpSession.list(SftpSession.java:92)
    ... 29 more

【问题讨论】:

Unix/Local 是什么意思?您的意思是从远程服务器读取文件吗? 是的。我想从远程服务器(Unix 位置)读取文件。有人提到 Sftp 可以提供帮助。我试过了,但后来它在本地复制文件,然后我必须一个一个地读取文件。但是我必须避免这种情况,并在任何新文件变得可用时通过避免使用 xml 来读取特定目录中的所有可用文件 您可以发布您的configuration 文件吗? 我正在使用java配置,因为我们被要求避免使用xml。上面的代码是我正在使用的。 不要在 cmets 中提供说明和附加信息。编辑您的问题,使其更清晰。 【参考方案1】:

从 Spring Integration 4.3 开始,远程文件支持 (FTP/SFTP) 提供 streaming 适配器:

<int-ftp:inbound-streaming-channel-adapter id="ftpInbound"
            channel="ftpChannel"
            session-factory="sessionFactory"
            filename-pattern="*.txt"
            filename-regex=".*\.txt"
            filter="filter"
            remote-file-separator="/"
            comparator="comparator"
            remote-directory-expression="'foo/bar'">
        <int:poller fixed-rate="1000" />
</int-ftp:inbound-streaming-channel-adapter>

http://docs.spring.io/spring-integration/reference/html/whats-new.html#_ftp_sftp_streaming_inbound_channel_adapters

但是!我们不能“以连续模式”这样做,因为 (S)FTP 不是事件驱动协议。所以,我们还是应该定期轮询远程目录。

如果您真的知道某种方法可以让它监听远程目录中的某些事件,我们会很高兴在 Spring Integration 中提供这样一个开箱即用的组件。

编辑

当你为 Spring Integration 升级依赖项时,请确保所有模块都在同一版本,你的版本控制不好。

spring-integration-file 也应该是 4.3.1.RELEASE

你根本不需要它。它是spring-integration-sftp 的传递依赖。 以及你不需要spring-integration-core,因为它是所有它们的传递依赖。

EDIT2

我只想知道过滤器中使用的“Streaming”这个词的含义。它本身并没有阻止我读取文件。但出于知识目的,我想知道

Streaming 适配器的目的是让目标应用程序不创建 本地 文件副本。只需直接从内存中读取远程源的数据。所以,这就是你仍然可以读取文件的方式,但那是一个远程文件。不是吗?

关于 PCF 上的错误。

很高兴与我们分享有关此问题的 StackTrace。 从另一边,请尝试将allowUnknownKeys = true 用于DefaultSftpSessionFactory。并在Reference Manual 中阅读更多内容。

【讨论】:

非常感谢。我正在使用通过链接提供的 Sftp 处理 java 配置。但是对于 bean MessageSource 例外是:类型 org.springframework.integration.file.remote.AbstractRemoteFileStreamingMessageSource无法解决。它是从所需的 .class 文件中间接引用的。我在 gradle 中使用的是 spring integration core 4.3.1 Release 版本 Bean 定义:@Bean @InboundChannelAdapter(channel = "stream") public MessageSource ftpMessageSource() SftpStreamingMessageSource messageSource = new SftpStreamingMessageSource(template(), null); messageSource.setRemoteDirectory("sftpSource/"); messageSource.setFilter(new SftpPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "streaming" ));返回消息源; 只有core? AbstractRemoteFileStreamingMessageSourcespring-integration-file 的一部分。您必须将所有模块升级到相同版本。或者更好的是使用spring-integration-bom 在同一个地方管理所有版本。 请不要在 cmets 中提供代码。那是完全不可读的。只需编辑您的问题并在那里发表评论。 StackTrace 也会很有用。 好的。我已经添加了代码。请提供你的 cmets,因为我仍然面临同样的问题

以上是关于从 Unix 读取而不使用 Spring Integration 复制到本地时发现循环引用的主要内容,如果未能解决你的问题,请参考以下文章

从 ByteBuffer 读取字符串而不使用双缓冲

需要有关 unix 脚本的帮助以从特定位置读取数据并使用在查询中提取的数据

从 C++ / Unix 中的字符串读取 XML [关闭]

使用云功能从firebase数据库中读取数据而不依赖于事件[重复]

反序列化错误(socklist[[n]]):从 Unix 上的连接读取错误

从 goroutine 通道读取而不阻塞