我有一个使用spring任务调度和批处理作业的java应用程序。我依靠MultiResourceItemReader
中的job
来读取目录中的某些文件,处理它们并删除这些文件。外部进程负责定期在该目录中放置新文件。但问题是,每次job
运行时,它都会尝试读取启动应用程序时出现的相同文件资源,因此会失败,因为这些资源已经消失,现在有新文件存在。
问题是,如何配置应用程序,以便为给定job
的每个计划执行评估资源属性。
相关豆类粘贴在下面:
<bean id="multiResourceReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
<property name="resources" value="file:/opt/data/*.csv" />
<property name="delegate" ref="testFlatFileItemReader" />
</bean>
<batch:job id="MyJob">
<batch:step id="readandstore">
<batch:tasklet>
<batch:chunk reader="multiResourceReader" writer="oracleItemWriter" commit-interval="10" />
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="runScheduler" class="com.myapp.Scheduler">
<property name="jobLauncher" ref="jobLauncher" />
<property name="job" ref="MyJob" />
</bean>
<task:scheduled-tasks>
<task:scheduled ref="runScheduler" method="run" cron="*/30 * * * * *" />
</task:scheduled-tasks>
答案 0 :(得分:4)
我设法解决了我自己发布的问题,因为它已经收到了近一周的回复。
我删除了multiResourceReader
的资源属性,并在实现StepListener
的{{1}}下的监听器中添加了<batch:tasklet>
。此侦听器有两个方法,一个在步执行之前调用,另一个在步执行之后调用。 StepExecutionListener
接受名为StepListener
的属性,其值与之前为filePattern
的resources属性提供的值类似。以下是更新的bean的外观:
multiResourceReader
以下是com.myapp.StepListener的样子:
<batch:job id="MyJob">
<batch:step id="readandstore">
<batch:tasklet>
<batch:chunk reader="multiResourceReader" writer="oracleItemWriter" commit-interval="10" />
<batch:listeners>
<batch:listener ref="StepListener" />
</batch:listeners>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="multiResourceReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
<property name="delegate" ref="csvFileItemReader" />
</bean>
<bean id="StepListener" class="com.myapp.StepListener">
<property name="filePattern" value="file:/opt/data/*.csv" />
</bean>
答案 1 :(得分:3)
bean multiResourceReader的范围是单例,因此每次只创建1。创建该bean时,将解析资源的值。
如果将bean multiResourceReader的范围设置为step,它也应该解决您的问题。然后每次执行该步骤时都会创建一个新bean。
答案 2 :(得分:1)
尝试在名为“multiResourceReader”的配置bean中添加标记“step”:
答案 3 :(得分:1)
另一种选择是扩展MultiResourceItemReader
并覆盖open()
方法,并在调用setResources()
方法之前调用super.open()
。
public class CustomMultiItemReader<T> extends MultiResourceItemReader<T> {
private static final Log logger = LogFactory.getLog(PrestoMultiItemReader.class);
private String filePattern;
public CustomMultiItemReader() {
super();
}
@Override
public void open(ExecutionContext executionContext) {
Assert.notNull(filePattern, "filePattern must be set");
try {
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
Resource[] resources = patternResolver.getResources(filePattern);
super.setResources(resources);
} catch (IOException e) {
logger.error("No resources to read.", e);
}
super.open(executionContext);
}
public void setFilePattern(String filePattern) {
this.filePattern = filePattern;
}
}
您可以按以下方式致电CustomMultiItemReader
。您无需致电setResources()
。
public CustomMultiItemReader<T> customMultiItemReader() {
String filePattern = "file:/...";
CustomMultiItemReader<T> reader = new CustomMultiItemReader<T>();
reader.setDelegate(reader()); //reader to delegate here
reader.setFilePattern(filePattern);
reader.setStrict(true);
return reader;
}
答案 4 :(得分:0)
我遇到了同样的问题,但是我用另一个方法解决了,也许会有所帮助,我正在使用FlatFileItemReader,但问题是相同的。
解决方案是在属性资源中使用带有处理jobParams的bean的ref,这样,每次重新启动步骤时,它都是一个具有新值的新实例,以下代码是我的操作方式:
<bean id="customFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="resource" ref="customFile"/><!-- avoid use directly jobParams here -->
<property name="linesToSkip" value="0" />
<property name="encoding" value="ISO-8859-1" />
<property name="comments" value="*, \u001A" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value=";" />
</bean>
</property>
<property name="fieldSetMapper">
<bean class="br.com.sample.batch.CustomFieldSetMapperSIAW"/>
</property>
</bean>
</property>
<bean id="customFile" class="org.springframework.core.io.FileSystemResource" scope="step">
<constructor-arg value="#{jobParameters[arquivoGSIN]}"></constructor-arg>