001/* 002 * Copyright 2006-2018 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.scope.context; 017 018import org.springframework.batch.core.Step; 019import org.springframework.batch.core.StepExecution; 020import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext; 021import org.springframework.lang.Nullable; 022 023/** 024 * Central convenience class for framework use in managing the step scope 025 * context. Generally only to be used by implementations of {@link Step}. N.B. 026 * it is the responsibility of every {@link Step} implementation to ensure that 027 * a {@link StepContext} is available on every thread that might be involved in 028 * a step execution, including worker threads from a pool. 029 * 030 * @author Dave Syer 031 * @author Michael Minella 032 * @author Mahmoud Ben Hassine 033 * 034 */ 035public class StepSynchronizationManager { 036 037 private static final SynchronizationManagerSupport<StepExecution, StepContext> manager = 038 new SynchronizationManagerSupport<StepExecution, StepContext>() { 039 040 @Override 041 protected StepContext createNewContext(StepExecution execution, BatchPropertyContext propertyContext) { 042 StepContext context; 043 044 if(propertyContext != null) { 045 context = new StepContext(execution, propertyContext); 046 } else { 047 context = new StepContext(execution); 048 } 049 050 return context; 051 } 052 053 @Override 054 protected void close(StepContext context) { 055 context.close(); 056 } 057 }; 058 059 /** 060 * Getter for the current context if there is one, otherwise returns {@code null}. 061 * 062 * @return the current {@link StepContext} or {@code null} if there is none (if one 063 * has not been registered for this thread). 064 */ 065 @Nullable 066 public static StepContext getContext() { 067 return manager.getContext(); 068 } 069 070 /** 071 * Register a context with the current thread - always put a matching 072 * {@link #close()} call in a finally block to ensure that the correct 073 * context is available in the enclosing block. 074 * 075 * @param stepExecution the step context to register 076 * @return a new {@link StepContext} or the current one if it has the same 077 * {@link StepExecution} 078 */ 079 public static StepContext register(StepExecution stepExecution) { 080 return manager.register(stepExecution); 081 } 082 083 /** 084 * Register a context with the current thread - always put a matching 085 * {@link #close()} call in a finally block to ensure that the correct 086 * context is available in the enclosing block. 087 * 088 * @param stepExecution the step context to register 089 * @param propertyContext an instance of {@link BatchPropertyContext} to be 090 * used by the StepSynchronizationManager. 091 * @return a new {@link StepContext} or the current one if it has the same 092 * {@link StepExecution} 093 */ 094 public static StepContext register(StepExecution stepExecution, BatchPropertyContext propertyContext) { 095 return manager.register(stepExecution, propertyContext); 096 } 097 098 /** 099 * Method for unregistering the current context - should always and only be 100 * used by in conjunction with a matching {@link #register(StepExecution)} 101 * to ensure that {@link #getContext()} always returns the correct value. 102 * Does not call {@link StepContext#close()} - that is left up to the caller 103 * because he has a reference to the context (having registered it) and only 104 * he has knowledge of when the step actually ended. 105 */ 106 public static void close() { 107 manager.close(); 108 } 109 110 /** 111 * A convenient "deep" close operation. Call this instead of 112 * {@link #close()} if the step execution for the current context is ending. 113 * Delegates to {@link StepContext#close()} and then ensures that 114 * {@link #close()} is also called in a finally block. 115 */ 116 public static void release() { 117 manager.release(); 118 } 119}