001/* 002 * Copyright 2009-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.springframework.batch.core.job.flow; 017 018import org.springframework.batch.core.JobExecutionException; 019import org.springframework.batch.core.Step; 020import org.springframework.batch.core.StepExecution; 021import org.springframework.batch.core.job.SimpleStepHandler; 022import org.springframework.batch.core.job.StepHandler; 023import org.springframework.batch.core.repository.JobRepository; 024import org.springframework.batch.core.step.AbstractStep; 025import org.springframework.util.Assert; 026 027/** 028 * A {@link Step} implementation that delegates to a {@link Flow}. Useful for 029 * logical grouping of steps, and especially for partitioning with multiple 030 * steps per execution. If the flow has steps then when the {@link FlowStep} 031 * executes, all steps including the parent {@link FlowStep} will have 032 * executions in the {@link JobRepository} (one for the parent and one each for 033 * the flow steps). 034 * 035 * @author Dave Syer 036 * 037 */ 038public class FlowStep extends AbstractStep { 039 040 private Flow flow; 041 042 /** 043 * Default constructor convenient for configuration purposes. 044 */ 045 public FlowStep() { 046 super(null); 047 } 048 049 /** 050 * Constructor for a {@link FlowStep} that sets the flow and of the step 051 * explicitly. 052 * 053 * @param flow the {@link Flow} instance to be associated with this step. 054 */ 055 public FlowStep(Flow flow) { 056 super(flow.getName()); 057 } 058 059 /** 060 * Public setter for the flow. 061 * 062 * @param flow the flow to set 063 */ 064 public void setFlow(Flow flow) { 065 this.flow = flow; 066 } 067 068 /** 069 * Ensure that the flow is set. 070 * @see AbstractStep#afterPropertiesSet() 071 */ 072 @Override 073 public void afterPropertiesSet() throws Exception { 074 Assert.state(flow != null, "A Flow must be provided"); 075 if (getName()==null) { 076 setName(flow.getName()); 077 } 078 super.afterPropertiesSet(); 079 } 080 081 /** 082 * Delegate to the flow provided for the execution of the step. 083 * 084 * @see AbstractStep#doExecute(StepExecution) 085 */ 086 @Override 087 protected void doExecute(StepExecution stepExecution) throws Exception { 088 try { 089 stepExecution.getExecutionContext().put(STEP_TYPE_KEY, this.getClass().getName()); 090 StepHandler stepHandler = new SimpleStepHandler(getJobRepository(), stepExecution.getExecutionContext()); 091 FlowExecutor executor = new JobFlowExecutor(getJobRepository(), stepHandler, stepExecution.getJobExecution()); 092 executor.updateJobExecutionStatus(flow.start(executor).getStatus()); 093 stepExecution.upgradeStatus(executor.getJobExecution().getStatus()); 094 stepExecution.setExitStatus(executor.getJobExecution().getExitStatus()); 095 } 096 catch (FlowExecutionException e) { 097 if (e.getCause() instanceof JobExecutionException) { 098 throw (JobExecutionException) e.getCause(); 099 } 100 throw new JobExecutionException("Flow execution ended unexpectedly", e); 101 } 102 } 103 104}