Spring Batch和JobInstanceAlreadyCompleteException:

时间:2016-03-05 01:54:05

标签: java spring spring-batch

我有一个Spring Batch作业,它通过SFTP从远程Linux服务器检索文件。 远程服务器上的目录是一个包含七天文件(~400个文件)的存档。这些文件的大小相对较小。

Spring Batch知道哪些文件已被处理。

当我启动应用程序时。第一次,Spring Batch tasklet检索文件然后,Spring Batch为它已经处理的每个文件生成一个例外:

E.g。

由以下原因引起:org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException:作业实例已存在,并且对parameters = {input.file.url = file:///blahblahblah.txt}已完成。

这会导致处理过程中的大量延误。

在第一次之后,在随后的sftp检索文件时,没有例外,因此没有延迟(可能是Spring Batch已生成已处理文件的内部哈希列表)。

  1. 在Transformer类中,我应该检查文件是否存在于本地,并且仅对尚未处理的新文件调用JobLaunchRequest()?

    / **

    • 将BAI文件转换为Spring Batch作业启动请求 * / public class FileMessageToJobRequestTransformer { public static final Logger LOGGER = LoggerFactory.getLogger(FileMessageToJobRequestTransformer.class); 私人工作;

      private String fileParameterName;

      public void setJob(Job job){     this.job =工作; }

      public void setFileParameterName(String fileParameterName){     LOGGER.debug("文件参数名称:{}",fileParameterName);     this.fileParameterName = fileParameterName; }

      @Transformer public JobLaunchRequest transform(Message message){     LOGGER.debug("文件消息:{}",message);     JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();

      jobParametersBuilder.addString(fileParameterName,
              "file://" + message.getPayload().getAbsolutePath());
      
      LOGGER.debug("Job params: {}", jobParametersBuilder.toJobParameters());
      
      return new JobLaunchRequest(job, jobParametersBuilder.toJobParameters());
      

      } }

  2. 有没有办法可以捕捉异常?

  3. JobInstanceAlreadyCompleteException

    1. 我应该设置retry-limit =" 1"和skip-limit =" 1"在SftpBaiParserJobBridge-context.hml?
    2. <!-- When getting a new BAI file, transform into spring batch job request --> <int:transformer id="fileMessageToJobRequestTransformer" input-channel="inboundFileChannel" output-channel="outboundJobRequestChannel" method="transform"> <bean class="com.distributedfinance.mbi.bai.transformer.FileMessageToJobRequestTransformer"> <property name="job" ref="baiParseJob"/> <property name="fileParameterName" value="input.file.url"/> </bean> <int:poller fixed-rate="10000"/> </int:transformer>

      附加addDate()允许多次处理文件。 现在数据库中有重复数据。

      jobParametersBuilder.addString(fileParameterName,
                      "file://" + message.getPayload().getAbsolutePath())).addDate("rundate", new Date()).toJobParameters();
      

      enter image description here 谢谢!

      1. 我是否可以通过内部的JobExplorer界面查询存储库来确定文件是否已经处理过&#39; @Transformer 公共JobLaunchRequest转换(消息消息)&#39;如果文件已被处理,则返回null?
      2. E.g。

        public interface JobExplorer {
        
            List<JobInstance> getJobInstances(String jobName, int start, int count);
        
            JobExecution getJobExecution(Long executionId);
        
            StepExecution getStepExecution(Long jobExecutionId, Long stepExecutionId);
        
            JobInstance getJobInstance(Long instanceId);
        
            List<JobExecution> getJobExecutions(JobInstance jobInstance);
        
            Set<JobExecution> findRunningJobExecutions(String jobName);
        }
        
        1. 如何捕获异常?

          引起:org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException:作业实例已经存在并且已完成参数= {input.file.url = file:/// home / dlaxer / dfc-bank-integration /mbi-application/bai/download/BAI_Intraday160302070054471.txt}。如果要再次运行此作业,请更改参数。         在org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:126)         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)         at java.lang.reflect.Method.invoke(Method.java:498)         在org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)         在org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)         在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)         at org.springframework.transaction.interceptor.TransactionInterceptor $ 1.proceedWithInvocation(TransactionInterceptor.java:99)         at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)         at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)         在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)         在org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean $ 1.invoke(AbstractJobRepositoryFactoryBean.java:172)         在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)         在org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)         在com.sun.proxy。$ Proxy113.createJobExecution(未知来源)         在org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:125)         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)         at java.lang.reflect.Method.invoke(Method.java:498)         在org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)         在org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)         在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)         在org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration $ PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)         在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)         在org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)         在com.sun.proxy。$ Proxy114.run(未知来源)         在org.springframework.batch.integration.launch.JobLaunchingMessageHandler.launch(JobLaunchingMessageHandler.java:50)         在org.springframework.batch.integration.launch.JobLaunchingGateway.handleRequestMessage(JobLaunchingGateway.java:76)         ......还有35个

2 个答案:

答案 0 :(得分:1)

我看到你在作业启动器中只传递一个参数作为&#34;文件名&#34;。 一旦启动了作业启动器,它将从存储库BATCH_JOB_EXECUTION表中查询并检查上次处理的作业的状态。 在您当前的作业执行输入参数与先前执行的作业相同,批处理状态&amp;退出代码=已完成,然后您将获得JobInstanceAlreadyCompleteException。您应该尝试在每次执行时始终传递唯一的Parmae​​ters。只需将当前时间作为参数传递并尝试

JobParameters jobparam =   new JobParametersBuilder().addString(fileParameterName, "file://" + message.getPayload().getAbsolutePath())
                        .addDate("rundate", new Date()).toJobParameters();

JobExecution execution = jobLauncher.run(job, jobparam);
         catch (Exception e) {
             if ( e instanceof JobInstanceAlreadyCompleteException){
                 System.out.println("Raj*************");
             }
  • 2是的,你可以像这样处理

    catch(例外e){              if(e instanceof JobInstanceAlreadyCompleteException){                  System.out.println(&#34;需要处理*************&#34;);              }

答案 1 :(得分:1)

3 - 我应该设置retry-limit =&#34; 1&#34;和skip-limit =&#34; 1&#34;。
 回答它取决于您的要求。你要忽略它的异常和次数意味着=跳过限制,并且在吸盘过程中想要重复同一步骤,特殊异常意味着重试。 我们可以用例子更好地理解。如果我想读取一些平面文件,并且文件有可能有错误的输入记录,这可能导致flatFileException  我想忽略它并顺利处理我的文件然后我的配置看起来像这样。 我可以在作业执行期间跳过最多20条记录,如果批次收到异常,任何记录都应该至少尝试2次。

 <chunk reader="flatFileItemReader" writer="itemWriter"
             commit-interval="1" skip-limit="20" retry-limit="2">
         <skippable-exception-classes>
            <include class="org.springframework.batch.item.file.FlatFileParseException"/>
         </skippable-exception-classes>