View Javadoc

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.util.Collection;
19  
20  import javax.sql.DataSource;
21  
22  import org.springframework.batch.core.configuration.JobRegistry;
23  import org.springframework.batch.core.configuration.support.MapJobRegistry;
24  import org.springframework.batch.core.launch.JobLauncher;
25  import org.springframework.batch.core.repository.JobRepository;
26  import org.springframework.batch.core.scope.StepScope;
27  import org.springframework.beans.factory.annotation.Autowired;
28  import org.springframework.context.ApplicationContext;
29  import org.springframework.context.annotation.Bean;
30  import org.springframework.context.annotation.Configuration;
31  import org.springframework.context.annotation.Import;
32  import org.springframework.context.annotation.ImportAware;
33  import org.springframework.core.annotation.AnnotationAttributes;
34  import org.springframework.core.type.AnnotationMetadata;
35  import org.springframework.transaction.PlatformTransactionManager;
36  import org.springframework.util.Assert;
37  
38  /**
39   * Base {@code Configuration} class providing common structure for enabling and using Spring Batch. Customization is
40   * available by implementing the {@link BatchConfigurer} interface. {@link BatchConfigurer}.
41   * 
42   * @author Dave Syer
43   * @since 2.2
44   * @see EnableBatchProcessing
45   */
46  @Configuration
47  @Import(StepScopeConfiguration.class)
48  public abstract class AbstractBatchConfiguration implements ImportAware {
49  
50  	@Autowired
51  	private ApplicationContext context;
52  
53  	@Autowired(required = false)
54  	private Collection<DataSource> dataSources;
55  
56  	private BatchConfigurer configurer;
57  
58  	@Bean
59  	public JobBuilderFactory jobBuilders() throws Exception {
60  		return new JobBuilderFactory(jobRepository());
61  	}
62  
63  	@Bean
64  	public StepBuilderFactory stepBuilders() throws Exception {
65  		return new StepBuilderFactory(jobRepository(), transactionManager());
66  	}
67  
68  	@Bean
69  	public abstract JobRepository jobRepository() throws Exception;
70  
71  	@Bean
72  	public abstract JobLauncher jobLauncher() throws Exception;
73  
74  	@Bean
75  	public JobRegistry jobRegistry() throws Exception {
76  		return new MapJobRegistry();
77  	}
78  
79  	@Bean
80  	public abstract PlatformTransactionManager transactionManager() throws Exception;
81  
82  	@Override
83  	public void setImportMetadata(AnnotationMetadata importMetadata) {
84  		AnnotationAttributes enabled = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(
85  				EnableBatchProcessing.class.getName(), false));
86  		Assert.notNull(enabled,
87  				"@EnableBatchProcessing is not present on importing class " + importMetadata.getClassName());
88  	}
89  
90  	protected BatchConfigurer getConfigurer(Collection<BatchConfigurer> configurers) throws Exception {
91  		if (this.configurer != null) {
92  			return this.configurer;
93  		}
94  		if (configurers == null || configurers.isEmpty()) {
95  			if (dataSources == null || dataSources.isEmpty() || dataSources.size() > 1) {
96  				throw new IllegalStateException(
97  						"To use the default BatchConfigurer the context must contain precisely one DataSource, found "
98  								+ (dataSources == null ? 0 : dataSources.size()));
99  			}
100 			DataSource dataSource = dataSources.iterator().next();
101 			DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(dataSource);
102 			configurer.initialize();
103 			this.configurer = configurer;
104 			return configurer;
105 		}
106 		if (configurers.size() > 1) {
107 			throw new IllegalStateException(
108 					"To use a custom BatchConfigurer the context must contain precisely one, found "
109 							+ configurers.size());
110 		}
111 		this.configurer = configurers.iterator().next();
112 		return this.configurer;
113 	}
114 
115 }
116 
117 /**
118  * Extract step scope configuration into a separate unit so that it can be non-static.
119  * 
120  * @author Dave Syer
121  * 
122  */
123 @Configuration
124 class StepScopeConfiguration {
125 
126 	private StepScope stepScope = new StepScope();
127 
128 	@Bean
129 	public StepScope stepScope() {
130 		stepScope.setAutoProxy(false);
131 		return stepScope;
132 	}
133 
134 }