Spring 集成 - SpelEvaluationException:'java.lang.String' 和 'null' 类型的对象之间不支持运算符 'ADD'
Spring Integration - SpelEvaluationException: The operator 'ADD' is not supported between objects of type 'java.lang.String' and 'null'
我有一个 Spring batch/integration 作业,它应该轮询 FTP 服务器,获取所有 .txt 文件,使用 Spring 批处理组件转换它们,然后然后将它们放在队列中(使用 ActiveMQ 实现)。但是,我在尝试从 FTP 区域检索文件时遇到此错误:
ERROR [org.springframework.integration.handler.LoggingHandler] - <org.springframework.expression.spel.SpelEvaluationException: EL1030E:(pos 0): The operator 'ADD' is not supported between objects of type 'java.lang.String' and 'null'
相关 spring xml 配置(为清楚起见省略了很多代码):
<beans>
<!-- Spring integration setup -->
<int:channel id="outboundJobRequestChannel"/>
<int:channel id="jobLaunchReplyChannel"/>
<int:channel id="inboundFileChannel"/>
<batch-int:job-launching-gateway request-channel="outboundJobRequestChannel"
reply-channel="jobLaunchReplyChannel"
job-launcher="jobLauncher" />
<int:logging-channel-adapter channel="jobLaunchReplyChannel"/>
<int:transformer input-channel="ftpChannel"
output-channel="outboundJobRequestChannel"
method="toRequest">
<bean class="package.FileMessageToJobRequest">
<constructor-arg index="0" ref="myJob" />
<constructor-arg index="1" value="input.file.name" />
</bean>
</int:transformer>
<bean id="ftpClientFactory" class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="${import.ftp.host}" />
<property name="port" value="${import.ftp.port}" />
<property name="username" value="${import.ftp.username}" />
<property name="password" value="${import.ftp.password}" />
</bean>
<int:channel id="ftpChannel" />
<int-ftp:inbound-channel-adapter id="ftpInbound"
channel="ftpChannel"
session-factory="ftpClientFactory"
auto-create-local-directory="true"
delete-remote-files="false"
filename-pattern="*.txt"
remote-directory="${import.ftp.remotefolder}"
local-filename-generator-expression="+#this"
temporary-file-suffix=".reading"
local-directory="${ftp.localdir}">
<int:poller fixed-rate="1000"/>
</int-ftp:inbound-channel-adapter>
<!-- Spring batch job setup -->
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<batch:job-repository id="jobRepository" transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<batch:job id="myJob">
<batch:step id="textToXmlStep" next="addToQueueStep">
<batch:tasklet>
<batch:chunk reader="filradReader" writer="multiResourceWriter" commit-interval="${job.commit.interval}" />
</batch:tasklet>
<batch:listeners>
<batch:listener ref="stepListener"/>
</batch:listeners>
</batch:step>
<batch:step id="addToQueueStep">
<batch:tasklet ref="addFilesToQueueTasklet" />
<batch:listeners>
<batch:listener ref="stepListener"/>
</batch:listeners>
</batch:step>
<batch:listeners>
<batch:listener ref="jobListener"/>
</batch:listeners>
</batch:job>
<bean id="filradReader" scope="step" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="file://#{jobParameters['input.file.name']}" />
<property name="lineMapper" ref="filradCompositeLineMapper"/>
<property name="linesToSkip" value="1"/>
<property name="skippedLinesCallback" ref="callbackHandler"/>
<property name="encoding" value="UTF-8" />
</bean>
<bean id="addFilesToQueueTasklet" class="package.FilesToMqTasklet">
<property name="filesBaseDir" value="${files.outputdir}\xml" />
<property name="messageProducer" ref="messageProducer"/>
</bean>
<!-- ActiveMQ setup -->
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
p:brokerURL="${broker.url}" />
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="queue" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="connectionFactory"
p:defaultDestination-ref="destination" />
<bean id="messageProducer" class="package.FileMessageProducer"
p:jmsTemplate-ref="jmsTemplate" />
<bean id="messageListener" class="package.FileMessageListener" />
<jms:listener-container concurrency="5-50">
<jms:listener destination="queue" ref="messageListener"/>
</jms:listener-container>
</beans>
(部分)FileMessageToJobRequest.java:
public FileMessageToJobRequest(final Job job, final String fileParameterName){
this.job = job;
this.fileParameterName = fileParameterName;
}
public JobLaunchRequest toRequest(Message<File> message) {
JobParametersBuilder jobParametersBuilder =
new JobParametersBuilder();
jobParametersBuilder.addString(fileParameterName,
message.getPayload().getAbsolutePath()).addDate("run.date", new Date());
return new JobLaunchRequest(job, jobParametersBuilder.toJobParameters());
}
(部分)FileMessageProducer.java:
public class FileMessageProducer {
private static final Logger logger = Logger.getLogger(FileMessageProducer.class);
protected JmsTemplate jmsTemplate;
public void sendFile(final File file) throws JMSException {
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
ObjectMessage message = session.createObjectMessage(file);
message.setStringProperty("fileName", file.getName());
logger.info("Sent message: "+message.getStringProperty("fileName"));
return message;
}
});
}
(部分)FileMessageListener.java:
public class FileMessageListener implements MessageListener {
private static final Logger logger = Logger.getLogger(FileMessageListener.class);
public void onMessage(Message message) {
try {
logger.info("Received file " + message.getStringProperty("fileName"));
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
我正在使用
测试此设置
public class FileListener {
private static final Logger logger = Logger.getLogger(FileListener.class);
private static final String CONFIG = "/launch-context.xml";
public static void main(String[] args) throws Exception {
logger.debug("FileListener started");
new ClassPathXmlApplicationContext(CONFIG);
}
}
完整的堆栈跟踪:
2015-03-09 10:06:52,879 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@644b27ad: startup date [Mon Mar 09 10:06:52 CET 2015]; root of context hierarchy>
2015-03-09 10:06:52,931 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [launch-context.xml]>
2015-03-09 10:06:53,111 INFO [org.springframework.context.annotation.ClassPathBeanDefinitionScanner] - <JSR-330 'javax.inject.Named' annotation found and supported for component scanning>
2015-03-09 10:06:53,187 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/datasource-beans.xml]>
2015-03-09 10:06:53,228 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/job.xml]>
2015-03-09 10:06:53,303 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'transactionManager': replacing [Generic bean: class [org.springframework.jdbc.datasource.DataSourceTransactionManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/datasource-beans.xml]] with [Generic bean: class [org.springframework.batch.support.transaction.ResourcelessTransactionManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:53,321 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'myJob': replacing [Generic bean: class [org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.springframework.batch.core.configuration.xml.JobParserJobFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]>
2015-03-09 10:06:53,326 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/queue.xml]>
2015-03-09 10:06:54,043 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/integration.xml]>
2015-03-09 10:06:54,367 INFO [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer] - <Loading properties file from URL [file:/.../externalConfig/dev/application.properties]>
2015-03-09 10:06:54,386 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'stepListener': replacing [Generic bean: class [package.StepListener]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:54,386 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'filradReader': replacing [Generic bean: class [org.springframework.batch.item.file.FlatFileItemReader]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:54,387 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'multiResourceWriter': replacing [Generic bean: class [org.springframework.batch.item.file.MultiResourceItemWriter]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:54,387 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'filradXmlWriter': replacing [Generic bean: class [org.springframework.batch.item.xml.StaxEventItemWriter]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:54,391 INFO [org.springframework.integration.config.xml.DefaultConfiguringBeanFactoryPostProcessor] - <No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.>
2015-03-09 10:06:54,392 INFO [org.springframework.integration.config.xml.DefaultConfiguringBeanFactoryPostProcessor] - <No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.>
2015-03-09 10:06:54,402 INFO [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - <JSR-330 'javax.inject.Inject' annotation found and supported for autowiring>
2015-03-09 10:06:54,415 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6112f78c: defining beans [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.jdbc.datasource.init.DataSourceInitializer#0,dataSource,transactionManager,jobLauncher,org.springframework.batch.core.scope.internalStepScope,org.springframework.beans.factory.config.CustomEditorConfigurer,org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor,jobRepository,filradSetMapper,stepListener,jobListener,callbackHandler,suffixCreator,filradProcessor,textToXmlStep,addToQueueStep,myJob,multiResourceReader,filradReader,filradCompositeLineMapper,taxiTokenizer,biljettTokenizer,rullstolTokenizer,multiResourceWriter,filradXmlWriter,filradTyperValidMarshaller,addFilesToQueueTasklet,connectionFactory,destination,jmsTemplate,messageProducer,messageListener,org.springframework.jms.listener.DefaultMessageListenerContainer#0,channelInitializer,$autoCreateChannelCandidates,org.springframework.integration.internalDefaultConfiguringBeanFactoryPostProcessor,outboundJobRequestChannel,jobLaunchReplyChannel,inboundFileChannel,org.springframework.batch.integration.launch.JobLaunchingGateway#0,org.springframework.integration.config.ConsumerEndpointFactoryBean#0,org.springframework.integration.handler.LoggingHandler#0,org.springframework.integration.config.ConsumerEndpointFactoryBean#1,org.springframework.integration.config.TransformerFactoryBean#0,org.springframework.integration.config.ConsumerEndpointFactoryBean#2,ftpClientFactory,ftpChannel,org.springframework.scheduling.support.PeriodicTrigger#0,ftpInbound,ftpController,scopedTarget.stepListener,scopedTarget.filradReader,scopedTarget.multiResourceWriter,scopedTarget.filradXmlWriter,nullChannel,errorChannel,_org.springframework.integration.errorLogger,taskScheduler,org.springframework.integration.config.IdGeneratorConfigurer#0]; root of factory hierarchy>
2015-03-09 10:06:54,597 INFO [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] - <Executing SQL script from URL [jar:file:/C:/Users/jesleh/.m2/repository/org/springframework/batch/spring-batch-core/2.2.3.RELEASE/spring-batch-core-2.2.3.RELEASE.jar!/org/springframework/batch/core/schema-drop-hsqldb.sql]>
2015-03-09 10:06:54,601 INFO [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] - <Done executing SQL script from URL [jar:file:/C:/Users/jesleh/.m2/repository/org/springframework/batch/spring-batch-core/2.2.3.RELEASE/spring-batch-core-2.2.3.RELEASE.jar!/org/springframework/batch/core/schema-drop-hsqldb.sql] in 4 ms.>
2015-03-09 10:06:54,601 INFO [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] - <Executing SQL script from URL [jar:file:/C:/Users/jesleh/.m2/repository/org/springframework/batch/spring-batch-core/2.2.3.RELEASE/spring-batch-core-2.2.3.RELEASE.jar!/org/springframework/batch/core/schema-hsqldb.sql]>
2015-03-09 10:06:54,614 INFO [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] - <Done executing SQL script from URL [jar:file:/C:/Users/jesleh/.m2/repository/org/springframework/batch/spring-batch-core/2.2.3.RELEASE/spring-batch-core-2.2.3.RELEASE.jar!/org/springframework/batch/core/schema-hsqldb.sql] in 12 ms.>
2015-03-09 10:06:54,663 INFO [org.springframework.batch.core.repository.support.JobRepositoryFactoryBean] - <No database type set, using meta data indicating: HSQL>
2015-03-09 10:06:54,797 INFO [org.springframework.batch.core.launch.support.SimpleJobLauncher] - <No TaskExecutor has been set, defaulting to synchronous executor.>
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
2015-03-09 10:06:55,027 INFO [org.springframework.oxm.jaxb.Jaxb2Marshaller] - <Creating JAXBContext with classes to be bound [class package.Filrad]>
2015-03-09 10:06:55,490 INFO [org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler] - <Initializing ExecutorService 'taskScheduler'>
2015-03-09 10:06:55,498 INFO [org.springframework.context.support.DefaultLifecycleProcessor] - <Starting beans in phase -2147483648>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <Adding {message-handler} as a subscriber to the 'outboundJobRequestChannel' channel>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.channel.DirectChannel] - <Channel 'outboundJobRequestChannel' has 1 subscriber(s).>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <started org.springframework.integration.config.ConsumerEndpointFactoryBean#0>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <Adding {logging-channel-adapter} as a subscriber to the 'jobLaunchReplyChannel' channel>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.channel.DirectChannel] - <Channel 'jobLaunchReplyChannel' has 1 subscriber(s).>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <started org.springframework.integration.config.ConsumerEndpointFactoryBean#1>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <Adding {transformer} as a subscriber to the 'ftpChannel' channel>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.channel.DirectChannel] - <Channel 'ftpChannel' has 1 subscriber(s).>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <started org.springframework.integration.config.ConsumerEndpointFactoryBean#2>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.channel.PublishSubscribeChannel] - <Channel 'errorChannel' has 1 subscriber(s).>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <started _org.springframework.integration.errorLogger>
2015-03-09 10:06:55,499 INFO [org.springframework.context.support.DefaultLifecycleProcessor] - <Starting beans in phase 2147483647>
2015-03-09 10:06:55,755 INFO [org.springframework.integration.endpoint.SourcePollingChannelAdapter] - <started ftpInbound>
2015-03-09 10:07:10,041 ERROR [org.springframework.integration.handler.LoggingHandler] - <org.springframework.expression.spel.SpelEvaluationException: EL1030E:(pos 0): The operator 'ADD' is not supported between objects of type 'java.lang.String' and 'null'
at org.springframework.expression.spel.ExpressionState.operate(ExpressionState.java:191)
at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:59)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:102)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.generateLocalFileName(AbstractInboundFileSynchronizer.java:228)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.copyFileToLocalDirectory(AbstractInboundFileSynchronizer.java:174)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.synchronizeToLocalDirectory(AbstractInboundFileSynchronizer.java:150)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizingMessageSource.receive(AbstractInboundFileSynchronizingMessageSource.java:146)
at org.springframework.integration.endpoint.SourcePollingChannelAdapter.receiveMessage(SourcePollingChannelAdapter.java:111)
at org.springframework.integration.endpoint.AbstractTransactionSynchronizingPollingEndpoint.doPoll(AbstractTransactionSynchronizingPollingEndpoint.java:67)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.call(AbstractPollingEndpoint.java:146)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.call(AbstractPollingEndpoint.java:144)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:236)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.run(ErrorHandlingTaskExecutor.java:52)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:49)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:231)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
作业本身(读取 .txt 文件并将其转换为 xml 输出)有效,我 运行 单独执行了该步骤没有问题。问题似乎在于从 FTP 区域读取文件。我也试过用谷歌搜索这个问题,但找不到任何东西。我意识到这是一个很大的要求,但如果有人有任何想法,我会非常高兴。谢谢。
我已经把它作为答案了。
第一个错误是因为在执行操作时传递了 null local-filename-generator-expression="+#this
”。尝试提供值似乎可以解决问题 local-filename-generator-expression="'sample'+#this"
。
您评论中的第二个错误是因为方法签名。下面的方法将 Message<File> message
作为参数,而它的调用者将 io.File 作为参数传递。因此错误。根据提供的信息,我不确定来电者在哪里,但这应该给你错误的要点。
public JobLaunchRequest toRequest(Message<File> message) {
JobParametersBuilder jobParametersBuilder =
new JobParametersBuilder();
我用
解决了这个问题
<int:service-activator id="runJob" method="launch" input-channel="outboundJobRequestChannel"
output-channel="statuses">
<bean class="org.springframework.batch.integration.launch.JobLaunchingMessageHandler">
<constructor-arg ref="jobLauncher"/>
</bean>
</int:service-activator>
而不是
<batch-int:job-launching-gateway request-channel="outboundJobRequestChannel"
reply-channel="jobLaunchReplyChannel"
job-launcher="jobLauncher" />
然后将 toRequest 方法的参数更改为(java.io.File 文件)。现在一切都按预期工作。感谢@minion 的帮助。
我有一个 Spring batch/integration 作业,它应该轮询 FTP 服务器,获取所有 .txt 文件,使用 Spring 批处理组件转换它们,然后然后将它们放在队列中(使用 ActiveMQ 实现)。但是,我在尝试从 FTP 区域检索文件时遇到此错误:
ERROR [org.springframework.integration.handler.LoggingHandler] - <org.springframework.expression.spel.SpelEvaluationException: EL1030E:(pos 0): The operator 'ADD' is not supported between objects of type 'java.lang.String' and 'null'
相关 spring xml 配置(为清楚起见省略了很多代码):
<beans>
<!-- Spring integration setup -->
<int:channel id="outboundJobRequestChannel"/>
<int:channel id="jobLaunchReplyChannel"/>
<int:channel id="inboundFileChannel"/>
<batch-int:job-launching-gateway request-channel="outboundJobRequestChannel"
reply-channel="jobLaunchReplyChannel"
job-launcher="jobLauncher" />
<int:logging-channel-adapter channel="jobLaunchReplyChannel"/>
<int:transformer input-channel="ftpChannel"
output-channel="outboundJobRequestChannel"
method="toRequest">
<bean class="package.FileMessageToJobRequest">
<constructor-arg index="0" ref="myJob" />
<constructor-arg index="1" value="input.file.name" />
</bean>
</int:transformer>
<bean id="ftpClientFactory" class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="${import.ftp.host}" />
<property name="port" value="${import.ftp.port}" />
<property name="username" value="${import.ftp.username}" />
<property name="password" value="${import.ftp.password}" />
</bean>
<int:channel id="ftpChannel" />
<int-ftp:inbound-channel-adapter id="ftpInbound"
channel="ftpChannel"
session-factory="ftpClientFactory"
auto-create-local-directory="true"
delete-remote-files="false"
filename-pattern="*.txt"
remote-directory="${import.ftp.remotefolder}"
local-filename-generator-expression="+#this"
temporary-file-suffix=".reading"
local-directory="${ftp.localdir}">
<int:poller fixed-rate="1000"/>
</int-ftp:inbound-channel-adapter>
<!-- Spring batch job setup -->
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<batch:job-repository id="jobRepository" transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<batch:job id="myJob">
<batch:step id="textToXmlStep" next="addToQueueStep">
<batch:tasklet>
<batch:chunk reader="filradReader" writer="multiResourceWriter" commit-interval="${job.commit.interval}" />
</batch:tasklet>
<batch:listeners>
<batch:listener ref="stepListener"/>
</batch:listeners>
</batch:step>
<batch:step id="addToQueueStep">
<batch:tasklet ref="addFilesToQueueTasklet" />
<batch:listeners>
<batch:listener ref="stepListener"/>
</batch:listeners>
</batch:step>
<batch:listeners>
<batch:listener ref="jobListener"/>
</batch:listeners>
</batch:job>
<bean id="filradReader" scope="step" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="file://#{jobParameters['input.file.name']}" />
<property name="lineMapper" ref="filradCompositeLineMapper"/>
<property name="linesToSkip" value="1"/>
<property name="skippedLinesCallback" ref="callbackHandler"/>
<property name="encoding" value="UTF-8" />
</bean>
<bean id="addFilesToQueueTasklet" class="package.FilesToMqTasklet">
<property name="filesBaseDir" value="${files.outputdir}\xml" />
<property name="messageProducer" ref="messageProducer"/>
</bean>
<!-- ActiveMQ setup -->
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
p:brokerURL="${broker.url}" />
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="queue" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="connectionFactory"
p:defaultDestination-ref="destination" />
<bean id="messageProducer" class="package.FileMessageProducer"
p:jmsTemplate-ref="jmsTemplate" />
<bean id="messageListener" class="package.FileMessageListener" />
<jms:listener-container concurrency="5-50">
<jms:listener destination="queue" ref="messageListener"/>
</jms:listener-container>
</beans>
(部分)FileMessageToJobRequest.java:
public FileMessageToJobRequest(final Job job, final String fileParameterName){
this.job = job;
this.fileParameterName = fileParameterName;
}
public JobLaunchRequest toRequest(Message<File> message) {
JobParametersBuilder jobParametersBuilder =
new JobParametersBuilder();
jobParametersBuilder.addString(fileParameterName,
message.getPayload().getAbsolutePath()).addDate("run.date", new Date());
return new JobLaunchRequest(job, jobParametersBuilder.toJobParameters());
}
(部分)FileMessageProducer.java:
public class FileMessageProducer {
private static final Logger logger = Logger.getLogger(FileMessageProducer.class);
protected JmsTemplate jmsTemplate;
public void sendFile(final File file) throws JMSException {
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
ObjectMessage message = session.createObjectMessage(file);
message.setStringProperty("fileName", file.getName());
logger.info("Sent message: "+message.getStringProperty("fileName"));
return message;
}
});
}
(部分)FileMessageListener.java:
public class FileMessageListener implements MessageListener {
private static final Logger logger = Logger.getLogger(FileMessageListener.class);
public void onMessage(Message message) {
try {
logger.info("Received file " + message.getStringProperty("fileName"));
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
我正在使用
测试此设置public class FileListener {
private static final Logger logger = Logger.getLogger(FileListener.class);
private static final String CONFIG = "/launch-context.xml";
public static void main(String[] args) throws Exception {
logger.debug("FileListener started");
new ClassPathXmlApplicationContext(CONFIG);
}
}
完整的堆栈跟踪:
2015-03-09 10:06:52,879 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@644b27ad: startup date [Mon Mar 09 10:06:52 CET 2015]; root of context hierarchy>
2015-03-09 10:06:52,931 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [launch-context.xml]>
2015-03-09 10:06:53,111 INFO [org.springframework.context.annotation.ClassPathBeanDefinitionScanner] - <JSR-330 'javax.inject.Named' annotation found and supported for component scanning>
2015-03-09 10:06:53,187 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/datasource-beans.xml]>
2015-03-09 10:06:53,228 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/job.xml]>
2015-03-09 10:06:53,303 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'transactionManager': replacing [Generic bean: class [org.springframework.jdbc.datasource.DataSourceTransactionManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/datasource-beans.xml]] with [Generic bean: class [org.springframework.batch.support.transaction.ResourcelessTransactionManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:53,321 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'myJob': replacing [Generic bean: class [org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.springframework.batch.core.configuration.xml.JobParserJobFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]>
2015-03-09 10:06:53,326 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/queue.xml]>
2015-03-09 10:06:54,043 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/integration.xml]>
2015-03-09 10:06:54,367 INFO [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer] - <Loading properties file from URL [file:/.../externalConfig/dev/application.properties]>
2015-03-09 10:06:54,386 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'stepListener': replacing [Generic bean: class [package.StepListener]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:54,386 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'filradReader': replacing [Generic bean: class [org.springframework.batch.item.file.FlatFileItemReader]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:54,387 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'multiResourceWriter': replacing [Generic bean: class [org.springframework.batch.item.file.MultiResourceItemWriter]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:54,387 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'filradXmlWriter': replacing [Generic bean: class [org.springframework.batch.item.xml.StaxEventItemWriter]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/spring/job.xml]] with [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [META-INF/spring/job.xml]]>
2015-03-09 10:06:54,391 INFO [org.springframework.integration.config.xml.DefaultConfiguringBeanFactoryPostProcessor] - <No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.>
2015-03-09 10:06:54,392 INFO [org.springframework.integration.config.xml.DefaultConfiguringBeanFactoryPostProcessor] - <No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.>
2015-03-09 10:06:54,402 INFO [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - <JSR-330 'javax.inject.Inject' annotation found and supported for autowiring>
2015-03-09 10:06:54,415 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6112f78c: defining beans [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.jdbc.datasource.init.DataSourceInitializer#0,dataSource,transactionManager,jobLauncher,org.springframework.batch.core.scope.internalStepScope,org.springframework.beans.factory.config.CustomEditorConfigurer,org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor,jobRepository,filradSetMapper,stepListener,jobListener,callbackHandler,suffixCreator,filradProcessor,textToXmlStep,addToQueueStep,myJob,multiResourceReader,filradReader,filradCompositeLineMapper,taxiTokenizer,biljettTokenizer,rullstolTokenizer,multiResourceWriter,filradXmlWriter,filradTyperValidMarshaller,addFilesToQueueTasklet,connectionFactory,destination,jmsTemplate,messageProducer,messageListener,org.springframework.jms.listener.DefaultMessageListenerContainer#0,channelInitializer,$autoCreateChannelCandidates,org.springframework.integration.internalDefaultConfiguringBeanFactoryPostProcessor,outboundJobRequestChannel,jobLaunchReplyChannel,inboundFileChannel,org.springframework.batch.integration.launch.JobLaunchingGateway#0,org.springframework.integration.config.ConsumerEndpointFactoryBean#0,org.springframework.integration.handler.LoggingHandler#0,org.springframework.integration.config.ConsumerEndpointFactoryBean#1,org.springframework.integration.config.TransformerFactoryBean#0,org.springframework.integration.config.ConsumerEndpointFactoryBean#2,ftpClientFactory,ftpChannel,org.springframework.scheduling.support.PeriodicTrigger#0,ftpInbound,ftpController,scopedTarget.stepListener,scopedTarget.filradReader,scopedTarget.multiResourceWriter,scopedTarget.filradXmlWriter,nullChannel,errorChannel,_org.springframework.integration.errorLogger,taskScheduler,org.springframework.integration.config.IdGeneratorConfigurer#0]; root of factory hierarchy>
2015-03-09 10:06:54,597 INFO [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] - <Executing SQL script from URL [jar:file:/C:/Users/jesleh/.m2/repository/org/springframework/batch/spring-batch-core/2.2.3.RELEASE/spring-batch-core-2.2.3.RELEASE.jar!/org/springframework/batch/core/schema-drop-hsqldb.sql]>
2015-03-09 10:06:54,601 INFO [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] - <Done executing SQL script from URL [jar:file:/C:/Users/jesleh/.m2/repository/org/springframework/batch/spring-batch-core/2.2.3.RELEASE/spring-batch-core-2.2.3.RELEASE.jar!/org/springframework/batch/core/schema-drop-hsqldb.sql] in 4 ms.>
2015-03-09 10:06:54,601 INFO [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] - <Executing SQL script from URL [jar:file:/C:/Users/jesleh/.m2/repository/org/springframework/batch/spring-batch-core/2.2.3.RELEASE/spring-batch-core-2.2.3.RELEASE.jar!/org/springframework/batch/core/schema-hsqldb.sql]>
2015-03-09 10:06:54,614 INFO [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] - <Done executing SQL script from URL [jar:file:/C:/Users/jesleh/.m2/repository/org/springframework/batch/spring-batch-core/2.2.3.RELEASE/spring-batch-core-2.2.3.RELEASE.jar!/org/springframework/batch/core/schema-hsqldb.sql] in 12 ms.>
2015-03-09 10:06:54,663 INFO [org.springframework.batch.core.repository.support.JobRepositoryFactoryBean] - <No database type set, using meta data indicating: HSQL>
2015-03-09 10:06:54,797 INFO [org.springframework.batch.core.launch.support.SimpleJobLauncher] - <No TaskExecutor has been set, defaulting to synchronous executor.>
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
2015-03-09 10:06:55,027 INFO [org.springframework.oxm.jaxb.Jaxb2Marshaller] - <Creating JAXBContext with classes to be bound [class package.Filrad]>
2015-03-09 10:06:55,490 INFO [org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler] - <Initializing ExecutorService 'taskScheduler'>
2015-03-09 10:06:55,498 INFO [org.springframework.context.support.DefaultLifecycleProcessor] - <Starting beans in phase -2147483648>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <Adding {message-handler} as a subscriber to the 'outboundJobRequestChannel' channel>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.channel.DirectChannel] - <Channel 'outboundJobRequestChannel' has 1 subscriber(s).>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <started org.springframework.integration.config.ConsumerEndpointFactoryBean#0>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <Adding {logging-channel-adapter} as a subscriber to the 'jobLaunchReplyChannel' channel>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.channel.DirectChannel] - <Channel 'jobLaunchReplyChannel' has 1 subscriber(s).>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <started org.springframework.integration.config.ConsumerEndpointFactoryBean#1>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <Adding {transformer} as a subscriber to the 'ftpChannel' channel>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.channel.DirectChannel] - <Channel 'ftpChannel' has 1 subscriber(s).>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <started org.springframework.integration.config.ConsumerEndpointFactoryBean#2>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.channel.PublishSubscribeChannel] - <Channel 'errorChannel' has 1 subscriber(s).>
2015-03-09 10:06:55,498 INFO [org.springframework.integration.endpoint.EventDrivenConsumer] - <started _org.springframework.integration.errorLogger>
2015-03-09 10:06:55,499 INFO [org.springframework.context.support.DefaultLifecycleProcessor] - <Starting beans in phase 2147483647>
2015-03-09 10:06:55,755 INFO [org.springframework.integration.endpoint.SourcePollingChannelAdapter] - <started ftpInbound>
2015-03-09 10:07:10,041 ERROR [org.springframework.integration.handler.LoggingHandler] - <org.springframework.expression.spel.SpelEvaluationException: EL1030E:(pos 0): The operator 'ADD' is not supported between objects of type 'java.lang.String' and 'null'
at org.springframework.expression.spel.ExpressionState.operate(ExpressionState.java:191)
at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:59)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:102)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.generateLocalFileName(AbstractInboundFileSynchronizer.java:228)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.copyFileToLocalDirectory(AbstractInboundFileSynchronizer.java:174)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.synchronizeToLocalDirectory(AbstractInboundFileSynchronizer.java:150)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizingMessageSource.receive(AbstractInboundFileSynchronizingMessageSource.java:146)
at org.springframework.integration.endpoint.SourcePollingChannelAdapter.receiveMessage(SourcePollingChannelAdapter.java:111)
at org.springframework.integration.endpoint.AbstractTransactionSynchronizingPollingEndpoint.doPoll(AbstractTransactionSynchronizingPollingEndpoint.java:67)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.call(AbstractPollingEndpoint.java:146)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.call(AbstractPollingEndpoint.java:144)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:236)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.run(ErrorHandlingTaskExecutor.java:52)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:49)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:231)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
作业本身(读取 .txt 文件并将其转换为 xml 输出)有效,我 运行 单独执行了该步骤没有问题。问题似乎在于从 FTP 区域读取文件。我也试过用谷歌搜索这个问题,但找不到任何东西。我意识到这是一个很大的要求,但如果有人有任何想法,我会非常高兴。谢谢。
我已经把它作为答案了。
第一个错误是因为在执行操作时传递了 null local-filename-generator-expression="+#this
”。尝试提供值似乎可以解决问题 local-filename-generator-expression="'sample'+#this"
。
您评论中的第二个错误是因为方法签名。下面的方法将 Message<File> message
作为参数,而它的调用者将 io.File 作为参数传递。因此错误。根据提供的信息,我不确定来电者在哪里,但这应该给你错误的要点。
public JobLaunchRequest toRequest(Message<File> message) {
JobParametersBuilder jobParametersBuilder =
new JobParametersBuilder();
我用
解决了这个问题 <int:service-activator id="runJob" method="launch" input-channel="outboundJobRequestChannel"
output-channel="statuses">
<bean class="org.springframework.batch.integration.launch.JobLaunchingMessageHandler">
<constructor-arg ref="jobLauncher"/>
</bean>
</int:service-activator>
而不是
<batch-int:job-launching-gateway request-channel="outboundJobRequestChannel"
reply-channel="jobLaunchReplyChannel"
job-launcher="jobLauncher" />
然后将 toRequest 方法的参数更改为(java.io.File 文件)。现在一切都按预期工作。感谢@minion 的帮助。