Source:
<code>public IntegrationFlow ftpInboundFlow() { FtpInboundChannelAdapterSpec messageSourceBuilder = Ftp.inboundAdapter(FtpSource.this.ftpSessionFactory) .preserveTimestamp(config.isPreserveTimestamp()) .remoteDirectory(config.getRemoteDir()) .remoteFileSeparator(config.getRemoteFileSeparator()) .localDirectory(config.getLocalDir()) .autoCreateLocalDirectory(config.isAutoCreateLocalDir()) .temporaryFileSuffix(config.getTmpFileSuffix()) .deleteRemoteFiles(config.isDeleteRemoteFiles()); if (StringUtils.hasText(this.config.getFilenamePattern())) { messageSourceBuilder.filter(new FtpSimplePatternFileListFilter(this.config.getFilenamePattern())); } else if (StringUtils.hasText(this.config.getFilenameRegex())) { messageSourceBuilder <START> .filter(new FtpRegexPatternFileListFilter(Pattern.compile(this.config.getFilenameRegex()))); <END> } IntegrationFlowBuilder flowBuilder = IntegrationFlows.from(messageSourceBuilder , new Consumer<SourcePollingChannelAdapterSpec>() { @Override public void accept(SourcePollingChannelAdapterSpec sourcePollingChannelAdapterSpec) { sourcePollingChannelAdapterSpec .autoStartup(false) .poller(poller()); } }); switch (fileConsumerConfig.getMode()) { case contents: flowBuilder.enrichHeaders(Collections.<String, Object>singletonMap(MessageHeaders.CONTENT_TYPE, "application/octet-stream")) .transform(new FileToByteArrayTransformer()); break; case lines: flowBuilder.enrichHeaders(Collections.<String, Object>singletonMap(MessageHeaders.CONTENT_TYPE, "text/plain")) .split(new FileSplitter(true, fileConsumerConfig.getWithMarkers()), null); case ref: break; default: throw new IllegalArgumentException(fileConsumerConfig.getMode().name() + " is not a supported file reading mode."); } return flowBuilder.channel(source.output()).get(); }</code><technical_language>property a Pattern (adding a dedicated Converter if exists). This surface pattern compilation errors early</technical_language>

Target:
public IntegrationFlow ftpInboundFlow() { FtpInboundChannelAdapterSpec messageSourceBuilder = Ftp.inboundAdapter(FtpSource.this.ftpSessionFactory) .preserveTimestamp(config.isPreserveTimestamp()) .remoteDirectory(config.getRemoteDir()) .remoteFileSeparator(config.getRemoteFileSeparator()) .localDirectory(config.getLocalDir()) .autoCreateLocalDirectory(config.isAutoCreateLocalDir()) .temporaryFileSuffix(config.getTmpFileSuffix()) .deleteRemoteFiles(config.isDeleteRemoteFiles()); if (StringUtils.hasText(this.config.getFilenamePattern())) { messageSourceBuilder.filter(new FtpSimplePatternFileListFilter(this.config.getFilenamePattern())); } else if (this.config.getFilenameRegex() != null) { messageSourceBuilder .filter(new FtpRegexPatternFileListFilter(this.config.getFilenameRegex())); } IntegrationFlowBuilder flowBuilder = IntegrationFlows.from(messageSourceBuilder , new Consumer<SourcePollingChannelAdapterSpec>() { @Override public void accept(SourcePollingChannelAdapterSpec sourcePollingChannelAdapterSpec) { sourcePollingChannelAdapterSpec .autoStartup(false) .poller(poller()); } }); switch (fileConsumerConfig.getMode()) { case contents: flowBuilder.enrichHeaders(Collections.<String, Object>singletonMap(MessageHeaders.CONTENT_TYPE, "application/octet-stream")) .transform(new FileToByteArrayTransformer()); break; case lines: flowBuilder.enrichHeaders(Collections.<String, Object>singletonMap(MessageHeaders.CONTENT_TYPE, "text/plain")) .split(new FileSplitter(true, fileConsumerConfig.getWithMarkers()), null); case ref: break; default: throw new IllegalArgumentException(fileConsumerConfig.getMode().name() + " is not a supported file reading mode."); } return flowBuilder.channel(source.output()).get(); }