001/* 002 * Copyright 2013 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; 017 018import java.io.Serializable; 019import java.util.List; 020import java.util.Properties; 021import java.util.concurrent.atomic.AtomicBoolean; 022 023import javax.batch.runtime.BatchStatus; 024import javax.batch.runtime.Metric; 025 026import org.springframework.batch.core.ExitStatus; 027import org.springframework.batch.core.StepExecution; 028import org.springframework.batch.item.util.ExecutionContextUserSupport; 029import org.springframework.util.Assert; 030import org.springframework.util.ClassUtils; 031 032/** 033 * Wrapper class to provide the {@link javax.batch.runtime.context.StepContext} functionality 034 * as specified in JSR-352. Wrapper delegates to the underlying {@link StepExecution} to 035 * obtain the related contextual information. 036 * 037 * @author Michael Minella 038 * @author Chris Schaefer 039 * @since 3.0 040 */ 041public class JsrStepContext implements javax.batch.runtime.context.StepContext { 042 private final static String PERSISTENT_USER_DATA_KEY = "batch_jsr_persistentUserData"; 043 private StepExecution stepExecution; 044 private Object transientUserData; 045 private Properties properties = new Properties(); 046 private AtomicBoolean exitStatusSet = new AtomicBoolean(); 047 private final ExecutionContextUserSupport executionContextUserSupport = new ExecutionContextUserSupport(ClassUtils.getShortName(JsrStepContext.class)); 048 049 public JsrStepContext(StepExecution stepExecution, Properties properties) { 050 Assert.notNull(stepExecution, "A StepExecution is required"); 051 052 this.stepExecution = stepExecution; 053 this.properties = properties; 054 } 055 056 /* (non-Javadoc) 057 * @see javax.batch.runtime.context.StepContext#getStepName() 058 */ 059 @Override 060 public String getStepName() { 061 return stepExecution.getStepName(); 062 } 063 064 /* (non-Javadoc) 065 * @see javax.batch.runtime.context.StepContext#getTransientUserData() 066 */ 067 @Override 068 public Object getTransientUserData() { 069 return transientUserData; 070 } 071 072 /* (non-Javadoc) 073 * @see javax.batch.runtime.context.StepContext#setTransientUserData(java.lang.Object) 074 */ 075 @Override 076 public void setTransientUserData(Object data) { 077 this.transientUserData = data; 078 } 079 080 /* (non-Javadoc) 081 * @see javax.batch.runtime.context.StepContext#getStepExecutionId() 082 */ 083 @Override 084 public long getStepExecutionId() { 085 return stepExecution.getId(); 086 } 087 088 /* (non-Javadoc) 089 * @see javax.batch.runtime.context.StepContext#getProperties() 090 */ 091 @Override 092 public Properties getProperties() { 093 return properties != null ? properties : new Properties(); 094 } 095 096 /* (non-Javadoc) 097 * @see javax.batch.runtime.context.StepContext#getPersistentUserData() 098 */ 099 @Override 100 public Serializable getPersistentUserData() { 101 return (Serializable) stepExecution.getExecutionContext().get(executionContextUserSupport.getKey(PERSISTENT_USER_DATA_KEY)); 102 } 103 104 /* (non-Javadoc) 105 * @see javax.batch.runtime.context.StepContext#setPersistentUserData(java.io.Serializable) 106 */ 107 @Override 108 public void setPersistentUserData(Serializable data) { 109 stepExecution.getExecutionContext().put(executionContextUserSupport.getKey(PERSISTENT_USER_DATA_KEY), data); 110 } 111 112 /* (non-Javadoc) 113 * @see javax.batch.runtime.context.StepContext#getBatchStatus() 114 */ 115 @Override 116 public BatchStatus getBatchStatus() { 117 return stepExecution.getStatus().getBatchStatus(); 118 } 119 120 /* (non-Javadoc) 121 * @see javax.batch.runtime.context.StepContext#getExitStatus() 122 */ 123 @Override 124 public String getExitStatus() { 125 return exitStatusSet.get() ? stepExecution.getExitStatus().getExitCode() : null; 126 } 127 128 /* (non-Javadoc) 129 * @see javax.batch.runtime.context.StepContext#setExitStatus(java.lang.String) 130 */ 131 @Override 132 public void setExitStatus(String status) { 133 stepExecution.setExitStatus(new ExitStatus(status)); 134 exitStatusSet.set(true); 135 } 136 137 /** 138 * To support both JSR-352's requirement to return the most recent exception 139 * and Spring Batch's support for {@link Throwable}, this implementation will 140 * return the most recent exception in the underlying {@link StepExecution}'s 141 * failure exceptions list. If the exception there extends {@link Throwable} 142 * instead of {@link Exception}, it will be wrapped in an {@link Exception} and 143 * then returned. 144 * 145 * @see javax.batch.runtime.context.StepContext#getException() 146 */ 147 @Override 148 public Exception getException() { 149 List<Throwable> failureExceptions = stepExecution.getFailureExceptions(); 150 if(failureExceptions == null || failureExceptions.isEmpty()) { 151 return null; 152 } else { 153 Throwable t = failureExceptions.get(failureExceptions.size() - 1); 154 155 if(t instanceof Exception) { 156 return (Exception) t; 157 } else { 158 return new Exception(t); 159 } 160 } 161 } 162 163 /* (non-Javadoc) 164 * @see javax.batch.runtime.context.StepContext#getMetrics() 165 */ 166 @Override 167 public Metric[] getMetrics() { 168 Metric[] metrics = new Metric[8]; 169 170 metrics[0] = new SimpleMetric(javax.batch.runtime.Metric.MetricType.COMMIT_COUNT, stepExecution.getCommitCount()); 171 metrics[1] = new SimpleMetric(javax.batch.runtime.Metric.MetricType.FILTER_COUNT, stepExecution.getFilterCount()); 172 metrics[2] = new SimpleMetric(javax.batch.runtime.Metric.MetricType.PROCESS_SKIP_COUNT, stepExecution.getProcessSkipCount()); 173 metrics[3] = new SimpleMetric(javax.batch.runtime.Metric.MetricType.READ_COUNT, stepExecution.getReadCount()); 174 metrics[4] = new SimpleMetric(javax.batch.runtime.Metric.MetricType.READ_SKIP_COUNT, stepExecution.getReadSkipCount()); 175 metrics[5] = new SimpleMetric(javax.batch.runtime.Metric.MetricType.ROLLBACK_COUNT, stepExecution.getRollbackCount()); 176 metrics[6] = new SimpleMetric(javax.batch.runtime.Metric.MetricType.WRITE_COUNT, stepExecution.getWriteCount()); 177 metrics[7] = new SimpleMetric(javax.batch.runtime.Metric.MetricType.WRITE_SKIP_COUNT, stepExecution.getWriteSkipCount()); 178 179 return metrics; 180 } 181}