commit ee95d7cbbbf692053431951c73b8b57dfda84da5 Author: Greg Turnquist Date: Thu May 16 11:12:00 2013 -0400 Initial commit of the working, complete example. This one has trickier issues to overcome, so I thought it more practical to push the code to origin so I could ping other people, before having to worry about writing the actual guide. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..a05cee53aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Operating System Files + +*.DS_Store +Thumbs.db + +# Build Files # + +bin +target +build/ +.gradle + +# Eclipse Project Files # + +.classpath +.project +.settings + +# IntelliJ IDEA Files # + +*.iml +*.ipr +*.iws +*.idea + +# Spring Bootstrap artifacts + +dependency-reduced-pom.xml diff --git a/complete/.gitignore b/complete/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/complete/.gitignore @@ -0,0 +1 @@ +/target diff --git a/complete/pom.xml b/complete/pom.xml new file mode 100644 index 0000000000..353717c260 --- /dev/null +++ b/complete/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + org.springframework + gs-batch-processing-complete + 1.0 + + + org.springframework.bootstrap + spring-bootstrap-starters + 0.5.0.BUILD-SNAPSHOT + + + + + org.springframework.bootstrap + spring-bootstrap-starter + 0.5.0.BUILD-SNAPSHOT + + + org.springframework.batch + spring-batch-core + 2.2.0.BUILD-SNAPSHOT + + + org.springframework + spring-jdbc + ${spring.framework.version} + + + org.springframework + spring-tx + ${spring.framework.version} + + + commons-dbcp + commons-dbcp + 1.2.2 + + + org.hsqldb + hsqldb + 2.2.9 + + + + + hello.Application + 4.0.0.BUILD-SNAPSHOT + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + + + + + spring-snapshots + http://repo.springsource.org/snapshot + true + + + + + spring-snapshots + http://repo.springsource.org/snapshot + true + + + diff --git a/complete/src/main/java/hello/Application.java b/complete/src/main/java/hello/Application.java new file mode 100644 index 0000000000..262db7ac99 --- /dev/null +++ b/complete/src/main/java/hello/Application.java @@ -0,0 +1,37 @@ +package hello; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; + +public class Application { + + public static void main(String[] args) throws Exception { + ApplicationContext ctx = new AnnotationConfigApplicationContext(BatchConfiguration.class); + JobLauncher jobLauncher = ctx.getBean(JobLauncher.class); + jobLauncher.run(ctx.getBean(Job.class), new JobParametersBuilder().toJobParameters()); + + JdbcTemplate jdbcTemplate = ctx.getBean(JdbcTemplate.class); + List results = jdbcTemplate.query("select first_name, last_name from PEOPLE", new RowMapper() { + @Override + public Person mapRow(final ResultSet rs, int rowNum) throws SQLException { + return new Person() {{ + setFirstName(rs.getString(1)); + setLastName(rs.getString(2)); + }}; + } + }); + for (Person person : results) { + System.out.println("Found <" + person + "> in the database."); + } + } + +} diff --git a/complete/src/main/java/hello/BatchConfiguration.java b/complete/src/main/java/hello/BatchConfiguration.java new file mode 100644 index 0000000000..0d42436c02 --- /dev/null +++ b/complete/src/main/java/hello/BatchConfiguration.java @@ -0,0 +1,94 @@ +package hello; + +import javax.sql.DataSource; + +import org.springframework.batch.core.Job; +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.ItemProcessor; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; +import org.springframework.batch.item.database.JdbcBatchItemWriter; +import org.springframework.batch.item.file.FlatFileItemReader; +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.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; + +@Configuration +@EnableBatchProcessing +public class BatchConfiguration { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder(). + addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql"). + addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql"). + addScript("classpath:person.sql"). + build(); + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + public ItemReader reader() { + FlatFileItemReader reader = new FlatFileItemReader(); + reader.setResource(new ClassPathResource("sample-data.csv")); + reader.setLineMapper(new DefaultLineMapper() {{ + setLineTokenizer(new DelimitedLineTokenizer(){{ + setNames(new String[]{"firstName", "lastName"}); + }}); + setFieldSetMapper(new BeanWrapperFieldSetMapper(){{ + setTargetType(Person.class); + }}); + }}); + return reader; + } + + @Bean + public ItemProcessor processor() { + return new PersonItemProcessor(); + } + + @Bean + public ItemWriter writer(DataSource dataSource) { + JdbcBatchItemWriter writer = new JdbcBatchItemWriter(); + writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider()); + writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)"); + writer.setDataSource(dataSource); + return writer; + } + + @Bean + public Job importUserJob(JobBuilderFactory jobs, Step s1) { + Job job = jobs.get("importUserJob") + .incrementer(new RunIdIncrementer()) + .flow(s1) + .end() + .build(); + return job; + } + + @Bean + public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader reader, + ItemWriter writer, ItemProcessor processor) { + return stepBuilderFactory.get("step1") + . chunk(10) + .reader(reader) + .processor(processor) + .writer(writer) + .build(); + } + +} diff --git a/complete/src/main/java/hello/Person.java b/complete/src/main/java/hello/Person.java new file mode 100644 index 0000000000..d41f7bc9bd --- /dev/null +++ b/complete/src/main/java/hello/Person.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hello; + +/** + *

