5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Spring Batch】Spring Batchのchunk stepとtasklet stepの実現検証

Posted at
1 / 17

#はじめに

Spring Batchの二つステップの種類に実現方法を検証します。今回はJava のアノテーションで実現します。


#ステップの種類

ステップには主に2つの種類があります。
「taskletのみのステップ」と「チャンクによるステップ」です。
以下ではそれぞれについて簡単に見ていきます。

  1. taskletのみのステップ

    image.png

  2. チャンクによるステップ

    image.png


#環境

Windows 10
JDK 1.8.0_251
STS 4.6.2


#プロジェクトの作成

「Spring スターター・プロジェクト」を作成します。プロジェクトを作成する時、依存関係の時、「Spring Batch」しか選択しません。
 ※プロジェクトを作成した後、pom.xmlに「hsqldb」の依存を手動で追記します。dependenciesブロックに下記ソースを追記します。

pom.xml
        <dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<scope>runtime</scope>
        </dependency>

###chunk stepサンプルソースの説明

#####■起動Main方法

BatchTestAppApplication.java
@SpringBootApplication
public class BatchTestAppApplication {

	public static void main(String[] args) {
		SpringApplication.run(BatchTestAppApplication.class, args);
	}

}

#####■テーブル作成用SQL

schema-all.sql
DROP TABLE people IF EXISTS;

CREATE TABLE people  (
    person_id BIGINT IDENTITY NOT NULL PRIMARY KEY,
    first_name VARCHAR(20),
    last_name VARCHAR(20)
);

#####■インプットCSVファイル

sample-data.csv
Jill,Doe
Joe,Doe
Justin,Doe
Jane,Doe
John,Doe

#####■DTOクラス

Person.java
public class Person {

	private String lastName;
	private String firstName;

	public Person() {
	}

	public Person(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@Override
	public String toString() {
		return "firstName: " + firstName + ", lastName: " + lastName;
	}

}

#####■ItemProcessorインタフェースの実装クラス

PersonItemProcessor.java
public class PersonItemProcessor implements ItemProcessor<Person, Person> {

	private static final Logger log = LoggerFactory.getLogger(PersonItemProcessor.class);

	@Override
	public Person process(final Person person) throws Exception {
		final String firstName = person.getFirstName().toUpperCase();
		final String lastName = person.getLastName().toUpperCase();

		final Person transformedPerson = new Person(firstName, lastName);

		log.info("Converting (" + person + ") into (" + transformedPerson + ")");

		return transformedPerson;
	}

}

######説明:

processメソッドを実装します。簡単な名前を大文字に変更します。実行履歴確認のため、infoログを出力します。


#####■リスナークラス
  ジョブ実行結果を確認するために、JobExecutionListenerSupportのafterJobメソッドを実装します。

JobCompletionNotificationListener.java
@Component
public class JobCompletionNotificationListener extends JobExecutionListenerSupport {

	private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class);

	private final JdbcTemplate jdbcTemplate;

	@Autowired
	public JobCompletionNotificationListener(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	@Override
	public void afterJob(JobExecution jobExecution) {
		if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
			log.info("!!! JOB FINISHED! Time to verify the results");

			jdbcTemplate
					.query("SELECT first_name, last_name FROM people",
							(rs, row) -> new Person(rs.getString(1), rs.getString(2)))
					.forEach(person -> log.info("Found <" + person + "> in the database."));
		}
	}
}

#####■Batchの各Bean定義クラス

BatchConfiguration.java
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {

	private static final Logger log = LoggerFactory.getLogger(BatchConfiguration.class);

	@Autowired
	public JobBuilderFactory jobBuilderFactory;

	@Autowired
	public StepBuilderFactory stepBuilderFactory;
	
	@Bean
	public FlatFileItemReader<Person> reader() {
		return new FlatFileItemReaderBuilder<Person>().name("personItemReader")
				.resource(new ClassPathResource("sample-data.csv")).delimited()
				.names(new String[] { "firstName", "lastName" })
				.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {
					{
						setTargetType(Person.class);
					}
				}).build();
	}

	@Bean
	public PersonItemProcessor processor() {
		return new PersonItemProcessor();
	}

	@Bean
	public JdbcBatchItemWriter<Person> writer(DataSource dataSource) {
		return new JdbcBatchItemWriterBuilder<Person>()
				.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
				.sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)").dataSource(dataSource)
				.build();
	}

	@Bean
	public Job importUserJob(JobCompletionNotificationListener listener, Step step1) {
		return jobBuilderFactory.get("importUserJob").incrementer(new RunIdIncrementer()).listener(listener).flow(step1)
				.end()
				.build();
	}
	
	@Bean
	public Step step1(JdbcBatchItemWriter<Person> writer) {
		return stepBuilderFactory.get("step1").<Person, Person>chunk(10).reader(reader()).processor(processor())
				.writer(writer).build();
	}
}

######説明:

  1. reader

    FlatFileItemReaderをItemReaderとしてを戻ります。入力CSVファイルのデータを読み込んで、Person DTO Beanに格納すします。

  2. processor

    PersonItemProcessorをItemProcessorとしてを戻ります。

  3. writer

    JdbcBatchItemWriterをItemWriterとして戻ります。ItemProcessorの処理結果をDBに格納します。

  4. step1

    StepBuilderFactoryでFlatFileItemReader、PersonItemProcessorとJdbcBatchItemWriterをリンクして、Spring Batchのchunk step Beanを生成します。

  5. importUserJob

    カスタマイズしたJobCompletionNotificationListener Beanとstep1で生成したchunk step Beanを利用して、Spring BatchのJobを生成します。該当バッチを起動すると、このメソッドで生成したJobを実行できます。


###tasklet stepサンプルソースの説明

  上記のプロジェクトを活用して、BatchConfigurationを改修して、tasklet stepサンプルを実装します。該当tasklet stepはOSのコマンドを実行します。


#####■BatchConfigurationの改修

  • tasklet Beanの生成
	@Bean
	public Tasklet copyFile() {
		log.info("Start FileCopy");
		SystemCommandTasklet tasklet = new SystemCommandTasklet();
		tasklet.setCommand("cmd /C copy C:\\data\\test.txt C:\\data\\test2.txt");
		tasklet.setTimeout(3000);
		return tasklet;
	}

  ※SystemCommandTaskletの各属性の説明はJavadocで確認ください。


  • step Beanの生成
	@Bean
	public Step step2() {
		return stepBuilderFactory.get("step2").tasklet(copyFile()).build();
	}

  • Jobの生成
	@Bean
	public Job cmdJob(JobCompletionNotificationListener listener, Step step1, Step step2, Step step3) {
		return jobBuilderFactory.get("cmdJob").incrementer(new RunIdIncrementer()).listener(listener).
				flow(step2)
				.end()
				.build();
	}

#参考
Creating a Batch Service
[Java][Spring Boot] Spring BatchでTaskletを使ってみる

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?