spring batch - multiResourceItemReader:如何使作业参数唯一并重新启动作业

时间:2015-04-06 08:17:04

标签: spring spring-batch

我正在使用spring batch模块来处理目录中的csv文件。目录可能包含具有特定扩展的多个文件,我使用MultiResourceItemReader来读取文件。 作业将接收3个作业参数:read_from_directory,move_to_directory和default_user_id。对于所有作业运行,所有这些参数将保持相同。 read_from_directory将包含 多个csv文件和作业应该一个接一个地处理这些文件。我面临的问题是,由于作业参数相同,我第二次运行作业时会得到JobInstanceAlreadyCompleteException。我知道通过使用额外的时间戳参数来使作业参数唯一,可以克服这个问题。但是,由于添加timestamp参数将使每个作业实例都是唯一的,我不希望使用此方法,因为它会在使我的作业重新启动时产生问题。 所以我想提出一些建议,

  1. 如何在不使用timestamp参数的情况下使每个作业实例都是唯一的。

  2. 在这种情况下如何重新启动作业?将添加' restartable =" true"'足够或者我需要一些额外的配置/编码。我在这里有点困惑因为job会从目录中读取多个文件。因此,如果作业失败,例如,由于其中一个文件中的记录不正确,我如何从它离开的位置重新启动相同的作业?我已将作业配置为在一定时间间隔后使用调度程序定期运行。因此,如果作业失败然后我纠正了csv文件中的错误,那么作业会在下次运行时从停止的位置开始吗?

  3. 请从我的配置中找到以下相关部分:

    <batch:job id="testJob" restartable="true">
            <batch:step id="step1">
                <batch:tasklet>
                    <batch:chunk reader="multiResourceItemReader" writer="fileWriter"
                        commit-interval="1">
                    </batch:chunk>
                </batch:tasklet>
            </batch:step>
        </batch:job>
    
        <bean id="fileWriter" class="com.ivish.TestFileWriter" />
        <bean id="multiResourceItemReader" class="org.springframework.batch.item.file.MultiResourceItemReader" scope="step">
            <property name="resources" value="file:#{jobParameters['read_from_directory']}/*.csv" />
            <property name="delegate" ref="fileReader" />
        </bean>
    
        <bean id="fileReader" class="com.ivish.TestFileReader" scope="step">
            <property name="delegate" ref="delegateFileReader" />
            <property name="moveToDirectory" value="#{jobParameters['move_to_directory']}" />
        </bean>
        <bean id="delegateFileReader" class="org.springframework.batch.item.file.FlatFileItemReader">
            <property name="lineMapper">
                <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                    <property name="lineTokenizer" ref="fileTokenizer" />
                    <property name="fieldSetMapper">
                        <bean
                            class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper" />
                    </property>
                </bean>
            </property>
        </bean>         
    

    谢谢。

2 个答案:

答案 0 :(得分:1)

Spring Batch有两个与作业相关的不同概念&#34;运行&#34;,JobInstanceJobExecution

JobInstance是逻辑运行的概念。它由一组唯一的识别作业参数识别。在您的示例中,我希望read_from_directory,move_to_directory和default_user_id的每个组合都有一个JobInstance

另一个概念是JobExecution。这表示实际运行。因此,例如,如果运行read_from_directory,move_to_directory和default_user_id的组合并且它通过,JobInstance将有一个子JobExecution。但是,如果第一次尝试(第一次JobExecution)失败,您可以重新启动作业。重新启动会在现有JobExecution下创建一个新的JobInstance(在一次逻辑运行下运行两次)。

考虑到上述情况,每个JobInstance通过read_from_directory,move_to_directory,default_user_id和某种类型的运行ID的组合将是唯一的(Spring Batch提供了一个开箱即用的计数器或者你可以使用时间戳)。

您可以在此处的文档中详细了解JobInstanceJobExecution的概念:http://docs.spring.io/spring-batch/trunk/reference/html/domain.html#domainJob

答案 1 :(得分:0)

问题1:您可以使用自己的逻辑实现JobParameterIncrementer下一个实例的内容以及您希望如何增加参数。然后,您可以根据逻辑运行下一个实例的下一个实例,然后只需运行,您将重新启动最新实例。如果您使用CommandLineJobRunner开始工作,则可以通过-next运行下一个实例,如果以编程方式执行,则可以使用JobOperator#startNextInstance(String jobName)JobParameterIncrementer exampledocumentation

问题2:对于可重启性,添加restartable="true"应该可以解决问题。 FlatFileItemReader是读取文件的委托,扩展AbstractItemCountingItemStreamItemReader,在读取文件时保存状态。至于MultiResourceItemReader,您可以在{{3}}上看到它说:

  

使用setComparator(Comparator)对输入资源进行排序,以确保在重新启动方案中的作业运行之间保留资源排序。

所以这意味着资源列表是有序的,每个资源都被委托给FlatFileItemReader,这样可以在运行之间保留顺序和计数。