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 * http://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.boot.autoconfigure.batch; 018 019import javax.annotation.PostConstruct; 020import javax.sql.DataSource; 021 022import org.springframework.batch.core.configuration.annotation.BatchConfigurer; 023import org.springframework.batch.core.explore.JobExplorer; 024import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; 025import org.springframework.batch.core.launch.JobLauncher; 026import org.springframework.batch.core.launch.support.SimpleJobLauncher; 027import org.springframework.batch.core.repository.JobRepository; 028import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; 029import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; 030import org.springframework.boot.context.properties.PropertyMapper; 031import org.springframework.jdbc.datasource.DataSourceTransactionManager; 032import org.springframework.transaction.PlatformTransactionManager; 033 034/** 035 * Basic {@link BatchConfigurer} implementation. 036 * 037 * @author Dave Syer 038 * @author Andy Wilkinson 039 * @author Kazuki Shimizu 040 * @author Stephane Nicoll 041 */ 042public class BasicBatchConfigurer implements BatchConfigurer { 043 044 private final BatchProperties properties; 045 046 private final DataSource dataSource; 047 048 private PlatformTransactionManager transactionManager; 049 050 private final TransactionManagerCustomizers transactionManagerCustomizers; 051 052 private JobRepository jobRepository; 053 054 private JobLauncher jobLauncher; 055 056 private JobExplorer jobExplorer; 057 058 /** 059 * Create a new {@link BasicBatchConfigurer} instance. 060 * @param properties the batch properties 061 * @param dataSource the underlying data source 062 * @param transactionManagerCustomizers transaction manager customizers (or 063 * {@code null}) 064 */ 065 protected BasicBatchConfigurer(BatchProperties properties, DataSource dataSource, 066 TransactionManagerCustomizers transactionManagerCustomizers) { 067 this.properties = properties; 068 this.dataSource = dataSource; 069 this.transactionManagerCustomizers = transactionManagerCustomizers; 070 } 071 072 @Override 073 public JobRepository getJobRepository() { 074 return this.jobRepository; 075 } 076 077 @Override 078 public PlatformTransactionManager getTransactionManager() { 079 return this.transactionManager; 080 } 081 082 @Override 083 public JobLauncher getJobLauncher() { 084 return this.jobLauncher; 085 } 086 087 @Override 088 public JobExplorer getJobExplorer() throws Exception { 089 return this.jobExplorer; 090 } 091 092 @PostConstruct 093 public void initialize() { 094 try { 095 this.transactionManager = buildTransactionManager(); 096 this.jobRepository = createJobRepository(); 097 this.jobLauncher = createJobLauncher(); 098 this.jobExplorer = createJobExplorer(); 099 } 100 catch (Exception ex) { 101 throw new IllegalStateException("Unable to initialize Spring Batch", ex); 102 } 103 } 104 105 protected JobExplorer createJobExplorer() throws Exception { 106 PropertyMapper map = PropertyMapper.get(); 107 JobExplorerFactoryBean factory = new JobExplorerFactoryBean(); 108 factory.setDataSource(this.dataSource); 109 map.from(this.properties::getTablePrefix).whenHasText() 110 .to(factory::setTablePrefix); 111 factory.afterPropertiesSet(); 112 return factory.getObject(); 113 } 114 115 protected JobLauncher createJobLauncher() throws Exception { 116 SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); 117 jobLauncher.setJobRepository(getJobRepository()); 118 jobLauncher.afterPropertiesSet(); 119 return jobLauncher; 120 } 121 122 protected JobRepository createJobRepository() throws Exception { 123 JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); 124 PropertyMapper map = PropertyMapper.get(); 125 map.from(this.dataSource).to(factory::setDataSource); 126 map.from(this::determineIsolationLevel).whenNonNull() 127 .to(factory::setIsolationLevelForCreate); 128 map.from(this.properties::getTablePrefix).whenHasText() 129 .to(factory::setTablePrefix); 130 map.from(this::getTransactionManager).to(factory::setTransactionManager); 131 factory.afterPropertiesSet(); 132 return factory.getObject(); 133 } 134 135 /** 136 * Determine the isolation level for create* operation of the {@link JobRepository}. 137 * @return the isolation level or {@code null} to use the default 138 */ 139 protected String determineIsolationLevel() { 140 return null; 141 } 142 143 protected PlatformTransactionManager createTransactionManager() { 144 return new DataSourceTransactionManager(this.dataSource); 145 } 146 147 private PlatformTransactionManager buildTransactionManager() { 148 PlatformTransactionManager transactionManager = createTransactionManager(); 149 if (this.transactionManagerCustomizers != null) { 150 this.transactionManagerCustomizers.customize(transactionManager); 151 } 152 return transactionManager; 153 } 154 155}