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 @Configuration 037 * class, roughly equivalent to using the {@code <batch:*>} XML namespace.</p> 038 * 039 * <pre class="code"> 040 * @Configuration 041 * @EnableBatchProcessing 042 * @Import(DataSourceConfiguration.class) 043 * public class AppConfig { 044 * 045 * @Autowired 046 * private JobBuilderFactory jobs; 047 * 048 * @Bean 049 * public Job job() { 050 * return jobs.get("myJob").start(step1()).next(step2()).build(); 051 * } 052 * 053 * @Bean 054 * protected Step step1() { 055 * ... 056 * } 057 * 058 * @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 * @Configuration 070 * @EnableBatchProcessing 071 * public class AppConfig extends DefaultBatchConfigurer { 072 * 073 * @Bean 074 * public Job job() { 075 * ... 076 * } 077 * 078 * @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>@EnableBatchProcessing</code> 097 * annotation. Once you have an <code>@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>@Scope("step")</code> and <code>@Scope("job")</code> respectively. You will also be 100 * able to <code>@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 * @Configuration 127 * @EnableBatchProcessing 128 * public class AppConfig extends DefaultBatchConfigurer { 129 * 130 * @Bean 131 * public Job job() { 132 * ... 133 * } 134 * 135 * @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 * @Configuration 154 * @EnableBatchProcessing(modular=true) 155 * public class AppConfig { 156 * 157 * @Bean 158 * public ApplicationContextFactory someJobs() { 159 * return new GenericApplicationContextFactory(SomeJobConfiguration.class); 160 * } 161 * 162 * @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 @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 @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}