001/*
002 * Copyright 2012-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.configuration.annotation;
017
018import java.lang.annotation.Documented;
019import java.lang.annotation.ElementType;
020import java.lang.annotation.Retention;
021import java.lang.annotation.RetentionPolicy;
022import java.lang.annotation.Target;
023import javax.sql.DataSource;
024
025import org.springframework.batch.core.configuration.JobRegistry;
026import org.springframework.batch.core.configuration.support.ApplicationContextFactory;
027import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar;
028import org.springframework.batch.core.launch.JobLauncher;
029import org.springframework.batch.core.repository.JobRepository;
030import org.springframework.beans.factory.UnsatisfiedDependencyException;
031import org.springframework.context.annotation.Import;
032import org.springframework.transaction.PlatformTransactionManager;
033
034/**
035 * <p>
036 * Enable Spring Batch features and provide a base configuration for setting up batch jobs in an &#064;Configuration
037 * class, roughly equivalent to using the {@code <batch:*>} XML namespace.</p>
038 *
039 * <pre class="code">
040 * &#064;Configuration
041 * &#064;EnableBatchProcessing
042 * &#064;Import(DataSourceConfiguration.class)
043 * public class AppConfig {
044 *
045 *      &#064;Autowired
046 *      private JobBuilderFactory jobs;
047 *
048 *      &#064;Bean
049 *      public Job job() {
050 *              return jobs.get(&quot;myJob&quot;).start(step1()).next(step2()).build();
051 *      }
052 *
053 *      &#064;Bean
054 *    protected Step step1() {
055 *       ...
056 *    }
057 *
058 *      &#064;Bean
059 *    protected Step step2() {
060 *     ...
061 *    }
062 * }
063 * </pre>
064 *
065 * The user should to provide a {@link DataSource} as a bean in the context, or else implement {@link BatchConfigurer} in
066 * the configuration class itself, e.g.
067 *
068 * <pre class="code">
069 * &#064;Configuration
070 * &#064;EnableBatchProcessing
071 * public class AppConfig extends DefaultBatchConfigurer {
072 *
073 *    &#064;Bean
074 *    public Job job() {
075 *       ...
076 *    }
077 *
078 *    &#064;Override
079 *    protected JobRepository createJobRepository() {
080 *       ...
081 *    }
082 *
083 *  ...
084 *
085 * }
086 * </pre>
087 *
088 * If a user does not provide a {@link javax.sql.DataSource} within the context, a Map based
089 * {@link org.springframework.batch.core.repository.JobRepository} will be used. If multiple
090 * {@link javax.sql.DataSource}s are defined in the context, the one annotated with
091 * {@link org.springframework.context.annotation.Primary} will be used (Note that if none
092 * of them is annotated with {@link org.springframework.context.annotation.Primary}, the one
093 * named <code>dataSource</code> will be used if any, otherwise a {@link UnsatisfiedDependencyException}
094 * will be thrown).
095 *
096 * Note that only one of your configuration classes needs to have the <code>&#064;EnableBatchProcessing</code>
097 * annotation. Once you have an <code>&#064;EnableBatchProcessing</code> class in your configuration you will have an
098 * instance of {@link StepScope} and {@link org.springframework.batch.core.scope.JobScope} so your beans inside steps
099 * can have <code>&#064;Scope("step")</code> and <code>&#064;Scope("job")</code> respectively. You will also be
100 * able to <code>&#064;Autowired</code> some useful stuff into your context:
101 *
102 * <ul>
103 * <li>a {@link JobRepository} (bean name "jobRepository")</li>
104 * <li>a {@link JobLauncher} (bean name "jobLauncher")</li>
105 * <li>a {@link JobRegistry} (bean name "jobRegistry")</li>
106 * <li>a {@link org.springframework.batch.core.explore.JobExplorer} (bean name "jobExplorer")</li>
107 * <li>a {@link PlatformTransactionManager} (bean name "transactionManager")</li>
108 * <li>a {@link JobBuilderFactory} (bean name "jobBuilders") as a convenience to prevent you from having to inject the
109 * job repository into every job, as in the examples above</li>
110 * <li>a {@link StepBuilderFactory} (bean name "stepBuilders") as a convenience to prevent you from having to inject the
111 * job repository and transaction manager into every step</li>
112 * </ul>
113 *
114 * The transaction manager provided by this annotation will be of type:
115 *
116 * <ul>
117 *     <li>{@link org.springframework.batch.support.transaction.ResourcelessTransactionManager}
118 *     if no {@link javax.sql.DataSource} is provided within the context</li>
119 *     <li>{@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
120 *     if a {@link javax.sql.DataSource} is provided within the context</li>
121 * </ul>
122 *
123 * In order to use a custom transaction manager, a custom {@link BatchConfigurer} should be provided. For example:
124 *
125 * <pre class="code">
126 * &#064;Configuration
127 * &#064;EnableBatchProcessing
128 * public class AppConfig extends DefaultBatchConfigurer {
129 *
130 *    &#064;Bean
131 *    public Job job() {
132 *       ...
133 *    }
134 *
135 *    &#064;Override
136 *    public PlatformTransactionManager getTransactionManager() {
137 *       return new MyTransactionManager();
138 *    }
139 *
140 *  ...
141 *
142 * }
143 * </pre>
144 *
145 * If the configuration is specified as <code>modular=true</code> then the context will also contain an
146 * {@link AutomaticJobRegistrar}. The job registrar is useful for modularizing your configuration if there are multiple
147 * jobs. It works by creating separate child application contexts containing job configurations and registering those
148 * jobs. The jobs can then create steps and other dependent components without needing to worry about bean definition
149 * name clashes. Beans of type {@link ApplicationContextFactory} will be registered automatically with the job
150 * registrar. Example:
151 *
152 * <pre class="code">
153 * &#064;Configuration
154 * &#064;EnableBatchProcessing(modular=true)
155 * public class AppConfig {
156 *
157 *    &#064;Bean
158 *    public ApplicationContextFactory someJobs() {
159 *       return new GenericApplicationContextFactory(SomeJobConfiguration.class);
160 *    }
161 *
162 *    &#064;Bean
163 *    public ApplicationContextFactory moreJobs() {
164 *       return new GenericApplicationContextFactory(MoreJobConfiguration.class);
165 *    }
166 *
167 *  ...
168 *
169 * }
170 * </pre>
171 *
172 * Note that a modular parent context in general should <em>not</em> itself contain &#64;Bean definitions for job,
173 * especially if a {@link BatchConfigurer} is provided, because cyclic configuration dependencies are otherwise likely
174 * to develop.
175 *
176 * <p>
177 * For reference, the first example above can be compared to the following Spring XML configuration:
178 *
179 * <pre class="code">
180 * {@code
181 * <batch>
182 *     <job-repository />
183 *     <job id="myJob">
184 *       <step id="step1" .../>
185 *       <step id="step2" .../>
186 *     </job>
187 *     <beans:bean id="transactionManager" .../>
188 *     <beans:bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
189 *       <beans:property name="jobRepository" ref="jobRepository" />
190 *     </beans:bean>
191 * </batch>
192 * }
193 * </pre>
194 *
195 * @author Dave Syer
196 * @author Mahmoud Ben Hassine
197 *
198 */
199@Target(ElementType.TYPE)
200@Retention(RetentionPolicy.RUNTIME)
201@Documented
202@Import(BatchConfigurationSelector.class)
203public @interface EnableBatchProcessing {
204
205        /**
206         * Indicate whether the configuration is going to be modularized into multiple application contexts. If true then
207         * you should not create any &#64;Bean Job definitions in this context, but rather supply them in separate (child)
208         * contexts through an {@link ApplicationContextFactory}.
209         *
210         * @return boolean indicating whether the configuration is going to be
211         * modularized into multiple application contexts.  Defaults to false.
212         */
213        boolean modular() default false;
214
215}