개발/Spring Batch

Spring Batch decision으로 step 결정하기

신매력 2015. 10. 29. 16:40

보통은 step1 수행 -> step2 수행 -> step3 수행


이렇게 순차적으로 수행한다.

실행되는 스텝이 내가 할일 끝나고 나면 다음 스텝을 지정해서 다음 스텝을 실행시킨다.




이번에 포스팅할 예제는

step1 step2 가 있을 때 이런 규칙이 있다고 치자.


- step2만 실행

- step1 -> step2   : step1가 성공해야만 step2를 실행한다.



skip1를 스킵할지 말지는 skipFlag의 값으로 분기할 것이다.


decision 을 이용해서 스텝을 결정할 수 있다.

설정은 아래와 같음.


job.xml

<batch:job id="testJob">

<batch:decision decider="decider1" id="decision1">

<batch:next on="STEP_1" to="step1"/>

<batch:next on="STEP_2" to="step2"/>

</batch:decision>

<batch:step id="step1" next="decision2">

<batch:tasklet ref="step1Tasklet" />

</batch:step>

<batch:decision decider="decider2" id="decision2">

<batch:next on="STEP_2" to="step2"/>

<batch:end on="FAILED" />

</batch:decision>

<batch:step id="step2">

<batch:tasklet ref="step2Tasklet" />

</batch:step>

</batch:job>


<bean id="decider1" class="com.test.job.Decider1"/>

<bean id="decider2" class="com.test.job.Decider2" />


<bean id="step1Tasklet" class="com.test.job.Step1Tasklet" scope="step">

<property name="skipFlag" value="#{jobParameters['skipFlag']}" />

</bean>


<bean id="step2Tasklet" class="com.test.job.Step2Tasklet" scope="step" />



* step1을 스킵하고 step2만 실행하는 경우


decider1에서 skipFlag가 true이면, step2로 갈 수 있도록 한다.



* step1 -> step2 인 경우


decider1에서 skipFlag가 false이면, step1를 실행하도록 한다.

step1가 실행되고 나면 next 속성을 통해 decider2를 실행시킨다.


step1 tasklet에서 성공/실패 여부를 세팅해놨고,

그 값을 통해 FAILED이면 step2 실행 안하고 끝내버리고

STEP_2라면 step2를 실행시킨다.




decider에서 확인하고 결정하는 

<batch:next on="STEP_1" to="step1"/>

이 문법은 어떤 원리인가?


아래 코드를 보자. 


step1을 스킵할 것인지 말 것인지 결정하는 decider1이다.



Decider1.java

public class Decider1 implements JobExecutionDecider {

@Override

public FlowExecutionStatus decide(JobExecution jobExecution,

StepExecution stepExecution) {

String skipFlag = jobExecution.getJobParameters().getString("skipFlag");

if (StringUtils.equals(skip, "true")) {

return new FlowExecutionStatus("STEP_2"); // 임의의 스트링 값

}

return new FlowExecutionStatus("STEP_1");

}

}


여기서 주의주의주의! 할점은

외부 파라미터를 받아오는 jobParameter..

decider bean은 scope을 설정할 수 없고, jobParameter를 받아올 수가 없다.


step bean을 통해 셋을 하고, 모든 잡파라미터를 저장하는 곳에서 꺼내 써야한다.

jobExecution.getJobParameters().getString("skipFlag");




아래 코드는 실패 성공 여부를 넘겨주는 step1의 내용이다.


Step1Tasklet.java

public class Step1Tasklet implements Tasklet {

      @Override

public RepeatStatus execute(StepContribution contribution,

ChunkContext chunkContext) throws Exception {

           if (실패조건) {

              contribution.setExitStatus(ExitStatus.FAILED);

           }

          return RepeatStatus.FINISHED;

      }




지금 여기선 생략했으나 step1에게는 리스너가 필요하고,

afterStep 메소드에서 실패 성공 처리를 해줘야만

다음 스텝을 실행할지 말지 결정할 수 있다.

(아래는 step1의 리스너의 afterStep 메소드)


String exitCode = stepExecution.getExitStatus().getExitCode();

if (StringUtils.equals(exitCode, ExitStatus.FAILED.getExitCode())) {

return ExitStatus.FAILED;

}

return ExitStatus.COMPLETED;