1 /*
2 * Copyright 2012-2013 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.springframework.batch.core.configuration.annotation;
17
18 import java.lang.annotation.Documented;
19 import java.lang.annotation.ElementType;
20 import java.lang.annotation.Retention;
21 import java.lang.annotation.RetentionPolicy;
22 import java.lang.annotation.Target;
23
24 import org.springframework.batch.core.configuration.JobRegistry;
25 import org.springframework.batch.core.configuration.support.ApplicationContextFactory;
26 import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar;
27 import org.springframework.batch.core.launch.JobLauncher;
28 import org.springframework.batch.core.repository.JobRepository;
29 import org.springframework.context.annotation.Import;
30 import org.springframework.transaction.PlatformTransactionManager;
31
32 /**
33 * <p>
34 * Enable Spring Batch features and provide a base configuration for setting up batch jobs in an @Configuration
35 * class, roughly equivalent to using the {@code <batch:*>} XML namespace.
36 *
37 * <pre class="code">
38 * @Configuration
39 * @EnableBatchProcessing
40 * @Import(DataSourceCnfiguration.class)
41 * public class AppConfig {
42 *
43 * @Autowired
44 * private JobBuilderFactory jobs;
45 *
46 * @Bean
47 * public Job job() {
48 * return jobs.get("myJob").start(step1()).next(step2()).build();
49 * }
50 *
51 * @Bean
52 * protected Step step1() {
53 * ...
54 * }
55 *
56 * @Bean
57 * protected Step step2() {
58 * ...
59 * }
60 * }
61 * </pre>
62 *
63 * The user has to provide a {@link DataSource} as a bean in the context, or else implement {@link BatchConfigurer} in
64 * the configuration class itself, e.g.
65 *
66 * <pre class="code">
67 * @Configuration
68 * @EnableBatchProcessing
69 * public class AppConfig extends DefaultBatchConfigurer {
70 *
71 * @Bean
72 * public Job job() {
73 * ...
74 * }
75 *
76 * @Override
77 * protected JobRepository createJobRepository() {
78 * ...
79 * }
80 *
81 * ...
82 *
83 * }
84 * </pre>
85 *
86 * Note that only one of your configuration classes needs to have the <code>@EnableBatchProcessing</code>
87 * annotation. Once you have an <code>@EnableBatchProcessing</code> class in your configuration you will have an
88 * instance of {@link StepScope} so your beans inside steps can have <code>@Scope("step")</code>. You will also be
89 * able to <code>@Autowired</code> some useful stuff into your context:
90 *
91 * <ul>
92 * <li>a {@link JobRepository} (bean name "jobRepository")</li>
93 * <li>a {@link JobLauncher} (bean name "jobLauncher")</li>
94 * <li>a {@link JobRegistry} (bean name "jobRegistry")</li>
95 * <li>a {@link PlatformTransactionManager} (bean name "transactionManager")</li>
96 * <li>a {@link JobBuilderFactory} (bean name "jobBuilders") as a convenience to prevent you from having to inject the
97 * job repository into every job, as in the examples above</li>
98 * <li>a {@link StepBuilderFactory} (bean name "stepBuilders") as a convenience to prevent you from having to inject the
99 * job repository and transaction manager into every step</li>
100 * </ul>
101 *
102 * If the configuration is specified as <code>modular=true</code> then the context will also contain an
103 * {@link AutomaticJobRegistrar}. The job registrar is useful for modularizing your configuration if there are multiple
104 * jobs. It works by creating separate child application contexts containing job configurations and registering those
105 * jobs. The jobs can then create steps and other dependent components without needing to worry about bean definition
106 * name clashes. Beans of type {@link ApplicationContextFactory} will be registered automatically with the job
107 * registrar. Example:
108 *
109 * <pre class="code">
110 * @Configuration
111 * @EnableBatchProcessing(modular=true)
112 * public class AppConfig {
113 *
114 * @Bean
115 * public ApplicationContextFactory someJobs() {
116 * return new GenericApplicationContextFactory(SomeJobConfiguration.class);
117 * }
118 *
119 * @Bean
120 * public ApplicationContextFactory moreJobs() {
121 * return new GenericApplicationContextFactory(MoreJobConfiguration.class);
122 * }
123 *
124 * ...
125 *
126 * }
127 * </pre>
128 *
129 * Note that a modular parent context in general should <em>not</em> itself contain @Bean definitions for job,
130 * especially if a {@link BatchConfigurer} is provided, because cyclic configuration dependencies are otherwise likely
131 * to develop.
132 *
133 * </p>
134 *
135 * <p>
136 * For reference, the first example above can be compared to the following Spring XML configuration:
137 *
138 * <pre class="code">
139 * {@code
140 * <batch>
141 * <job-repository />
142 * <job id="myJob">
143 * <step id="step1" .../>
144 * <step id="step2" .../>
145 * </job>
146 * <beans:bean id="transactionManager" .../>
147 * <beans:bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
148 * <beans:property name="jobRepository" ref="jobRepository" />
149 * </beans:bean>
150 * </batch>
151 * }
152 * </pre>
153 *
154 * @author Dave Syer
155 *
156 */
157 @Target(ElementType.TYPE)
158 @Retention(RetentionPolicy.RUNTIME)
159 @Documented
160 @Import(BatchConfigurationSelector.class)
161 public @interface EnableBatchProcessing {
162
163 /**
164 * Indicate whether the configuration is going to be modularized into multiple application contexts. If true then
165 * you should not create any @Bean Job definitions in this context, but rather supply them in separate (child)
166 * contexts through an {@link ApplicationContextFactory}.
167 */
168 boolean modular() default false;
169
170 }