From 98f399a65ac1c68645aad2c5ab80b9e57d351176 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Thu, 30 May 2019 15:54:12 -0400 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=BA=90=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/hello/Application.java | 12 +++ src/main/java/hello/BatchConfiguration.java | 86 +++++++++++++++++++ .../JobCompletionNotificationListener.java | 36 ++++++++ src/main/java/hello/Person.java | 37 ++++++++ src/main/java/hello/PersonItemProcessor.java | 24 ++++++ src/main/resources/sample-data.csv | 6 ++ src/main/resources/schema-all.sql | 7 ++ src/test/run.sh | 36 ++++++++ 8 files changed, 244 insertions(+) create mode 100644 src/main/java/hello/Application.java create mode 100644 src/main/java/hello/BatchConfiguration.java create mode 100644 src/main/java/hello/JobCompletionNotificationListener.java create mode 100644 src/main/java/hello/Person.java create mode 100644 src/main/java/hello/PersonItemProcessor.java create mode 100644 src/main/resources/sample-data.csv create mode 100644 src/main/resources/schema-all.sql create mode 100644 src/test/run.sh diff --git a/src/main/java/hello/Application.java b/src/main/java/hello/Application.java new file mode 100644 index 0000000000..55927b607a --- /dev/null +++ b/src/main/java/hello/Application.java @@ -0,0 +1,12 @@ +package hello; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) throws Exception { + SpringApplication.run(Application.class, args); + } +} diff --git a/src/main/java/hello/BatchConfiguration.java b/src/main/java/hello/BatchConfiguration.java new file mode 100644 index 0000000000..da10fbb89f --- /dev/null +++ b/src/main/java/hello/BatchConfiguration.java @@ -0,0 +1,86 @@ +package hello; + +import javax.sql.DataSource; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecutionListener; +import org.springframework.batch.core.Step; +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.launch.support.RunIdIncrementer; +import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; +import org.springframework.batch.item.database.JdbcBatchItemWriter; +import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder; +import org.springframework.batch.item.file.FlatFileItemReader; +import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; +import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; +import org.springframework.batch.item.file.mapping.DefaultLineMapper; +import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.jdbc.core.JdbcTemplate; + +@Configuration +@EnableBatchProcessing +public class BatchConfiguration { + + @Autowired + public JobBuilderFactory jobBuilderFactory; + + @Autowired + public StepBuilderFactory stepBuilderFactory; + + // tag::readerwriterprocessor[] + @Bean + public FlatFileItemReader reader() { + return new FlatFileItemReaderBuilder() + .name("personItemReader") + .resource(new ClassPathResource("sample-data.csv")) + .delimited() + .names(new String[]{"firstName", "lastName"}) + .fieldSetMapper(new BeanWrapperFieldSetMapper() {{ + setTargetType(Person.class); + }}) + .build(); + } + + @Bean + public PersonItemProcessor processor() { + return new PersonItemProcessor(); + } + + @Bean + public JdbcBatchItemWriter writer(DataSource dataSource) { + return new JdbcBatchItemWriterBuilder() + .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()) + .sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)") + .dataSource(dataSource) + .build(); + } + // end::readerwriterprocessor[] + + // tag::jobstep[] + @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 writer) { + return stepBuilderFactory.get("step1") + . chunk(10) + .reader(reader()) + .processor(processor()) + .writer(writer) + .build(); + } + // end::jobstep[] +} diff --git a/src/main/java/hello/JobCompletionNotificationListener.java b/src/main/java/hello/JobCompletionNotificationListener.java new file mode 100644 index 0000000000..577fc70635 --- /dev/null +++ b/src/main/java/hello/JobCompletionNotificationListener.java @@ -0,0 +1,36 @@ +package hello; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.listener.JobExecutionListenerSupport; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; + +@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.")); + } + } +} diff --git a/src/main/java/hello/Person.java b/src/main/java/hello/Person.java new file mode 100644 index 0000000000..d115ea8496 --- /dev/null +++ b/src/main/java/hello/Person.java @@ -0,0 +1,37 @@ +package hello; + +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; + } + +} diff --git a/src/main/java/hello/PersonItemProcessor.java b/src/main/java/hello/PersonItemProcessor.java new file mode 100644 index 0000000000..78f30cfee1 --- /dev/null +++ b/src/main/java/hello/PersonItemProcessor.java @@ -0,0 +1,24 @@ +package hello; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.batch.item.ItemProcessor; + +public class PersonItemProcessor implements ItemProcessor { + + 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; + } + +} diff --git a/src/main/resources/sample-data.csv b/src/main/resources/sample-data.csv new file mode 100644 index 0000000000..bf7081eaef --- /dev/null +++ b/src/main/resources/sample-data.csv @@ -0,0 +1,6 @@ +Jill,Doe +Joe,Doe +Justin,Doe +Jane,Doe +John,Doe +YuCheng,HU diff --git a/src/main/resources/schema-all.sql b/src/main/resources/schema-all.sql new file mode 100644 index 0000000000..e472ce1e8c --- /dev/null +++ b/src/main/resources/schema-all.sql @@ -0,0 +1,7 @@ +DROP TABLE people IF EXISTS; + +CREATE TABLE people ( + person_id BIGINT IDENTITY NOT NULL PRIMARY KEY, + first_name VARCHAR(20), + last_name VARCHAR(20) +); diff --git a/src/test/run.sh b/src/test/run.sh new file mode 100644 index 0000000000..9c7ca9531f --- /dev/null +++ b/src/test/run.sh @@ -0,0 +1,36 @@ +#!/bin/sh +cd $(dirname $0) + +cd ../complete + +mvn clean package +ret=$? +if [ $ret -ne 0 ]; then + exit $ret +fi +rm -rf target + +./gradlew build +ret=$? +if [ $ret -ne 0 ]; then + exit $ret +fi +rm -rf build + +cd ../initial + +mvn clean compile +ret=$? +if [ $ret -ne 0 ]; then + exit $ret +fi +rm -rf target + +./gradlew compileJava +ret=$? +if [ $ret -ne 0 ]; then + exit $ret +fi +rm -rf build + +exit