Spring integration 来自控制器的Spring批处理集成启动/停止文件适配器
我不确定我的端点是否设置正确。我的最终目标是,当我在两个适配器上调用stop时,如果一个文件被放置在入站通道适配器轮询的任一目录中,该文件将不会被处理。但事实并非如此——文件仍在进行轮询和处理 当前,当代码运行时,从一开始就启动6个任务调度器:Spring integration 来自控制器的Spring批处理集成启动/停止文件适配器,spring-integration,Spring Integration,我不确定我的端点是否设置正确。我的最终目标是,当我在两个适配器上调用stop时,如果一个文件被放置在入站通道适配器轮询的任一目录中,该文件将不会被处理。但事实并非如此——文件仍在进行轮询和处理 当前,当代码运行时,从一开始就启动6个任务调度器: 2015-08-03 18:12:40,011 [task-scheduler-6] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Receive
2015-08-03 18:12:40,011 [task-scheduler-6] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:12:40,011 [task-scheduler-5] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:12:40,011 [task-scheduler-8] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:12:40,011 [task-scheduler-1] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:12:40,011 [task-scheduler-3] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:12:40,011 [task-scheduler-1] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
当我发出停止信号时
@'mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter'.stop()
在其中一个适配器上,我只剩下5个任务调度器。以下是正在发出的停止命令:
2015-08-03 18:15:28,392 [http-8080-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'control'
2015-08-03 18:15:28,392 [http-8080-1] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'control', message: GenericMessage [payload=@'mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter'.stop(), headers={timestamp=1438650928392, id=8107d99e-667c-1e78-31a0-dbcac2a6b03e}]
2015-08-03 18:15:28,392 [http-8080-1] DEBUG org.springframework.integration.handler.ServiceActivatingHandler - ServiceActivator for [org.springframework.integration.handler.ExpressionCommandMessageProcessor@f275f321] received message: GenericMessage [payload=@'mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter'.stop(), headers={timestamp=1438650928392, id=8107d99e-667c-1e78-31a0-dbcac2a6b03e}]
2015-08-03 18:15:28,407 [http-8080-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter'
2015-08-03 18:15:28,407 [http-8080-1] INFO org.springframework.integration.endpoint.SourcePollingChannelAdapter - stopped mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter
2015-08-03 18:15:28,407 [http-8080-1] DEBUG org.springframework.integration.handler.ServiceActivatingHandler - handler 'ServiceActivator for [org.springframework.integration.handler.ExpressionCommandMessageProcessor@f275f321]' produced no reply for request Message: GenericMessage [payload=@'mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter'.stop(), headers={timestamp=1438650928392, id=8107d99e-667c-1e78-31a0-dbcac2a6b03e}]
2015-08-03 18:15:28,407 [http-8080-1] DEBUG org.springframework.integration.channel.DirectChannel - postSend (sent=true) on channel 'control', message: GenericMessage [payload=@'mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter'.stop(), headers={timestamp=1438650928392, id=8107d99e-667c-1e78-31a0-dbcac2a6b03e}]
下面是第一个stop命令后生成的任务调度程序,现在只有5个:
2015-08-03 18:15:30,017 [task-scheduler-7] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:15:30,017 [task-scheduler-1] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:15:30,017 [task-scheduler-6] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:15:30,017 [task-scheduler-10] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:15:30,017 [task-scheduler-2] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
当我在第二个适配器上发出第二个停止时
@'mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter'.stop()
命令如下:
2015-08-03 18:21:49,652 [http-8080-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'control'
2015-08-03 18:21:49,668 [http-8080-1] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'control', message: GenericMessage [payload=@'mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter'.stop(), headers={timestamp=1438651309652, id=d4ba5ca8-db6f-4ee9-564e-9a2df2f6fb4d}]
2015-08-03 18:21:49,668 [http-8080-1] DEBUG org.springframework.integration.handler.ServiceActivatingHandler - ServiceActivator for [org.springframework.integration.handler.ExpressionCommandMessageProcessor@f275f321] received message: GenericMessage [payload=@'mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter'.stop(), headers={timestamp=1438651309652, id=d4ba5ca8-db6f-4ee9-564e-9a2df2f6fb4d}]
2015-08-03 18:21:49,668 [http-8080-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter'
2015-08-03 18:21:49,668 [http-8080-1] INFO org.springframework.integration.endpoint.SourcePollingChannelAdapter - stopped mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter
2015-08-03 18:21:49,668 [http-8080-1] DEBUG org.springframework.integration.handler.ServiceActivatingHandler - handler 'ServiceActivator for [org.springframework.integration.handler.ExpressionCommandMessageProcessor@f275f321]' produced no reply for request Message: GenericMessage [payload=@'mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter'.stop(), headers={timestamp=1438651309652, id=d4ba5ca8-db6f-4ee9-564e-9a2df2f6fb4d}]
2015-08-03 18:21:49,668 [http-8080-1] DEBUG org.springframework.integration.channel.DirectChannel - postSend (sent=true) on channel 'control', message: GenericMessage [payload=@'mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter'.stop(), headers={timestamp=1438651309652, id=d4ba5ca8-db6f-4ee9-564e-9a2df2f6fb4d}]
我只剩下4个任务调度器:
2015-08-03 18:23:40,014 [task-scheduler-2] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:23:40,014 [task-scheduler-6] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:23:40,014 [task-scheduler-5] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 18:23:40,014 [task-scheduler-7] DEBUG org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
下面是MecFilePoller类的代码:
@Configuration
@PropertySource("classpath:mec.properties")
@EnableIntegration
@IntegrationComponentScan
public class MecFilePoller {
private Job job;
private String fileParameterName;
@Autowired
MecProperty mecProperty;
@Bean
MessageChannel control() {
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel="control")
public ExpressionControlBusFactoryBean controlBus() {
return new ExpressionControlBusFactoryBean();
}
public void setFileParameterName(String fileParameterName) {
this.fileParameterName = fileParameterName;
}
public void setJob(Job job) {
this.job = job;
}
@Bean
@InboundChannelAdapter(value = "ssnInboundFileChannel", poller = @Poller(cron="${mec/SSN_POLLER}"))
public MessageSource<File> fileMessageSourceSSN() {
System.out.println("SSN POLLING...");
FileReadingMessageSource source = initialSetUp();
source.setDirectory(new File(mecProperty.getProperty(MecConstants.SSN_SFTP_WORKING_DIR)));
System.out.println("enter fileMessageSource in following dir....." + mecProperty.getProperty(MecConstants.SSN_SFTP_WORKING_DIR));
return source;
}
@Bean
@InboundChannelAdapter(value = "mdwInboundFileChannel", poller = @Poller(cron="${mec/MDW_POLLER}"))
public MessageSource<File> fileMessageSourceMDW() {
System.out.println("MDW POLLING...");
FileReadingMessageSource source = initialSetUp();
source.setDirectory(new File(mecProperty.getProperty(MecConstants.MDW_SFTP_WORKING_DIR)));
System.out.println("enter fileMessageSource in following dir....." + mecProperty.getProperty(MecConstants.MDW_SFTP_WORKING_DIR));
return source;
}
private FileReadingMessageSource initialSetUp() {
FileReadingMessageSource source = new FileReadingMessageSource();
CompositeFileListFilter<File> compositeFileListFilter = new CompositeFileListFilter<File>();
SimplePatternFileListFilter simplePatternFileListFilter = new SimplePatternFileListFilter("*.done");
AcceptOnceFileListFilter<File> acceptOnceFileListFilter = new AcceptOnceFileListFilter<File>();
compositeFileListFilter.addFilter(simplePatternFileListFilter);
compositeFileListFilter.addFilter(acceptOnceFileListFilter);
source.setFilter(compositeFileListFilter);
return source;
}
@Transformer(inputChannel="mdwInboundFileChannel",outputChannel="mdwOutboundJobRequestChannel")
public JobLaunchRequest toRequestMDW(Message<File> message) {
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
jobParametersBuilder.addString(INPUT_FILE_NAME, message.getPayload().getAbsolutePath());
return new JobLaunchRequest((Job) appContext.getBean("mecmdwJob"), jobParametersBuilder.toJobParameters());
}
@Transformer(inputChannel="ssnInboundFileChannel",outputChannel="ssnOutboundJobRequestChannel")
public JobLaunchRequest toRequestSSN(Message<File> message) {
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
jobParametersBuilder.addString(INPUT_FILE_NAME, message.getPayload().getAbsolutePath());
return new JobLaunchRequest((Job) appContext.getBean("mecssnJob"), jobParametersBuilder.toJobParameters());
}
public void commandTypePollerRequest(String command, String type) {
if(command.equals("stop") && type.equals("mdw")){
control().send(new GenericMessage<String>(
"@'mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter'.stop()"));
}
else if(command.equals("stop") && type.equals("ssn")){
control().send(new GenericMessage<String>(
"@'mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter'.stop()"));
}
else if(command.equals("start") && type.equals("mdw")){
control().send(new GenericMessage<String>(
"@'mecFilePoller.fileMessageSourceMDW.inboundChannelAdapter'.start()"));
}
else if(command.equals("start") && type.equals("ssn")){
control().send(new GenericMessage<String>(
"@'mecFilePoller.fileMessageSourceSSN.inboundChannelAdapter'.start()"));
}
}
@Controller
public class MECPollerController {
@Autowired
MecFilePoller mecFilePoller;
@Autowired
private ApplicationContext appContext;
@Autowired
MessageChannel ssnOutboundJobRequestChannel;
@Autowired
MessageChannel mdwOutboundJobRequestChannel;
@RequestMapping(value = "ui/stopMdwPoller.action", method = RequestMethod.GET)
public void stopMdwPollerRequest() {
mecFilePoller.commandTypePollerRequest("stop","mdw");
}
@RequestMapping(value = "ui/stopSsnPoller.action", method = RequestMethod.GET)
public void stopSsnPollerRequest() {
mecFilePoller.commandTypePollerRequest("stop","ssn");
}
@RequestMapping(value = "ui/startMdwPoller.action", method = RequestMethod.GET)
public void startMdwPollerRequest() {
mecFilePoller.commandTypePollerRequest("start","mdw");
}
@RequestMapping(value = "ui/startSsnPoller.action", method = RequestMethod.GET)
public void startSsnPollerRequest() {
mecFilePoller.commandTypePollerRequest("start","ssn");
}
}
以下是one Spring批处理作业job-mecmdw.XML的XML配置:
<int:channel id="mdwInboundFileChannel" />
<int:channel id="mdwOutboundJobRequestChannel" />
<int:channel id="mdwJobLaunchReplyChannel" />
<int:annotation-config />
<bean class="org.springframework.integration.core.MessagingTemplate"></bean>
<!-- THIS WAS MOVED TO MecFilePoller
<int:transformer input-channel="mdwInboundFileChannel" output-channel="mdwOutboundJobRequestChannel">
<bean
class="org.batch.poller.MecFilePoller">
<property name="job" ref="mecmdwJob" />
<property name="fileParameterName" value="input.file.name" />
</bean>
</int:transformer>
-->
<batch-int:job-launching-gateway request-channel="mdwOutboundJobRequestChannel" reply-channel="mdwJobLaunchReplyChannel" />
<int:logging-channel-adapter channel="mdwJobLaunchReplyChannel" />
以下是另一个Spring批处理作业job-mecssn.XML的XML配置:
<int:annotation-config />
<int:channel id="ssnInboundFileChannel" />
<int:channel id="ssnOutboundJobRequestChannel" />
<int:channel id="ssnJobLaunchReplyChannel" />
<!-- THIS WAS MOVED TO MecFilePoller
<int:transformer input-channel="ssnInboundFileChannel"
output-channel="ssnOutboundJobRequestChannel">
<bean
class="org.batch.poller.MecFilePoller">
<property name="job" ref="mecssnJob" />
<property name="fileParameterName" value="input.file.name" />
</bean>
</int:transformer>
-->
<batch-int:job-launching-gateway request-channel="ssnOutboundJobRequestChannel" reply-channel="ssnJobLaunchReplyChannel" />
<int:logging-channel-adapter channel="ssnJobLaunchReplyChannel" />
入站通道适配器由(至少两个)bean组成;在本例中,使用
MessageSource
和SourcePollingChannelAdapter
在您的示例中,消息源获取指定的bean名称(filePoller
)。将生成通道适配器的名称,并将
filePoller.fileMessageSource.inboundChannelAdapter
(@Configuration
类bean名称+方法名称+类型)
我们有一个文档来记录这些生成的bean名称
由于名称为虚线,因此在使用控制总线时需要引用:
@'filePoller.fileMessageSource.inboundChannelAdapter'.stop()
编辑
我刚测试过这个,效果很好
@Configuration
@EnableIntegration
public class Foo {
@Bean
QueueChannel inboundFileChannel() {
return new QueueChannel();
}
@Bean
@InboundChannelAdapter(value = "inboundFileChannel", poller = @Poller(fixedDelay="1000"))
public MessageSource<?> fileMessageSource() {
MessageSource<?> source = mock(MessageSource.class);
return source;
}
@Bean
MessageChannel control() {
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel="control")
public ExpressionControlBusFactoryBean controlBus() {
return new ExpressionControlBusFactoryBean();
}
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Foo.class);
Thread.sleep(2000);
ctx.getBean("control", MessageChannel.class).send(
new GenericMessage<String>("@'foo.fileMessageSource.inboundChannelAdapter'.stop()"));
assertFalse(ctx.getBean(SourcePollingChannelAdapter.class).isRunning());
Thread.sleep(2000);
ctx.close();
}
}
(停止后不进行投票)。谢谢。但当我将其更改为control.send(新的GenericMessage(“@'filePoller.fileMessageSource.inboundChannelAdapter.stop()”)时,我得到了错误org.springframework.expression.spel.SpelEvaluationException:EL1058E:(位置1):尝试解析bean“filePoller.fileMessageSource.inboundChannelAdapter”时出现问题:“无法解析针对BeanFactory的bean引用”。本质上,NoSuchBeanDefinitionException:没有定义名为“filePoller.fileMessageSource.inboundChannelAdapter”的bean从bean中删除名称,或者更改名称,或者重命名配置类;配置类
FilePoller
获取bean名FilePoller
。这可能是问题的根源。谢谢你,加里。我照你说的做了。将我的类更新为MECFilePoller,将我的bean名更新为(不同于类名)mdwFilePoller。我的文件消息源方法现在也是fileMessageSourceMDW。我现在向控制总线发送的命令是:control.send(新的GenericMessage(“@'mdwFilePoller.fileMessageSourceMDW.inboundChannelAdapter.stop()”)。不幸的是,我仍然没有定义名为“mdwFilePoller.fileMessageSourceMDW.inboundChannelAdapter”的bean,如果您的类是MECFilePoller
,则bean名称是MECFilePoller
而不是mdw…
。我刚刚在我的答案中粘贴了一个测试,效果很好。太好了。虽然我认为它会立即停止投票?我仍然看到轮询消息:SourcePollingChannelAdapter-在轮询期间没有收到任何消息,返回“false”,即使在调用stop之后也是如此。
2015-08-03 12:23:34,528 [task-scheduler-1] DEBUG: org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 12:23:35,530 [task-scheduler-2] DEBUG: org.springframework.integration.endpoint.SourcePollingChannelAdapter - Received no Message during the poll, returning 'false'
2015-08-03 12:23:35,615 [main] DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'control'
2015-08-03 12:23:35,616 [main] DEBUG: org.springframework.integration.channel.DirectChannel - preSend on channel 'control', message: GenericMessage [payload=@'foo.fileMessageSource.inboundChannelAdapter'.stop(), headers={id=d0049777-025c-5439-6ee7-d66bce34868a, timestamp=1438619015616}]
2015-08-03 12:23:35,616 [main] DEBUG: org.springframework.integration.handler.ServiceActivatingHandler - ServiceActivator for [org.springframework.integration.handler.ExpressionCommandMessageProcessor@1e0b4072] received message: GenericMessage [payload=@'foo.fileMessageSource.inboundChannelAdapter'.stop(), headers={id=d0049777-025c-5439-6ee7-d66bce34868a, timestamp=1438619015616}]
2015-08-03 12:23:35,617 [main] DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'foo.fileMessageSource.inboundChannelAdapter'
2015-08-03 12:23:35,618 [main] INFO : org.springframework.integration.endpoint.SourcePollingChannelAdapter - stopped foo.fileMessageSource.inboundChannelAdapter
2015-08-03 12:23:35,618 [main] DEBUG: org.springframework.integration.handler.ServiceActivatingHandler - handler 'ServiceActivator for [org.springframework.integration.handler.ExpressionCommandMessageProcessor@1e0b4072]' produced no reply for request Message: GenericMessage [payload=@'foo.fileMessageSource.inboundChannelAdapter'.stop(), headers={id=d0049777-025c-5439-6ee7-d66bce34868a, timestamp=1438619015616}]
2015-08-03 12:23:35,618 [main] DEBUG: org.springframework.integration.channel.DirectChannel - postSend (sent=true) on channel 'control', message: GenericMessage [payload=@'foo.fileMessageSource.inboundChannelAdapter'.stop(), headers={id=d0049777-025c-5439-6ee7-d66bce34868a, timestamp=1438619015616}]
2015-08-03 12:23:35,618 [main] DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'foo.fileMessageSource.inboundChannelAdapter'