Spring Integration在处理后没有移动文件

时间:2018-04-06 23:02:35

标签: spring spring-boot spring-integration

我的要求是将文件从输入目录移动到输出目录。目前,我收到一个XML文件,解析它,处理它,并希望移动到新文件夹。我正在使用SPring boot 2.0,Spring INtegration 5.附带的是代码。此集成流程处理文件,但在处理后,它不会移动文件新目录。

您能告诉我遗漏的内容以及如何解决这个问题吗?

日志

2018-04-06 15:55:16.473[0;39m [32mDEBUG[0;39m [35m6364[0;39m [2m---[0;39m [2m[ask-scheduler-1][0;39m [36mo.s.i.handler.ServiceActivatingHandler  [0;39m [2m:[0;39m handler 'ServiceActivator for [org.springframework.integration.handler.BeanNameMessageProcessor@33a55bd8] (org.springframework.integration.handler.ServiceActivatingHandler#0)' produced no reply for request Message: GenericMessage [payload=Producers {id: -2147483648, parent-id: 0}, headers={file_originalFile=C:\slim\OBDF\Entire_IMO_hierarchy.xml, id=3ee00fca-1f2b-be84-742a-b5c6edfaf42a, file_name=Entire_IMO_hierarchy.xml, file_relativePath=Entire_IMO_hierarchy.xml, timestamp=1523055316426}]
2018-04-06 15:55:16.475[0;39m [32mDEBUG[0;39m [35m6364[0;39m ---[0;39m [ask-scheduler-1][0;39m [36mo.s.integration.channel.DirectChannel   [0;39m :[0;39m postSend (sent=true) on channel 'slimflow.channel#1', message: GenericMessage [payload=Producers {id: -2147483648, parent-id: 0}, headers={file_originalFile=C:\slim\OBDF\Entire_IMO_hierarchy.xml, id=3ee00fca-1f2b-be84-742a-b5c6edfaf42a, file_name=Entire_IMO_hierarchy.xml, file_relativePath=Entire_IMO_hierarchy.xml, timestamp=1523055316426}]
2018-04-06 15:55:16.480[0;39m [32mDEBUG[0;39m [35m6364[0;39m ---[0;39m [ask-scheduler-1][0;39m [36mo.s.integration.channel.DirectChannel   [0;39m :[0;39m postSend (sent=true) on channel 'slimflow.channel#0', message: GenericMessage [payload=C:\slim\OBDF\Entire_IMO_hierarchy.xml, headers={file_originalFile=C:\slim\OBDF\Entire_IMO_hierarchy.xml, id=0f673954-bceb-6e64-0d47-639522002569, file_name=Entire_IMO_hierarchy.xml, file_relativePath=Entire_IMO_hierarchy.xml, timestamp=1523055316320}]

集成流配置

import java.io.File;
import java.util.function.Function;

import javax.xml.bind.JAXBException;
import javax.xml.stream.XMLStreamException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.Pollers;
import org.springframework.integration.file.FileReadingMessageSource;
import org.springframework.integration.file.FileWritingMessageHandler;
import org.springframework.integration.file.filters.AcceptOnceFileListFilter;
import org.springframework.integration.file.filters.ChainFileListFilter;
import org.springframework.integration.file.filters.RegexPatternFileListFilter;
import org.springframework.integration.transformer.PayloadTypeConvertingTransformer;
import org.springframework.messaging.MessageHandler;

@Configuration
@EnableIntegration
public class SlimIntegrationConfig {
    @Value("${input.directory}")
    private String inputDir;

    @Value("${outputDir.directory}")
    private String outputDir;

    @Value("${input.scan.frequency: 100000}")
    private long scanFrequency;

    @Autowired
    private XmlBeanExtractor<Producers> xmlBeanExtractor;

    @Bean
    public MessageSource<File> inputFileSource() {
        FileReadingMessageSource src = new FileReadingMessageSource(
                (f1, f2) -> Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()));

        src.setDirectory(new File(inputDir));
        src.setAutoCreateDirectory(true);

        ChainFileListFilter<File> chainFileListFilter = new ChainFileListFilter<>();        
        chainFileListFilter.addFilter(new AcceptOnceFileListFilter<>() );
        chainFileListFilter.addFilter(new RegexPatternFileListFilter("(?i)^.+\\.xml$"));        
        src.setFilter(chainFileListFilter);

        return src;
    }

    @Bean
    public DirectChannel outputChannel() {
        return new DirectChannel();
    }

    @Bean
    public MessageHandler fileOutboundChannelAdapter() {

        FileWritingMessageHandler adapter = new FileWritingMessageHandler(new File(outputDir));
        adapter.setDeleteSourceFiles(true);
        adapter.setAutoCreateDirectory(true);
        adapter.setExpectReply(false);
        return adapter;
    }

    @Bean
    PayloadTypeConvertingTransformer<File, Producers> xmlBeanTranformer() {
        PayloadTypeConvertingTransformer<File, Producers> tranformer = new PayloadTypeConvertingTransformer<>();
        tranformer.setConverter(file -> {
            Producers p = null;
            try {
                p = xmlBeanExtractor.extract(file.getAbsolutePath(), Producers.class);
            } catch (JAXBException | XMLStreamException e) {
                e.printStackTrace();
            }

            return p;
        });

        return tranformer;
    }

    @Bean
    public IntegrationFlow slimflow() {
        return IntegrationFlows
                .from(inputFileSource(), spec -> spec.poller(Pollers.fixedDelay(scanFrequency)))
                .transform(xmlBeanTranformer())
                .handle("slimFileProcessor","processfile")
                .channel(outputChannel())
                .handle(fileOutboundChannelAdapter())
                .get()
                ;
    }
}

1 个答案:

答案 0 :(得分:1)

我们需要知道你的slimFileProcessor.processfile()做了什么。但是,它并没有反映出您在xmlBeanTranformer中所做的事情。您将File有效负载转换为Producers对象,并将此对象发送到slimFileProcessor

那么,首先是File payload中没有FileWritingMessageHandler。但我们可以稍后解决它。

现在您有一个日志:

  

ServiceActivatingHandler#0)&#39;没有回复请求

因此,您的slimFileProcessor不会返回要发送到outputChannel()的内容,以便将潜在文件从一个目录移动到另一个目录。

如果逻辑根本无法返回某些内容,则可以考虑使用.publishSubscribeChannel()。将xmlBeanTranformer()作为一个订阅者,将fileOutboundChannelAdapter()作为另一个订阅者。这样,相同的File对象将被发送到两个分支。只有在第一个分支完成其工作之前,第二个分支才会被调用。当然,如果一切都在同一个线程中完成。

您仍然可以使用简单的线性流,只是因为您获得了FileHeaders.ORIGINAL_FILE标题的增益,该标题将在FileWritingMessageHandler中使用。但是您应该记住,最后一个仅支持请求消息有效负载的这些类型:FileInputStreambyte[]String。对于进程后移动用例,当然,处理File类型会更好。这就是我建议考虑发布 - 订阅变体的原因。