@Bean public Flow flow() { return new FlowBuilder<Flow>("flow") .start(stepBuilderFactory.get("flow.step1") .tasklet(new Tasklet() { @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return RepeatStatus.FINISHED; } }).build() ).next(stepBuilderFactory.get("flow.step2") .tasklet(new Tasklet() { @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return RepeatStatus.FINISHED; } }).build() ).build(); }
@Test public void testBuildSplitUsingStartAndAdd_BATCH_2346() throws Exception { Flow subflow1 = new FlowBuilder<Flow>("subflow1").from(step2).end(); Flow subflow2 = new FlowBuilder<Flow>("subflow2").from(step3).end(); Flow splitflow = new FlowBuilder<Flow>("splitflow").start(subflow1).split(new SimpleAsyncTaskExecutor()) .add(subflow2).build(); FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(splitflow).end(); builder.preventRestart().build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(2, execution.getStepExecutions().size()); }
protected Flow flow() { if (!dirty) { // optimization in case this method is called consecutively return flow; } flow = new SimpleFlow(name); // optimization for flows that only have one state that itself is a flow: if (currentState instanceof FlowState && states.size() == 1) { return ((FlowState) currentState).getFlows().iterator().next(); } addDanglingEndStates(); flow.setStateTransitions(transitions); dirty = false; return flow; }
private void doStart(Object input) { if (this.currentState != null) { doFrom(input); } this.currentState = createState(input); }
private void doNext(Object input) { if (this.currentState == null) { doStart(input); } State next = createState(input); addTransition("COMPLETED", next); addTransition("*", failedState); this.currentState = next; }
private void doFrom(Object input) { if (currentState == null) { doStart(input); } State state = createState(input); tos.put(currentState.getName(), currentState); this.currentState = state; }
@Test public void testBuildSingleFlow() throws Exception { Flow flow = new FlowBuilder<Flow>("subflow").from(step1).next(step2).build(); FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(flow).end().preventRestart(); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(2, execution.getStepExecutions().size()); }
@Test public void testBuildSplit() throws Exception { Flow flow = new FlowBuilder<Flow>("subflow").from(step1).end(); SimpleJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step2); builder.split(new SimpleAsyncTaskExecutor()).add(flow).end(); builder.preventRestart().build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(2, execution.getStepExecutions().size()); }
/** * Add flows to the split, in addition to the current state already present in the parent builder. * * @param flows more flows to add to the split * @return the parent builder */ public FlowBuilder<Q> add(Flow... flows) { Collection<Flow> list = new ArrayList<>(Arrays.asList(flows)); String name = "split" + (parent.splitCounter++); int counter = 0; State one = parent.currentState; Flow flow = null; if (!(one == null || one instanceof FlowState)) { FlowBuilder<Flow> stateBuilder = new FlowBuilder<>(name + "_" + (counter++)); stateBuilder.currentState = one; flow = stateBuilder.build(); } else if (one instanceof FlowState && parent.states.size() == 1) { list.add(((FlowState) one).getFlows().iterator().next()); } if (flow != null) { list.add(flow); } State next = parent.createState(list, executor); parent.currentState = next; return parent; }
@Test public void test() throws Exception { FlowBuilder<Flow> builder = new FlowBuilder<>("flow"); JobRepository jobRepository = new MapJobRepositoryFactoryBean().getObject(); JobExecution execution = jobRepository.createJobExecution("foo", new JobParameters()); builder.start(new StepSupport("step") { @Override public void execute(StepExecution stepExecution) throws JobInterruptedException, UnexpectedJobExecutionException { } }).end().start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); }
@Bean public Job concurrentJob() { Flow splitFlow = new FlowBuilder<Flow>("splitflow").split(new SimpleAsyncTaskExecutor()).add(flow(), flow(), flow(), flow(), flow(), flow(), flow()).build(); return jobBuilderFactory.get("concurrentJob") .start(firstStep()) .next(stepBuilderFactory.get("splitFlowStep") .flow(splitFlow) .build()) .next(lastStep()) .build(); }
private void handleTransition(Deque<Flow> resultFlowDeque, TaskAppNode taskAppNode) { String beanName = getBeanName(taskAppNode); Step currentStep = this.context.getBean(beanName, Step.class); FlowBuilder<Flow> builder = new FlowBuilder<Flow>(beanName) .from(currentStep); boolean wildCardPresent = false; for (TransitionNode transitionNode : taskAppNode.getTransitions()) { String transitionBeanName = getBeanName(transitionNode); wildCardPresent = transitionNode.getStatusToCheck().equals(WILD_CARD); Step transitionStep = this.context.getBean(transitionBeanName, Step.class); builder.on(transitionNode.getStatusToCheck()).to(transitionStep) .from(currentStep); } if (wildCardPresent && !resultFlowDeque.isEmpty()) { throw new IllegalStateException( "Invalid flow following '*' specifier."); } else { //if there are nodes are in the execution Deque. Make sure that //they are processed as a target of the wildcard instead of the //whole transition. if (!resultFlowDeque.isEmpty()) { builder.on(WILD_CARD).to(handleFlowForSegment(resultFlowDeque)).from(currentStep); } } resultFlowDeque.push(builder.end()); }
currentState = copy.get(to); if (!currentState.isEndState()) { addTransition("COMPLETED", completedState); addTransition("*", failedState); currentState = copy.get(from); if (!currentState.isEndState()) { if (!hasFail(from)) { addTransition("*", failedState); if (!hasCompleted(from)) { addTransition("*", completedState);
@Bean public Flow flow1() { return new FlowBuilder<Flow>("flow1") .start(stepBuilderFactory.get("step1") .tasklet(tasklet()).build()) .build(); }
@Bean public Job conditionalJob(JobBuilderFactory jobs, Step conditionalStep1, Step conditionalStep2, Step conditionalStep3, Step conditionalStep4, Step conditionalStep5) throws Exception { return jobs.get("conditionalJob") .incrementer(new RunIdIncrementer()) .flow(conditionalStep1).on(ExitStatus.FAILED.getExitCode()).to(conditionalStep3) .from(conditionalStep1).on("HOGE").to(conditionalStep4) .from(conditionalStep1).on("*").to(conditionalStep2) .from(conditionalStep4).next(conditionalStep5).on("*").stop() .end() .build(); }
@Bean public Job splitJob(@Qualifier("foo") Flow foo, @Qualifier("foo") Flow bar) { FlowBuilder<Flow> flowBuilder = new FlowBuilder<>("split"); Flow flow = flowBuilder.split(new SimpleAsyncTaskExecutor()) .add(foo, bar) .end(); return jobBuilderFactory.get("splitJob") .start(myStep1()) .next(myStep2()) .on("COMPLETED").to(flow) .end() .build(); } }
@Test public void testBuildOnOneLine() throws Exception { FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step1).on("COMPLETED") .to(step2).end().preventRestart(); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(2, execution.getStepExecutions().size()); }
/** * A synonym for {@link #build()} which callers might find useful. Subclasses can override build to create an object * of the desired type (e.g. a parent builder or an actual flow). * * @return the result of the builder */ public final Q end() { return build(); }