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.util.Properties; 019 020import javax.batch.runtime.context.StepContext; 021 022import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext; 023import org.springframework.batch.core.scope.context.StepSynchronizationManager; 024import org.springframework.beans.factory.FactoryBean; 025import org.springframework.beans.factory.FactoryBeanNotInitializedException; 026import org.springframework.beans.factory.InitializingBean; 027import org.springframework.beans.factory.annotation.Autowired; 028import org.springframework.util.Assert; 029 030/** 031 * {@link FactoryBean} implementation used to create {@link javax.batch.runtime.context.StepContext} 032 * instances within the step scope. 033 * 034 * @author Michael Minella 035 * @author Chris Schaefer 036 * @since 3.0 037 */ 038public class JsrStepContextFactoryBean implements FactoryBean<StepContext>, InitializingBean { 039 @Autowired 040 private BatchPropertyContext batchPropertyContext; 041 042 private static final ThreadLocal<javax.batch.runtime.context.StepContext> contextHolder = new ThreadLocal<javax.batch.runtime.context.StepContext>(); 043 044 protected void setBatchPropertyContext(BatchPropertyContext batchPropertyContext) { 045 this.batchPropertyContext = batchPropertyContext; 046 } 047 048 /* (non-Javadoc) 049 * @see org.springframework.beans.factory.FactoryBean#getObject() 050 */ 051 @Override 052 public StepContext getObject() throws Exception { 053 return getCurrent(); 054 } 055 056 private javax.batch.runtime.context.StepContext getCurrent() { 057 org.springframework.batch.core.StepExecution curStepExecution = null; 058 059 if(StepSynchronizationManager.getContext() != null) { 060 curStepExecution = StepSynchronizationManager.getContext().getStepExecution(); 061 } 062 063 if(curStepExecution == null) { 064 throw new FactoryBeanNotInitializedException("A StepExecution is required"); 065 } 066 067 StepContext context = contextHolder.get(); 068 069 // If the current context applies to the current step, use it 070 if(context != null && context.getStepExecutionId() == curStepExecution.getId()) { 071 return context; 072 } 073 074 Properties stepProperties = batchPropertyContext.getStepProperties(curStepExecution.getStepName()); 075 076 if(stepProperties != null) { 077 context = new JsrStepContext(curStepExecution, stepProperties); 078 } else { 079 context = new JsrStepContext(curStepExecution, new Properties()); 080 } 081 082 contextHolder.set(context); 083 084 return context; 085 } 086 087 /* (non-Javadoc) 088 * @see org.springframework.beans.factory.FactoryBean#getObjectType() 089 */ 090 @Override 091 public Class<?> getObjectType() { 092 return StepContext.class; 093 } 094 095 /* (non-Javadoc) 096 * @see org.springframework.beans.factory.FactoryBean#isSingleton() 097 */ 098 @Override 099 public boolean isSingleton() { 100 return false; 101 } 102 103 @Override 104 public void afterPropertiesSet() throws Exception { 105 Assert.notNull(batchPropertyContext, "BatchPropertyContext is required"); 106 } 107 108 public void remove() { 109 if(contextHolder.get() != null) { 110 contextHolder.remove(); 111 } 112 } 113}