001/* 002 * Copyright 2013-2014 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.jsr.job.flow.support.state; 017 018import org.springframework.batch.core.BatchStatus; 019import org.springframework.batch.core.ExitStatus; 020import org.springframework.batch.core.JobExecution; 021import org.springframework.batch.core.StepExecution; 022import org.springframework.batch.core.job.flow.FlowExecutionStatus; 023import org.springframework.batch.core.job.flow.FlowExecutor; 024import org.springframework.batch.core.job.flow.State; 025import org.springframework.batch.core.repository.JobRepository; 026import org.springframework.batch.item.ExecutionContext; 027 028/** 029 * {@link State} implementation for ending a job per JSR-352 rules if it is 030 * in progress and continuing if just starting. 031 * 032 * @author Michael Minella 033 * @since 3.0 034 */ 035public class JsrEndState extends org.springframework.batch.core.job.flow.support.state.EndState { 036 037 private JobRepository jobRepository; 038 private String restart; 039 040 /** 041 * @param status The {@link FlowExecutionStatus} to end with 042 * @param name The name of the state 043 */ 044 public JsrEndState(FlowExecutionStatus status, String name) { 045 super(status, status.getName(), name); 046 } 047 048 /** 049 * @param status The {@link FlowExecutionStatus} to end with 050 * @param name The name of the state 051 * @param code the exit status. 052 */ 053 public JsrEndState(FlowExecutionStatus status, String code, String name) { 054 super(status, code, name, false); 055 } 056 057 /** 058 * @param status The {@link FlowExecutionStatus} to end with 059 * @param name The name of the state 060 * @param abandon flag to indicate that previous step execution can be 061 * marked as abandoned (if there is one) 062 * @param code the exit status. 063 * 064 */ 065 public JsrEndState(FlowExecutionStatus status, String code, String name, boolean abandon) { 066 super(status, code, name, abandon); 067 } 068 069 public JsrEndState(FlowExecutionStatus status, String code, String name, String restart, boolean abandon, JobRepository jobRepository) { 070 super(status, code, name, abandon); 071 this.jobRepository = jobRepository; 072 this.restart = restart; 073 } 074 075 @Override 076 public FlowExecutionStatus handle(FlowExecutor executor) 077 throws Exception { 078 synchronized (executor) { 079 080 // Special case. If the last step execution could not complete we 081 // are in an unknown state (possibly unrecoverable). 082 StepExecution stepExecution = executor.getStepExecution(); 083 if (stepExecution != null && executor.getStepExecution().getStatus() == BatchStatus.UNKNOWN) { 084 return FlowExecutionStatus.UNKNOWN; 085 } 086 087 if (getStatus().isStop()) { 088 JobExecution jobExecution = stepExecution.getJobExecution(); 089 ExecutionContext executionContext = jobExecution.getExecutionContext(); 090 executionContext.put("batch.restartStep", restart); 091 executionContext.put("batch.stoppedStep", stepExecution.getStepName()); 092 jobRepository.updateExecutionContext(jobExecution); 093 094 if (!executor.isRestart()) { 095 /* 096 * If there are step executions, then we are not at the 097 * beginning of a restart. 098 */ 099 if (isAbandon()) { 100 /* 101 * Only if instructed to do so, upgrade the status of 102 * last step execution so it is not replayed on a 103 * restart... 104 */ 105 executor.abandonStepExecution(); 106 } 107 } 108 else { 109 /* 110 * If we are a stop state and we got this far then it must 111 * be a restart, so return COMPLETED. 112 */ 113 return FlowExecutionStatus.COMPLETED; 114 } 115 } 116 117 setExitStatus(executor, getCode()); 118 119 return getStatus(); 120 } 121 } 122 123 /* (non-Javadoc) 124 * @see org.springframework.batch.core.job.flow.support.state.EndState#setExitStatus(org.springframework.batch.core.job.flow.FlowExecutor, java.lang.String) 125 */ 126 @Override 127 protected void setExitStatus(FlowExecutor executor, String code) { 128 StepExecution stepExecution = executor.getStepExecution(); 129 130 ExitStatus status = new ExitStatus(code); 131 if(!ExitStatus.isNonDefaultExitStatus(status)) { 132 stepExecution.getJobExecution().setExitStatus(status); 133 } 134 } 135}