2017-04-14 33 views
0

私はSpring Batch Taskletで電子メールを送信します。チェックされていない例外の場合、バッチ処理が続行されます

SMTPサーバーがダウンしているので、チェックが外されていますMailSendException例外が発生しました。移行

次のステップは、(電子メール送信から)として宣言されている:

FlowBuilder<Flow> flowBuilder = new FlowBuilder<Flow>("myFlow") 
     .from(sendNotificationStep()).next(nextStep()); 

nextStep()あってもチェックされない例外の場合に実行されます。

チェックされていない例外を無視するSpring Batch Frameworkの通常の動作ですか?

この例外は無視され、ログに記録されません(私はrootロガーをWARNに設定しました)。 why does transaction roll back on RuntimeException but not SQLException

UPDATEに報告

やや反対の現象がデバッガとステッピング後、私は内側端:

public class SimpleFlow implements Flow, InitializingBean { 

    public FlowExecution resume(String stateName, FlowExecutor executor) throws FlowExecutionException { 

     state = nextState(stateName, status, stepExecution); 

statusstatesendNotificationStepnextState()リターンnextStepで、FAILEDあります。

catchresumeである:

catch (Exception e) { 
    executor.close(new FlowExecution(stateName, status)); 
    throw new FlowExecutionException(String.format("Ended flow=%s at state=%s with exception", name, 
                stateName), e); 
} 

しかしによって以前に処理した例外:

public abstract class AbstractStep implements Step, InitializingBean, BeanNameAware { 
    public final void execute(StepExecution stepExecution) throws JobInterruptedException, 

    catch (Throwable e) { 
     stepExecution.upgradeStatus(determineBatchStatus(e)); 
     exitStatus = exitStatus.and(getDefaultExitStatusForFailure(e)); 
     stepExecution.addFailureException(e); 
     if (stepExecution.getStatus() == BatchStatus.STOPPED) { 
      logger.info(String.format("Encountered interruption executing step %s in job %s : %s", name, stepExecution.getJobExecution().getJobInstance().getJobName(), e.getMessage())); 
      if (logger.isDebugEnabled()) { 
       logger.debug("Full exception", e); 
      } 
     } 
     else { 
      logger.error(String.format("Encountered an error executing step %s in job %s", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); 
     } 
    } 

バッチ管理者はABANDONEDとして問題のあるステップを示しています。動作を再現する

UPDATE 3フル機能の例を(刺しを提供するためのサバー・カーンに感謝!):

@SpringBootApplication 
@Configuration 
@EnableBatchProcessing 
public class X { 

    private static final Logger logger = LoggerFactory.getLogger(X.class); 

    @Autowired 
    private JobBuilderFactory jobs; 

    @Autowired 
    private StepBuilderFactory steps; 

    @Bean 
    protected Tasklet tasklet1() { 
     return (StepContribution contribution, ChunkContext context) -> { 
      logger.warn("Inside tasklet1"); 
      throw new IllegalStateException("xxx"); 
      //return RepeatStatus.FINISHED; 
     }; 
    } 

    @Bean 
    protected Tasklet tasklet2() { 
     return (StepContribution contribution, ChunkContext context) -> { 
      logger.warn("Inside tasklet2"); 
      return RepeatStatus.FINISHED; 
     }; 
    } 

    @Bean 
    public Job job() throws Exception { 
     Flow flow = new FlowBuilder<Flow>("myFlow").from(firstStep()).on("*").to(nextStep()).end(); 
     return this.jobs.get("job").start(flow).end().build(); 
    } 

    @Bean 
    protected Step firstStep() { 
     return this.steps.get("firstStep").tasklet(tasklet1()).build(); 
    } 

    @Bean 
    protected Step nextStep() { 
     return this.steps.get("nextStep").tasklet(tasklet2()).build(); 
    } 

    public static void main(String[] args) throws Exception { 
     System.exit(SpringApplication.exit(SpringApplication.run(X.class, args))); 
    } 
} 
+0

'sendNotificationStep()'の完全なコードを表示してください。 –

+0

他の例外は無視されませんか?誤ってskippable-exception-classes(またはFaultTolerantStepBuilder.skip())を使用して春バッチ設定で例外をスキップすることはありませんか? – qtips

答えて

1

いいえ、それは通常の春のバッチ動作ではありませんし、私は何を見たことがありません説明しています。

私は、バッチ・バッチでは、スローされた例外がチェックされているかチェックされていないかの区別はしていないと思います。フローは、逐次実行の場合に例外がスローされた時点で停止します。

明らかに、パラレルステップまたは実行が行われている場合、他の部分の実行は継続されます。

コードのどこかで例外が処理されている可能性があります(サイレントモード)。そのため、実行が次のステップに進んでいる可能性があります。

私は自分の仕事と仕事にスローされる例外の両方のカテゴリーは、私がスキップリトライおよびその他の例外処理メカニズムをコード化して、それが春のバッチとは何の関係もない道に振る舞う見てきました - それは純粋なJavaのですが。

あなたの質問が誤解されているかどうかはわかりませんが、以下のサンプルコードはあなたの説明どおりに動作しません。Step-1はチェックされていない例外をスローし、実行は私がとにかくそれを処理していないのでそこで停止しました。

@SpringBootApplication(exclude = { DataSource.class, 
     DataSourceAutoConfiguration.class }) 
@Configuration 
@EnableBatchProcessing 
public class AppConfiguration { 

    private static final Logger logger = LoggerFactory.getLogger(AppConfiguration.class); 

    @Autowired 
    private JobBuilderFactory jobs; 

    @Autowired 
    private StepBuilderFactory steps; 

    @Autowired 
    private JavaMailSender javaMailSender; 

    @Bean 
    protected Tasklet tasklet() { 

     return new Tasklet() { 
      @Override 
      public RepeatStatus execute(StepContribution contribution, 
        ChunkContext context) { 


       MimeMessage message = javaMailSender.createMimeMessage(); 
       javaMailSender.send(message); 

       return RepeatStatus.FINISHED; 

      } 
     }; 

    } 

    @Bean 
    protected Tasklet tasklet2() { 

     return new Tasklet() { 
      @Override 
      public RepeatStatus execute(StepContribution contribution, 
        ChunkContext context) { 

       return RepeatStatus.FINISHED; 
      } 
     }; 

    } 

    @Bean 
    public Job job() throws Exception { 

     Flow flow = new FlowBuilder<Flow>("myFlow").from(step1()).next(nextStep()).end(); 
     return this.jobs.get("job").start(flow).end().build(); 

    } 

    @Bean 
    protected Step step1() { 
     return this.steps.get("step1").tasklet(tasklet()).build(); 
    } 

    @Bean 
    protected Step nextStep() { 
     return this.steps.get("nextStep").tasklet(tasklet2()).build(); 
    } 

    public static void main(String[] args) throws Exception { 
     System.exit(SpringApplication.exit(SpringApplication.run(AppConfiguration.class, args))); 
    } 

} 

希望すると助かります!

+0

あなたの例の 'from(step1())。on(" * ")。〜(nextStep())' 'nextStep()の'原因に 'from(step1())。next '実行! 'AbstractJob#getDefaultExitStatusForFailure()'をデバッグするときに 'ExitStatus.FAILED'を設定し、' .on( "*") 'がこの文字列にマッチします。 – gavenkoa

+0

'on(" * ")'は、前のステップで何が起きたかに関係なく、ステップ-2の実行を開始します。それはあなたの質問で尋ねたように、春のバッチ例外処理とは関係ありません。 –

+0

それは驚くべき振る舞いでした。公式のSpring Batchドキュメントでは、例外の場合に何が起こるべきかを明示的に述べていません。デバッガを踏むと、そのようなタスクは 'ExitStatus.FAILED'ステータスを受け取ることが示されました。それも明示的に文書化されていません。 – gavenkoa

関連する問題