+ * Domain object representing information about a person. + *

+ */ +public class Person { + private String lastName; + private String firstName; + + public void setFirstName(final String firstName) { + this.firstName = firstName; + } + + public String getFirstName() { + return firstName; + } + + public void setLastName(final String lastName) { + this.lastName = lastName; + } + + public String getLastName() { + return lastName; + } + + @Override + public String toString() { + return "firstName: " + firstName + ", lastName: " + lastName; + } +} diff --git a/complete/src/main/java/hello/PersonItemProcessor.java b/complete/src/main/java/hello/PersonItemProcessor.java new file mode 100644 index 0000000000..61c50a229c --- /dev/null +++ b/complete/src/main/java/hello/PersonItemProcessor.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hello; + +import org.springframework.batch.item.ItemProcessor; + +/** + *

+ * An example {@link org.springframework.batch.item.ItemProcessor} implementation that upper cases attributes on the + * provided {@link Person} object. + *

+ */ +public class PersonItemProcessor implements ItemProcessor { + @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(); + transformedPerson.setFirstName(firstName); + transformedPerson.setLastName(lastName); + + System.out.println("Converting (" + person + ") into (" + transformedPerson + ")"); + + return transformedPerson; + } +} diff --git a/complete/src/main/resources/log4j.properties b/complete/src/main/resources/log4j.properties new file mode 100644 index 0000000000..49817983a1 --- /dev/null +++ b/complete/src/main/resources/log4j.properties @@ -0,0 +1,9 @@ +log4j.rootCategory=TRACE, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p %t [%c] - <%m>%n + +#log4j.org.springframework.batch=DEBUG +#log4j.org.springframework.integration=DEBUG +#log4j.org.hsqldb=DEBUG \ No newline at end of file diff --git a/complete/src/main/resources/logging.properties b/complete/src/main/resources/logging.properties new file mode 100644 index 0000000000..60a0286380 --- /dev/null +++ b/complete/src/main/resources/logging.properties @@ -0,0 +1,6 @@ +handlers = java.util.logging.ConsoleHandler +.level = ALL +.formatter = java.util.logging.SimpleFormatter +org.springframework.batch.level = FINE +org.springframework.integration.level = FINE +org.hsqldb.level = FINE \ No newline at end of file diff --git a/complete/src/main/resources/person.sql b/complete/src/main/resources/person.sql new file mode 100644 index 0000000000..4e405e6de6 --- /dev/null +++ b/complete/src/main/resources/person.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/complete/src/main/resources/sample-data.csv b/complete/src/main/resources/sample-data.csv new file mode 100644 index 0000000000..cead90f5a9 --- /dev/null +++ b/complete/src/main/resources/sample-data.csv @@ -0,0 +1,5 @@ +Jill,Doe +Joe,Doe +Justin,Doe +Jane,Doe +John,Doe