001/*
002 * Copyright 2013-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.Job;
019import org.springframework.batch.core.JobExecution;
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 job scope
025 * context. Generally only to be used by implementations of {@link Job}. N.B.
026 * it is the responsibility of every {@link Job} implementation to ensure that
027 * a {@link JobContext} is available on every thread that might be involved in
028 * a job execution, including worker threads from a pool.
029 *
030 * @author Dave Syer
031 * @author Jimmy Praet
032 * @author Mahmoud Ben Hassine
033 * @since 3.0
034 */
035public class JobSynchronizationManager {
036
037        private static final SynchronizationManagerSupport<JobExecution, JobContext> manager = new SynchronizationManagerSupport<JobExecution, JobContext>() {
038
039                @Override
040                protected JobContext createNewContext(JobExecution execution, BatchPropertyContext args) {
041                        return new JobContext(execution);
042                }
043
044                @Override
045                protected void close(JobContext context) {
046                        context.close();
047                }
048        };
049
050        /**
051         * Getter for the current context if there is one, otherwise returns {@code null}.
052         *
053         * @return the current {@link JobContext} or {@code null} if there is none (if one
054         * has not been registered for this thread).
055         */
056        @Nullable
057        public static JobContext getContext() {
058                return manager.getContext();
059        }
060
061        /**
062         * Register a context with the current thread - always put a matching
063         * {@link #close()} call in a finally block to ensure that the correct
064         * context is available in the enclosing block.
065         *
066         * @param JobExecution the step context to register
067         * @return a new {@link JobContext} or the current one if it has the same
068         * {@link JobExecution}
069         */
070        public static JobContext register(JobExecution JobExecution) {
071                return manager.register(JobExecution);
072        }
073
074        /**
075         * Method for unregistering the current context - should always and only be
076         * used by in conjunction with a matching {@link #register(JobExecution)}
077         * to ensure that {@link #getContext()} always returns the correct value.
078         * Does not call {@link JobContext#close()} - that is left up to the caller
079         * because he has a reference to the context (having registered it) and only
080         * he has knowledge of when the step actually ended.
081         */
082        public static void close() {
083                manager.close();
084        }
085
086        /**
087         * A convenient "deep" close operation. Call this instead of
088         * {@link #close()} if the step execution for the current context is ending.
089         * Delegates to {@link JobContext#close()} and then ensures that
090         * {@link #close()} is also called in a finally block.
091         */
092        public static void release() {
093                manager.release();
094        }
095}