001/*
002 * Copyright 2006-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 */
016
017package org.springframework.batch.core.resource;
018
019import org.springframework.batch.core.JobParameters;
020import org.springframework.batch.core.StepExecution;
021import org.springframework.batch.core.StepExecutionListener;
022import org.springframework.batch.core.listener.StepExecutionListenerSupport;
023import org.springframework.batch.repeat.CompletionPolicy;
024import org.springframework.batch.repeat.RepeatContext;
025import org.springframework.batch.repeat.RepeatStatus;
026import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
027import org.springframework.util.Assert;
028
029/**
030 * <p>
031 * A {@link CompletionPolicy} that picks up a commit interval from
032 * {@link JobParameters} by listening to the start of a step. Use anywhere that
033 * a {@link CompletionPolicy} can be used (usually at the chunk level in a
034 * step), and inject as a {@link StepExecutionListener} into the surrounding
035 * step. N.B. only after the step has started will the completion policy be
036 * usable.
037 * </p>
038 *
039 * <p>
040 * It is easier and probably preferable to simply declare the chunk with a
041 * commit-interval that is a late-binding expression (e.g.
042 * <code>#{jobParameters['commit.interval']}</code>). That feature is available
043 * from of Spring Batch 2.1.7.
044 * </p>
045 *
046 * @author Dave Syer
047 *
048 * @see CompletionPolicy
049 */
050public class StepExecutionSimpleCompletionPolicy extends StepExecutionListenerSupport implements CompletionPolicy {
051
052        private CompletionPolicy delegate;
053
054        private String keyName = "commit.interval";
055
056        /**
057         * Public setter for the key name of a Long value in the
058         * {@link JobParameters} that will contain a commit interval. Defaults to
059         * "commit.interval".
060         * @param keyName the keyName to set
061         */
062        public void setKeyName(String keyName) {
063                this.keyName = keyName;
064        }
065
066        /**
067         * Set up a {@link SimpleCompletionPolicy} with a commit interval taken from
068         * the {@link JobParameters}. If there is a Long parameter with the given
069         * key name, the intValue of this parameter is used. If not an exception
070         * will be thrown.
071         *
072         * @see org.springframework.batch.core.listener.StepExecutionListenerSupport#beforeStep(org.springframework.batch.core.StepExecution)
073         */
074        @Override
075        public void beforeStep(StepExecution stepExecution) {
076                JobParameters jobParameters = stepExecution.getJobParameters();
077                Assert.state(jobParameters.getParameters().containsKey(keyName),
078                                "JobParameters do not contain Long parameter with key=[" + keyName + "]");
079                delegate = new SimpleCompletionPolicy(jobParameters.getLong(keyName).intValue());
080        }
081
082        /**
083         * @return true if the commit interval has been reached or the result
084         * indicates completion
085         * @see CompletionPolicy#isComplete(RepeatContext, RepeatStatus)
086         */
087        @Override
088        public boolean isComplete(RepeatContext context, RepeatStatus result) {
089                Assert.state(delegate != null, "The delegate resource has not been initialised. "
090                                + "Remember to register this object as a StepListener.");
091                return delegate.isComplete(context, result);
092        }
093
094        /**
095         * @return if the commit interval has been reached
096         * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext)
097         */
098        @Override
099        public boolean isComplete(RepeatContext context) {
100                Assert.state(delegate != null, "The delegate resource has not been initialised. "
101                                + "Remember to register this object as a StepListener.");
102                return delegate.isComplete(context);
103        }
104
105        /**
106         * @return a new {@link RepeatContext}
107         * @see org.springframework.batch.repeat.CompletionPolicy#start(org.springframework.batch.repeat.RepeatContext)
108         */
109        @Override
110        public RepeatContext start(RepeatContext parent) {
111                Assert.state(delegate != null, "The delegate resource has not been initialised. "
112                                + "Remember to register this object as a StepListener.");
113                return delegate.start(parent);
114        }
115
116        /**
117         * @see org.springframework.batch.repeat.CompletionPolicy#update(org.springframework.batch.repeat.RepeatContext)
118         */
119        @Override
120        public void update(RepeatContext context) {
121                Assert.state(delegate != null, "The delegate resource has not been initialised. "
122                                + "Remember to register this object as a StepListener.");
123                delegate.update(context);
124        }
125
126        /**
127         * Delegates to the wrapped {@link CompletionPolicy} if set, otherwise
128         * returns the value of {@link #setKeyName(String)}.
129         */
130        @Override
131        public String toString() {
132                return (delegate == null) ? keyName : delegate.toString();
133        }
134
135}