成功频道未选择正确的委派工厂

时间:2019-06-07 15:51:35

标签: spring-integration

我的成功频道正在使用一个包含sessionFactoryLocator的delegatingSessionFactory,然后根据threadKey应该选择正确的连接并将文件发送到该FTP服务器。

首先,当我运行应用程序时,我没有任何集成流程在运行,我填写了一个表格,指定FTP服务器和服务器的位置,它将在其中拉出文件以对其进行操作,然后将输出发送回服务器,并在成功通道将同时将原始文件也发送到该服务器进行存档。

根据我的编码,成功通道未选择正确的会话,因此未将其发送到正确的存档目标,仅将其发送到从会话定位器返回的默认ftp会话。

例如,我想插入FTP A,那么成功频道将发送到FTP A存档文件夹,然后,如果我输入另一个FTP B,那么成功频道将发送到FTP B存档文件夹。

@Configuration
@EnableIntegration
@ComponentScan
public class FTPIntegration {

public static final String TIMEZONE_UTC = "UTC";
public static final String TIMESTAMP_FORMAT_OF_FILES = "yyyyMMddHHmmssSSS";
public static final String TEMPORARY_FILE_SUFFIX = ".part";
public static final int POLLER_FIXED_PERIOD_DELAY = 5000;
public static final int MAX_MESSAGES_PER_POLL = 100;

private DataSource dataSource;

private static final Logger LOG1 = Logger.getLogger(FTPIntegration.class);
@Autowired
private CSVToCSVNoQ csvToCSVNoQ;

public FTPIntegration() {
}

@Autowired
BranchRepository branchRepository;

Map<Object, SessionFactory<FTPFile>> factories = new HashMap<>();
DefaultSessionFactoryLocator<FTPFile> defaultSessionFactoryLocator = new DefaultSessionFactoryLocator<FTPFile>(factories);

@Bean
public Branch myBranch() {
    return new Branch();
}

/**
 * The default poller with 5s, 100 messages , will poll the FTP folder location
 *
 * @return default poller.
 */
@Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata poller() {
    return Pollers
            .fixedDelay(POLLER_FIXED_PERIOD_DELAY)
            .maxMessagesPerPoll(MAX_MESSAGES_PER_POLL)
            .transactional()
            .get();
}

/**
 * The direct channel for the flow.
 *
 * @return MessageChannel
 */
@Bean
public MessageChannel stockIntermediateChannel() {
    return new DirectChannel();
}

/**
 * Get the files from a remote directory. Add a timestamp to the filename
 * and write them to a local temporary folder.
 *
 * @return IntegrationFlow
 */

/**
 * Method that creates a flow to read from FTP server the csv file
 * and transform it to a local folder with the name branch.
 *
 * @return IntegrationFlow
 */
public IntegrationFlow fileInboundFlowFromFTPServer(Branch myBranch) throws IOException {

    final FtpInboundChannelAdapterSpec sourceSpecFtp = Ftp.inboundAdapter(createNewFtpSessionFactory(myBranch))
            .preserveTimestamp(true)
            //.patternFilter("*.csv")
            .maxFetchSize(MAX_MESSAGES_PER_POLL)
            .remoteDirectory(myBranch.getFolderPath())
            .regexFilter("FEFOexport" + myBranch.getBranchCode() + ".csv")
            .deleteRemoteFiles(true)
            .localDirectory(new File(myBranch.getBranchCode()))
            .temporaryFileSuffix(TEMPORARY_FILE_SUFFIX);


           /* .localFilenameExpression(new FunctionExpression<String>(s -> {
                final int fileTypeSepPos = s.lastIndexOf('.');
                return DateTimeFormatter
                        .ofPattern(TIMESTAMP_FORMAT_OF_FILES)
                        .withZone(ZoneId.of(TIMEZONE_UTC))
                        .format(Instant.now())
                        + "_"
                        + s.substring(0,fileTypeSepPos)
                        + s.substring(fileTypeSepPos);
            }));*/

    // Poller definition
    final Consumer<SourcePollingChannelAdapterSpec> stockInboundPoller = endpointConfigurer -> endpointConfigurer
            .id("stockInboundPoller")
            .autoStartup(true)
            .poller(poller());

    IntegrationFlow flow = IntegrationFlows
            .from(sourceSpecFtp, stockInboundPoller)

            .transform(File.class, p -> {
                // log step
                LOG1.info("flow=stockInboundFlowFromAFT, message=incoming file: " + p);
                return p;
            })
            .handle(m -> {
                try {/* Invoking a method through the integration flow that reads a csv file and transform it to a new format that should be sent to FTP */
                    this.csvToCSVNoQ.writeCSVfinal("test", myBranch.getBranchCode() + "/final" + myBranch.getBranchCode() + ".csv", myBranch.getBranchCode() + "/FEFOexport" + myBranch.getBranchCode() + ".csv");
                    LOG1.info("Writing final file .csv " + m);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            })
            .get();

    return flow;
}

/**
 * Creating the outbound adaptor to send files from local to FTP server
 *@return integration flow from local to FTP server
 */

public IntegrationFlow localToFtpFlow(Branch myBranch) {

    return IntegrationFlows.from(Files.inboundAdapter(new File(myBranch.getBranchCode()))
                    .filter(new ChainFileListFilter<File>()
                            .addFilter(new RegexPatternFileListFilter("final" + myBranch.getBranchCode() + ".csv"))
                            .addFilter(new FileSystemPersistentAcceptOnceFileListFilter(metadataStore(dataSource), "foo"))),//FileSystemPersistentAcceptOnceFileListFilter
            e -> e.poller(Pollers.fixedDelay(10_000)))
            .enrichHeaders(h ->h.headerExpression("file_originalFile", "new java.io.File('"+ myBranch.getBranchCode() +"/FEFOexport" + myBranch.getBranchCode() + ".csv')",true))
            .transform(p -> {
                LOG1.info("Sending file " + p + " to FTP branch " + myBranch.getBranchCode());
                return p;
            })

            .log()
            .transform(m -> {
                        this.defaultSessionFactoryLocator.addSessionFactory(myBranch.getBranchCode(),createNewFtpSessionFactory(myBranch));
                        LOG1.info("Adding factory to delegation");
                        return m;
            })
            .handle(Ftp.outboundAdapter(createNewFtpSessionFactory(myBranch), FileExistsMode.REPLACE)

                    .useTemporaryFileName(true)
                    .autoCreateDirectory(false)
                    .remoteDirectory(myBranch.getFolderPath()), e -> e.advice(expressionAdvice()))

            .get();
}

/**
* Creating the advice for routing the payload of the outbound message on different expressions (success, failure)
* @return Advice
*/

@Bean
public Advice expressionAdvice() {
    ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
    advice.setSuccessChannelName("success.input");
    advice.setOnSuccessExpressionString("payload.delete() + ' was successful'");
    //advice.setOnSuccessExpressionString("inputMessage.headers['file_originalFile'].renameTo(new java.io.File(payload.absolutePath + '.success.to.send'))");
    //advice.setFailureChannelName("failure.input");
    advice.setOnFailureExpressionString("payload + ' was bad, with reason: ' + #exception.cause.message");
    advice.setTrapException(true);
    return advice;
}

/**
 * Creating FTP connection based on the branch ftp data entered.
 * @return ftpSessionFactory
 */

public DefaultFtpSessionFactory createNewFtpSessionFactory(Branch branch) {
    final DefaultFtpSessionFactory factory = new DefaultFtpSessionFactory();
    factory.setHost(branch.getHost());
    factory.setUsername(branch.getUsern());
    factory.setPort(branch.getFtpPort());
    factory.setPassword(branch.getPassword());
    return factory;
}

/**
 * Creating a default FTP connection.
 * @return ftpSessionFactory
 */
@Bean
public SessionFactory<FTPFile> createNewFtpSessionFactory() {
    final DefaultFtpSessionFactory factory = new DefaultFtpSessionFactory();
    factory.setHost("xxxxxxx");
    factory.setUsername("xxxxx");
    factory.setPort(21);
    factory.setPassword("xxxxxx");
    return factory;
}

/**
 * Creating a metadata store to be used across the application flows to prevent reprocessing the file if it is already processed.
 * This will save the new file in a metadata table in the DB with the state of the report, so when a new copy comes with different date it will be processed only.
 * @return metadataStore
 * */
@Bean
public ConcurrentMetadataStore metadataStore(final DataSource dataSource) {
    return new JdbcMetadataStore(dataSource);
}

/*
* Success channel that will handle the AdviceMessage from the outbound adapter and sends the inputMessage file_originalFile to FTP destination folder specified.
*
* */

@Bean
public IntegrationFlow success(){
    return f -> f.transform("inputMessage.headers['file_originalFile']")
            .transform(e -> {
                //getting the Branch code from the Input message and calling the correct factory based on it
                delegatingSessionFactoryAuto().setThreadKey(e.toString().substring(0,3));
                return e;
            })
            .handle(Ftp.outboundAdapter(delegatingSessionFactoryAuto(), FileExistsMode.REPLACE)
                    .useTemporaryFileName(true)
                    .autoCreateDirectory(true)
                    .remoteDirectory("/ftp/erbranch/EDMS/FEFO/History/").get());
}

@Bean
public DelegatingSessionFactory<FTPFile> delegatingSessionFactoryAuto(){

    SessionFactoryLocator<FTPFile> sff = createNewFtpSessionFactoryAndAddItToTheLocator();
    return new DelegatingSessionFactory<FTPFile>(sff);
}

@Bean
public SessionFactoryLocator<FTPFile> createNewFtpSessionFactoryAndAddItToTheLocator(){

    this.defaultSessionFactoryLocator.addSessionFactory("BEY",createNewFtpSessionFactory());
    return this.defaultSessionFactoryLocator;
}
}

0 个答案:

没有答案