Spring Bootプロジェクト内でSpringバッチを構成しようとしていますが、データソースなしで使用したいと思います。 ResourcelessTransactionManager
を使用する方法を見つけましたが、機能させることができません。問題は、すでに3つの別のdataSourcesが定義されていることですが、それらのいずれもspringBatchで使用したくありません。
私はデフォルトの実装DefaultBatchConfigurer
を確認しましたが、dataSourceが見つからない場合は、私が望んでいるとおりに動作します。問題は、私が3つ持っていて、どれも使いたくないということです。
私はそれを望まないので、hsqlやその他をメモリDBで使用することを勧めないでください。
この問題を回避するには、DefaultBatchConfigurerクラスを拡張して、DataSourceを無視するようにします。その結果、マップベースのJobRepositoryが構成されます。
例:
@Configuration
@EnableBatchProcessing
public class BatchConfig extends DefaultBatchConfigurer {
@Override
public void setDataSource(DataSource dataSource) {
//This BatchConfigurer ignores any DataSource
}
}
私の場合、Cassandraにデータを永続化します。 spring-boot-starter-batchを使用している場合、まだ実装されていないDataSourceが提供されることが予想されますが、次の手順のように構成をだますことができます。
ステップ1:
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class SampleSpringBatchApplication{
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "true");
SpringApplication.run(SampleSpringBatchApplication.class, args);
}
}
ステップ2:
@Configuration
@EnableBatchProcessing
public class SampleBatchJob extends DefaultBatchConfigurer {
//..
@Override
public void setDataSource(DataSource dataSource) {
}
//..
}
構成に複数のDataSource
がある場合(それらを使用するかどうかに関係なく)、独自のBatchConfigurer
を定義する必要があります。フレームワークがそのような状況で何をすべきかを知る唯一の方法です。
BatchConfigurer
の詳細については、こちらのドキュメントをご覧ください。 http://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/configuration/annotation /BatchConfigurer.html
同様の問題があり、Spring Boot JDBCを使用していて、DBにSpringバッチテーブルを格納したくありませんでしたが、それでもDataSourceにSpringのトランザクション管理を使用したいと考えました。
最終的に、独自のBatchConfigurerを実装しました。
@Component
public class TablelessBatchConfigurer implements BatchConfigurer {
private final PlatformTransactionManager transactionManager;
private final JobRepository jobRepository;
private final JobLauncher jobLauncher;
private final JobExplorer jobExplorer;
private final DataSource dataSource;
@Autowired
public TablelessBatchConfigurer(DataSource dataSource) {
this.dataSource = dataSource;
this.transactionManager = new DataSourceTransactionManager(this.dataSource);
try {
final MapJobRepositoryFactoryBean jobRepositoryFactory = new MapJobRepositoryFactoryBean(this.transactionManager);
jobRepositoryFactory.afterPropertiesSet();
this.jobRepository = jobRepositoryFactory.getObject();
final MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean(jobRepositoryFactory);
jobExplorerFactory.afterPropertiesSet();
this.jobExplorer = jobExplorerFactory.getObject();
final SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
simpleJobLauncher.setJobRepository(this.jobRepository);
simpleJobLauncher.afterPropertiesSet();
this.jobLauncher = simpleJobLauncher;
} catch (Exception e) {
throw new BatchConfigurationException(e);
}
}
// ... override getters
}
イニシャライザをfalseに設定する
spring.batch.initializer.enabled=false
@SpringBootApplicationでDataSourceAutoConfigurationを除外してみてください。以下のサンプルコードを参照してください。
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableBatchProcessing
public class SampleBatchApplication {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
protected Tasklet tasklet() {
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext context) {
return RepeatStatus.FINISHED;
}
};
}
@Bean
public Job job() throws Exception {
return this.jobs.get("job").start(step1()).build();
}
@Bean
protected Step step1() throws Exception {
return this.steps.get("step1").tasklet(tasklet()).build();
}
public static void main(String[] args) throws Exception {
System.exit(SpringApplication.exit(SpringApplication.run(SampleBatchApplication.class, args)));
}
}
そしてサンプルテストクラス
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.rule.OutputCapture;
import static org.assertj.core.api.Assertions.assertThat;
public class SampleBatchApplicationTests {
@Rule
public OutputCapture outputCapture = new OutputCapture();
@Test
public void testDefaultSettings() throws Exception {
assertThat(SpringApplication.exit(SpringApplication.run(SampleBatchApplication.class))).isEqualTo(0);
String output = this.outputCapture.toString();
assertThat(output).contains("completed with the following parameters");
}
}