我正在使用spring batch模块来处理目录中的csv文件。目录可能包含具有特定扩展的多个文件,我使用MultiResourceItemReader来读取文件。 作业将接收3个作业参数:read_from_directory,move_to_directory和default_user_id。对于所有作业运行,所有这些参数将保持相同。 read_from_directory将包含 多个csv文件和作业应该一个接一个地处理这些文件。我面临的问题是,由于作业参数相同,我第二次运行作业时会得到JobInstanceAlreadyCompleteException。我知道通过使用额外的时间戳参数来使作业参数唯一,可以克服这个问题。但是,由于添加timestamp参数将使每个作业实例都是唯一的,我不希望使用此方法,因为它会在使我的作业重新启动时产生问题。 所以我想提出一些建议,
如何在不使用timestamp参数的情况下使每个作业实例都是唯一的。
在这种情况下如何重新启动作业?将添加' restartable =" true"'足够或者我需要一些额外的配置/编码。我在这里有点困惑因为job会从目录中读取多个文件。因此,如果作业失败,例如,由于其中一个文件中的记录不正确,我如何从它离开的位置重新启动相同的作业?我已将作业配置为在一定时间间隔后使用调度程序定期运行。因此,如果作业失败然后我纠正了csv文件中的错误,那么作业会在下次运行时从停止的位置开始吗?
请从我的配置中找到以下相关部分:
<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>
谢谢。
答案 0 :(得分:1)
Spring Batch有两个与作业相关的不同概念&#34;运行&#34;,JobInstance
和JobExecution
。
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提供了一个开箱即用的计数器或者你可以使用时间戳)。
您可以在此处的文档中详细了解JobInstance
和JobExecution
的概念:http://docs.spring.io/spring-batch/trunk/reference/html/domain.html#domainJob
答案 1 :(得分:0)
问题1:您可以使用自己的逻辑实现JobParameterIncrementer
下一个实例的内容以及您希望如何增加参数。然后,您可以根据逻辑运行下一个实例的下一个实例,然后只需运行,您将重新启动最新实例。如果您使用CommandLineJobRunner
开始工作,则可以通过-next
运行下一个实例,如果以编程方式执行,则可以使用JobOperator#startNextInstance(String jobName)
。 JobParameterIncrementer
example为documentation。
问题2:对于可重启性,添加restartable="true"
应该可以解决问题。 FlatFileItemReader
是读取文件的委托,扩展AbstractItemCountingItemStreamItemReader
,在读取文件时保存状态。至于MultiResourceItemReader
,您可以在{{3}}上看到它说:
使用setComparator(Comparator)对输入资源进行排序,以确保在重新启动方案中的作业运行之间保留资源排序。
所以这意味着资源列表是有序的,每个资源都被委托给FlatFileItemReader
,这样可以在运行之间保留顺序和计数。