如何确保MultiResourceItemReader在每次执行作业时刷新资源

时间:2014-02-19 12:19:45

标签: java spring scheduled-tasks task

我有一个使用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>

5 个答案:

答案 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>