diff --git a/spring-batch/.gitignore b/spring-batch/.gitignore
index 0ef6d10b38..5c16bc1baf 100644
--- a/spring-batch/.gitignore
+++ b/spring-batch/.gitignore
@@ -1 +1,2 @@
-output.csv
\ No newline at end of file
+output.csv
+output.json
\ No newline at end of file
diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml
index e81078568b..48d3baeae3 100644
--- a/spring-batch/pom.xml
+++ b/spring-batch/pom.xml
@@ -15,12 +15,30 @@
+
+
+
+
+ javax.xml.bind
+ jaxb-api
+ ${jaxb.version}
+ runtime
+
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+ ${jaxb.version}
+ runtime
+
+
org.xerial
sqlite-jdbc
${sqlite.version}
+
org.springframework
spring-oxm
@@ -32,40 +50,67 @@
+
org.springframework
spring-jdbc
${spring.version}
+
org.springframework.batch
spring-batch-core
${spring.batch.version}
+
org.springframework.batch
spring-batch-test
${spring.batch.version}
+
com.opencsv
opencsv
${opencsv.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-batch
+ ${spring.boot.version}
+
+
+
+ org.hsqldb
+ hsqldb
+ 2.5.0
+ runtime
+
- org.awaitility
- awaitility
- ${awaitility.version}
- test
-
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring.boot.version}
+ test
+
+
- 5.0.3.RELEASE
- 4.0.0.RELEASE
+ 5.2.0.RELEASE
+ 4.2.0.RELEASE
+ 2.1.9.RELEASE
3.15.1
4.1
+ 2.3.1
3.1.1
diff --git a/spring-batch/src/main/java/org/baeldung/batch/App.java b/spring-batch/src/main/java/org/baeldung/batch/App.java
index 749591aa03..91b99ba571 100644
--- a/spring-batch/src/main/java/org/baeldung/batch/App.java
+++ b/spring-batch/src/main/java/org/baeldung/batch/App.java
@@ -1,5 +1,7 @@
package org.baeldung.batch;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
@@ -8,6 +10,9 @@ import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
+
public static void main(final String[] args) {
// Spring Java config
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@@ -27,19 +32,16 @@ public class App {
final JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
final Job job = (Job) context.getBean(batchJobName);
- System.out.println("----------------------------------------");
- System.out.println("Starting the batch job: " + batchJobName);
+ LOGGER.info("Starting the batch job: {}", batchJobName);
try {
- // To enable multiple execution of a job with the same parameters
- JobParameters jobParameters = new JobParametersBuilder()
- .addString("jobID", String.valueOf(System.currentTimeMillis()))
- .toJobParameters();
+ // To enable multiple execution of a job with the same parameters
+ JobParameters jobParameters = new JobParametersBuilder().addString("jobID", String.valueOf(System.currentTimeMillis()))
+ .toJobParameters();
final JobExecution execution = jobLauncher.run(job, jobParameters);
- System.out.println("Job Status : " + execution.getStatus());
- System.out.println("Job succeeded");
+ LOGGER.info("Job Status : {}", execution.getStatus());
} catch (final Exception e) {
e.printStackTrace();
- System.out.println("Job failed");
+ LOGGER.error("Job failed {}", e.getMessage());
}
}
}
\ No newline at end of file
diff --git a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java
index b318dda154..07dd65bcfd 100644
--- a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java
+++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java
@@ -86,9 +86,14 @@ public class SpringBatchConfig {
}
@Bean
- protected Step step1(@Qualifier("itemProcessor") ItemProcessor processor,
- ItemWriter writer) throws ParseException {
- return stepBuilderFactory.get("step1").chunk(10).reader(itemReader(inputCsv)).processor(processor).writer(writer).build();
+ protected Step step1(@Qualifier("itemProcessor") ItemProcessor processor, ItemWriter writer) throws ParseException {
+ return stepBuilderFactory
+ .get("step1")
+ . chunk(10)
+ .reader(itemReader(inputCsv))
+ .processor(processor)
+ .writer(writer)
+ .build();
}
@Bean(name = "firstBatchJob")
diff --git a/spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionerApp.java b/spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionerApp.java
index e56afc591c..f456135058 100644
--- a/spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionerApp.java
+++ b/spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionerApp.java
@@ -1,5 +1,7 @@
package org.baeldung.batch.partitioner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
@@ -7,6 +9,9 @@ import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringbatchPartitionerApp {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SpringbatchPartitionerApp.class);
+
public static void main(final String[] args) {
// Spring Java config
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@@ -15,14 +20,13 @@ public class SpringbatchPartitionerApp {
final JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
final Job job = (Job) context.getBean("partitionerJob");
- System.out.println("Starting the batch job");
+ LOGGER.info("Starting the batch job");
try {
final JobExecution execution = jobLauncher.run(job, new JobParameters());
- System.out.println("Job Status : " + execution.getStatus());
- System.out.println("Job succeeded");
+ LOGGER.info("Job Status : {}", execution.getStatus());
} catch (final Exception e) {
e.printStackTrace();
- System.out.println("Job failed");
+ LOGGER.error("Job failed {}", e.getMessage());
}
}
}
\ No newline at end of file
diff --git a/spring-batch/src/main/java/org/baeldung/batchtesting/SpringBatchApplication.java b/spring-batch/src/main/java/org/baeldung/batchtesting/SpringBatchApplication.java
new file mode 100644
index 0000000000..39bfdfbee7
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchtesting/SpringBatchApplication.java
@@ -0,0 +1,43 @@
+package org.baeldung.batchtesting;
+
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+
+@SpringBootApplication
+@PropertySource("classpath:batchtesting/application.properties")
+public class SpringBatchApplication implements CommandLineRunner {
+
+ @Autowired
+ private JobLauncher jobLauncher;
+
+ @Autowired
+ @Qualifier("transformBooksRecords")
+ private Job transformBooksRecordsJob;
+
+ @Value("${file.input}")
+ private String input;
+
+ @Value("${file.output}")
+ private String output;
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBatchApplication.class, args);
+ }
+
+ @Override
+ public void run(String... args) throws Exception {
+ JobParametersBuilder paramsBuilder = new JobParametersBuilder();
+ paramsBuilder.addString("file.input", input);
+ paramsBuilder.addString("file.output", output);
+ jobLauncher.run(transformBooksRecordsJob, paramsBuilder.toJobParameters());
+ }
+
+}
diff --git a/spring-batch/src/main/java/org/baeldung/batchtesting/SpringBatchConfiguration.java b/spring-batch/src/main/java/org/baeldung/batchtesting/SpringBatchConfiguration.java
new file mode 100644
index 0000000000..2d891ad7da
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchtesting/SpringBatchConfiguration.java
@@ -0,0 +1,137 @@
+package org.baeldung.batchtesting;
+
+import java.io.IOException;
+
+import org.baeldung.batchtesting.model.Book;
+import org.baeldung.batchtesting.model.BookDetails;
+import org.baeldung.batchtesting.model.BookRecord;
+import org.baeldung.batchtesting.service.BookDetailsItemProcessor;
+import org.baeldung.batchtesting.service.BookItemProcessor;
+import org.baeldung.batchtesting.service.BookRecordFieldSetMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+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.configuration.annotation.StepScope;
+import org.springframework.batch.item.ItemReader;
+import org.springframework.batch.item.ItemWriter;
+import org.springframework.batch.item.file.FlatFileItemReader;
+import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
+import org.springframework.batch.item.file.mapping.FieldSetMapper;
+import org.springframework.batch.item.json.JacksonJsonObjectMarshaller;
+import org.springframework.batch.item.json.JsonFileItemWriter;
+import org.springframework.batch.item.json.builder.JsonFileItemWriterBuilder;
+import org.springframework.batch.item.support.ListItemWriter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.FileSystemResource;
+
+
+@Configuration
+@EnableBatchProcessing
+public class SpringBatchConfiguration {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(SpringBatchConfiguration.class);
+
+ private static final String[] TOKENS = { "bookname", "bookauthor", "bookformat", "isbn", "publishyear" };
+
+ @Autowired
+ private JobBuilderFactory jobBuilderFactory;
+
+ @Autowired
+ private StepBuilderFactory stepBuilderFactory;
+
+ @Bean
+ @StepScope
+ public FlatFileItemReader csvItemReader(@Value("#{jobParameters['file.input']}") String input) {
+ FlatFileItemReaderBuilder builder = new FlatFileItemReaderBuilder<>();
+ FieldSetMapper bookRecordFieldSetMapper = new BookRecordFieldSetMapper();
+ LOGGER.info("Configuring reader to input {}", input);
+ // @formatter:off
+ return builder
+ .name("bookRecordItemReader")
+ .resource(new FileSystemResource(input))
+ .delimited()
+ .names(TOKENS)
+ .fieldSetMapper(bookRecordFieldSetMapper)
+ .build();
+ // @formatter:on
+ }
+
+ @Bean
+ @StepScope
+ public JsonFileItemWriter jsonItemWriter(@Value("#{jobParameters['file.output']}") String output) throws IOException {
+ JsonFileItemWriterBuilder builder = new JsonFileItemWriterBuilder<>();
+ JacksonJsonObjectMarshaller marshaller = new JacksonJsonObjectMarshaller<>();
+ LOGGER.info("Configuring writer to output {}", output);
+ // @formatter:off
+ return builder
+ .name("bookItemWriter")
+ .jsonObjectMarshaller(marshaller)
+ .resource(new FileSystemResource(output))
+ .build();
+ // @formatter:on
+ }
+
+ @Bean
+ @StepScope
+ public ListItemWriter listItemWriter() {
+ return new ListItemWriter();
+ }
+
+ @Bean
+ @StepScope
+ public BookItemProcessor bookItemProcessor() {
+ return new BookItemProcessor();
+ }
+
+ @Bean
+ @StepScope
+ public BookDetailsItemProcessor bookDetailsItemProcessor() {
+ return new BookDetailsItemProcessor();
+ }
+
+ @Bean
+ public Step step1(ItemReader csvItemReader, ItemWriter jsonItemWriter) throws IOException {
+ // @formatter:off
+ return stepBuilderFactory
+ .get("step1")
+ . chunk(3)
+ .reader(csvItemReader)
+ .processor(bookItemProcessor())
+ .writer(jsonItemWriter)
+ .build();
+ // @formatter:on
+ }
+
+ @Bean
+ public Step step2(ItemReader csvItemReader, ItemWriter listItemWriter) {
+ // @formatter:off
+ return stepBuilderFactory
+ .get("step2")
+ . chunk(3)
+ .reader(csvItemReader)
+ .processor(bookDetailsItemProcessor())
+ .writer(listItemWriter)
+ .build();
+ // @formatter:on
+ }
+
+ @Bean(name = "transformBooksRecords")
+ public Job transformBookRecords(Step step1, Step step2) throws IOException {
+ // @formatter:off
+ return jobBuilderFactory
+ .get("transformBooksRecords")
+ .flow(step1)
+ .next(step2)
+ .end()
+ .build();
+ // @formatter:on
+ }
+
+}
diff --git a/spring-batch/src/main/java/org/baeldung/batchtesting/model/Book.java b/spring-batch/src/main/java/org/baeldung/batchtesting/model/Book.java
new file mode 100644
index 0000000000..3ea4a29e7f
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchtesting/model/Book.java
@@ -0,0 +1,33 @@
+package org.baeldung.batchtesting.model;
+
+public class Book {
+
+ private String author;
+
+ private String name;
+
+ public Book() {
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return "Book [author=" + author + ", name=" + name + "]";
+ }
+
+}
diff --git a/spring-batch/src/main/java/org/baeldung/batchtesting/model/BookDetails.java b/spring-batch/src/main/java/org/baeldung/batchtesting/model/BookDetails.java
new file mode 100644
index 0000000000..d9284fbc66
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchtesting/model/BookDetails.java
@@ -0,0 +1,50 @@
+package org.baeldung.batchtesting.model;
+
+public class BookDetails {
+
+ private String bookName;
+
+ private String bookFormat;
+
+ private String publishingYear;
+
+ private String bookISBN;
+
+ public String getBookName() {
+ return bookName;
+ }
+
+ public void setBookName(String bookName) {
+ this.bookName = bookName;
+ }
+
+ public String getBookFormat() {
+ return bookFormat;
+ }
+
+ public void setBookFormat(String bookFormat) {
+ this.bookFormat = bookFormat;
+ }
+
+ public String getPublishingYear() {
+ return publishingYear;
+ }
+
+ public void setPublishingYear(String publishingYear) {
+ this.publishingYear = publishingYear;
+ }
+
+ public String getBookISBN() {
+ return bookISBN;
+ }
+
+ public void setBookISBN(String bookISBN) {
+ this.bookISBN = bookISBN;
+ }
+
+ @Override
+ public String toString() {
+ return "BookDetails [bookName=" + bookName + ", bookFormat=" + bookFormat + ", publishingYear=" + publishingYear + ", bookISBN=" + bookISBN + "]";
+ }
+
+}
diff --git a/spring-batch/src/main/java/org/baeldung/batchtesting/model/BookRecord.java b/spring-batch/src/main/java/org/baeldung/batchtesting/model/BookRecord.java
new file mode 100644
index 0000000000..35fb40e878
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchtesting/model/BookRecord.java
@@ -0,0 +1,60 @@
+package org.baeldung.batchtesting.model;
+
+public class BookRecord {
+
+ private String bookName;
+
+ private String bookAuthor;
+
+ private String bookFormat;
+
+ private String bookISBN;
+
+ private String publishingYear;
+
+ public void setBookName(String bookName) {
+ this.bookName = bookName;
+ }
+
+ public void setBookAuthor(String bookAuthor) {
+ this.bookAuthor = bookAuthor;
+ }
+
+ public void setBookFormat(String bookFormat) {
+ this.bookFormat = bookFormat;
+ }
+
+ public void setBookISBN(String bookISBN) {
+ this.bookISBN = bookISBN;
+ }
+
+ public void setPublishingYear(String publishingYear) {
+ this.publishingYear = publishingYear;
+ }
+
+ public String getBookName() {
+ return bookName;
+ }
+
+ public String getBookAuthor() {
+ return bookAuthor;
+ }
+
+ public String getBookFormat() {
+ return bookFormat;
+ }
+
+ public String getBookISBN() {
+ return bookISBN;
+ }
+
+ public String getPublishingYear() {
+ return publishingYear;
+ }
+
+ @Override
+ public String toString() {
+ return "BookRecord [bookName=" + bookName + ", bookAuthor=" + bookAuthor + ", bookFormat=" + bookFormat + ", bookISBN=" + bookISBN + ", publishingYear=" + publishingYear + "]";
+ }
+
+}
diff --git a/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookDetailsItemProcessor.java b/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookDetailsItemProcessor.java
new file mode 100644
index 0000000000..f3800fee51
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookDetailsItemProcessor.java
@@ -0,0 +1,24 @@
+package org.baeldung.batchtesting.service;
+
+import org.baeldung.batchtesting.model.BookDetails;
+import org.baeldung.batchtesting.model.BookRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.batch.item.ItemProcessor;
+
+public class BookDetailsItemProcessor implements ItemProcessor {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(BookDetailsItemProcessor.class);
+
+ @Override
+ public BookDetails process(BookRecord item) throws Exception {
+ BookDetails bookDetails = new BookDetails();
+ bookDetails.setBookFormat(item.getBookFormat());
+ bookDetails.setBookISBN(item.getBookISBN());
+ bookDetails.setPublishingYear(item.getPublishingYear());
+ bookDetails.setBookName(item.getBookName());
+ LOGGER.info("Processing bookdetails {}", bookDetails);
+ return bookDetails;
+ }
+
+}
diff --git a/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookItemProcessor.java b/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookItemProcessor.java
new file mode 100644
index 0000000000..69e72ba1d3
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookItemProcessor.java
@@ -0,0 +1,22 @@
+package org.baeldung.batchtesting.service;
+
+import org.baeldung.batchtesting.model.Book;
+import org.baeldung.batchtesting.model.BookRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.batch.item.ItemProcessor;
+
+public class BookItemProcessor implements ItemProcessor {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(BookItemProcessor.class);
+
+ @Override
+ public Book process(BookRecord item) throws Exception {
+ Book book = new Book();
+ book.setAuthor(item.getBookAuthor());
+ book.setName(item.getBookName());
+ LOGGER.info("Processing book {}", book);
+ return book;
+ }
+
+}
diff --git a/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookRecordFieldSetMapper.java b/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookRecordFieldSetMapper.java
new file mode 100644
index 0000000000..cfc36fed7a
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchtesting/service/BookRecordFieldSetMapper.java
@@ -0,0 +1,22 @@
+package org.baeldung.batchtesting.service;
+
+import org.baeldung.batchtesting.model.BookRecord;
+import org.springframework.batch.item.file.mapping.FieldSetMapper;
+import org.springframework.batch.item.file.transform.FieldSet;
+import org.springframework.validation.BindException;
+
+
+public class BookRecordFieldSetMapper implements FieldSetMapper {
+
+ @Override
+ public BookRecord mapFieldSet(FieldSet fieldSet) throws BindException {
+ BookRecord bookRecord = new BookRecord();
+ bookRecord.setBookName(fieldSet.readString("bookname"));
+ bookRecord.setBookAuthor(fieldSet.readString("bookauthor"));
+ bookRecord.setBookFormat(fieldSet.readString("bookformat"));
+ bookRecord.setBookISBN(fieldSet.readString("isbn"));
+ bookRecord.setPublishingYear(fieldSet.readString("publishyear"));
+ return bookRecord;
+ }
+
+}
diff --git a/spring-batch/src/main/resources/batchtesting/application.properties b/spring-batch/src/main/resources/batchtesting/application.properties
new file mode 100644
index 0000000000..11af6f7d31
--- /dev/null
+++ b/spring-batch/src/main/resources/batchtesting/application.properties
@@ -0,0 +1,3 @@
+spring.batch.job.enabled=false
+file.input=src/main/resources/batchtesting/input.csv
+file.output=src/main/resources/batchtesting/output.json
\ No newline at end of file
diff --git a/spring-batch/src/main/resources/batchtesting/input.csv b/spring-batch/src/main/resources/batchtesting/input.csv
new file mode 100644
index 0000000000..5b873241d4
--- /dev/null
+++ b/spring-batch/src/main/resources/batchtesting/input.csv
@@ -0,0 +1,8 @@
+Foundation,Asimov I.,hardcover,ISBN 12839,2018
+Roadside Picnic,Strugatski A.,paperback,ISBN 12839,1988
+Norwegian Wood,Murakami H.,paperback,ISBN 12839,2015
+Davinci Code,Brown D.,hardcover,ISBN 12839,2005
+Ubik,Dick K. P.,hardcover,ISBN 12839,2013
+JFK,King S.,paperback,ISBN 12839,2017
+Contact,Sagan C.,paperback,ISBN 12839,2000
+Brave New World,Huxley A.,paperback,ISBN 12839,1986
diff --git a/spring-batch/src/main/resources/logback.xml b/spring-batch/src/main/resources/logback.xml
index 91d4292b8e..9a622ceb65 100644
--- a/spring-batch/src/main/resources/logback.xml
+++ b/spring-batch/src/main/resources/logback.xml
@@ -8,14 +8,17 @@
-
+
+
+
+
+
diff --git a/spring-batch/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/SpringContextIntegrationTest.java
index c3a9f74759..0898603083 100644
--- a/spring-batch/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-batch/src/test/java/org/baeldung/SpringContextIntegrationTest.java
@@ -5,8 +5,8 @@ import org.junit.Test;
public class SpringContextIntegrationTest {
- @Test
- public final void testMain() throws Exception {
+ @Test
+ public void testMain() throws Exception {
App.main(null);
- }
+ }
}
diff --git a/spring-batch/src/test/java/org/baeldung/SpringContextTest.java b/spring-batch/src/test/java/org/baeldung/SpringContextTest.java
index 0de9a07b0a..1a4f923a1e 100644
--- a/spring-batch/src/test/java/org/baeldung/SpringContextTest.java
+++ b/spring-batch/src/test/java/org/baeldung/SpringContextTest.java
@@ -5,8 +5,8 @@ import org.junit.Test;
public class SpringContextTest {
- @Test
- public final void testMain() throws Exception {
+ @Test
+ public void testMain() throws Exception {
App.main(null);
- }
+ }
}
diff --git a/spring-batch/src/test/java/org/baeldung/batchtesting/SpringBatchIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/batchtesting/SpringBatchIntegrationTest.java
new file mode 100644
index 0000000000..d66da89ba4
--- /dev/null
+++ b/spring-batch/src/test/java/org/baeldung/batchtesting/SpringBatchIntegrationTest.java
@@ -0,0 +1,115 @@
+package org.baeldung.batchtesting;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Collection;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobInstance;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.test.AssertFile;
+import org.springframework.batch.test.JobLauncherTestUtils;
+import org.springframework.batch.test.JobRepositoryTestUtils;
+import org.springframework.batch.test.context.SpringBatchTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
+
+@RunWith(SpringRunner.class)
+@SpringBatchTest
+@EnableAutoConfiguration
+@ContextConfiguration(classes = { SpringBatchConfiguration.class })
+@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
+public class SpringBatchIntegrationTest {
+
+ private static final String TEST_OUTPUT = "src/test/resources/output/actual-output.json";
+
+ private static final String EXPECTED_OUTPUT = "src/test/resources/output/expected-output.json";
+
+ private static final String TEST_INPUT = "src/test/resources/input/test-input.csv";
+
+ @Autowired
+ private JobLauncherTestUtils jobLauncherTestUtils;
+
+ @Autowired
+ private JobRepositoryTestUtils jobRepositoryTestUtils;
+
+ @After
+ public void cleanUp() {
+ jobRepositoryTestUtils.removeJobExecutions();
+ }
+
+ private JobParameters defaultJobParameters() {
+ JobParametersBuilder paramsBuilder = new JobParametersBuilder();
+ paramsBuilder.addString("file.input", TEST_INPUT);
+ paramsBuilder.addString("file.output", TEST_OUTPUT);
+ return paramsBuilder.toJobParameters();
+ }
+
+ @Test
+ public void givenReferenceOutput_whenJobExecuted_thenSuccess() throws Exception {
+ // given
+ FileSystemResource expectedResult = new FileSystemResource(EXPECTED_OUTPUT);
+ FileSystemResource actualResult = new FileSystemResource(TEST_OUTPUT);
+
+ // when
+ JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters());
+ JobInstance actualJobInstance = jobExecution.getJobInstance();
+ ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
+
+ // then
+ assertThat(actualJobInstance.getJobName(), is("transformBooksRecords"));
+ assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED"));
+ AssertFile.assertFileEquals(expectedResult, actualResult);
+ }
+
+ @Test
+ public void givenReferenceOutput_whenStep1Executed_thenSuccess() throws Exception {
+
+ // given
+ FileSystemResource expectedResult = new FileSystemResource(EXPECTED_OUTPUT);
+ FileSystemResource actualResult = new FileSystemResource(TEST_OUTPUT);
+
+ // when
+ JobExecution jobExecution = jobLauncherTestUtils.launchStep("step1", defaultJobParameters());
+ Collection actualStepExecutions = jobExecution.getStepExecutions();
+ ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
+
+ // then
+ assertThat(actualStepExecutions.size(), is(1));
+ assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED"));
+ AssertFile.assertFileEquals(expectedResult, actualResult);
+ }
+
+ @Test
+ public void whenStep2Executed_thenSuccess() {
+
+ // when
+ JobExecution jobExecution = jobLauncherTestUtils.launchStep("step2", defaultJobParameters());
+ Collection actualStepExecutions = jobExecution.getStepExecutions();
+ ExitStatus actualExitStatus = jobExecution.getExitStatus();
+
+ // then
+ assertThat(actualStepExecutions.size(), is(1));
+ assertThat(actualExitStatus.getExitCode(), is("COMPLETED"));
+ actualStepExecutions.forEach(stepExecution -> {
+ assertThat(stepExecution.getWriteCount(), is(8));
+ });
+ }
+
+}
diff --git a/spring-batch/src/test/java/org/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java
new file mode 100644
index 0000000000..f7b888f0f9
--- /dev/null
+++ b/spring-batch/src/test/java/org/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java
@@ -0,0 +1,116 @@
+package org.baeldung.batchtesting;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Arrays;
+
+import org.baeldung.batchtesting.model.Book;
+import org.baeldung.batchtesting.model.BookRecord;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.item.file.FlatFileItemReader;
+import org.springframework.batch.item.json.JsonFileItemWriter;
+import org.springframework.batch.test.AssertFile;
+import org.springframework.batch.test.JobRepositoryTestUtils;
+import org.springframework.batch.test.MetaDataInstanceFactory;
+import org.springframework.batch.test.StepScopeTestUtils;
+import org.springframework.batch.test.context.SpringBatchTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
+
+
+@RunWith(SpringRunner.class)
+@SpringBatchTest
+@EnableAutoConfiguration
+@ContextConfiguration(classes = { SpringBatchConfiguration.class })
+@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
+public class SpringBatchStepScopeIntegrationTest {
+
+ private static final String TEST_OUTPUT = "src/test/resources/output/actual-output.json";
+
+ private static final String EXPECTED_OUTPUT_ONE = "src/test/resources/output/expected-output-one.json";
+
+ private static final String TEST_INPUT_ONE = "src/test/resources/input/test-input-one.csv";
+ @Autowired
+ private JsonFileItemWriter jsonItemWriter;
+
+ @Autowired
+ private FlatFileItemReader itemReader;
+
+ @Autowired
+ private JobRepositoryTestUtils jobRepositoryTestUtils;
+
+ private JobParameters defaultJobParameters() {
+ JobParametersBuilder paramsBuilder = new JobParametersBuilder();
+ paramsBuilder.addString("file.input", TEST_INPUT_ONE);
+ paramsBuilder.addString("file.output", TEST_OUTPUT);
+ return paramsBuilder.toJobParameters();
+ }
+
+ @After
+ public void cleanUp() {
+ jobRepositoryTestUtils.removeJobExecutions();
+ }
+
+ @Test
+ public void givenMockedStep_whenReaderCalled_thenSuccess() throws Exception {
+
+ // given
+ StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(defaultJobParameters());
+
+ // when
+ StepScopeTestUtils.doInStepScope(stepExecution, () -> {
+ BookRecord bookRecord;
+ itemReader.open(stepExecution.getExecutionContext());
+ while ((bookRecord = itemReader.read()) != null) {
+
+ // then
+ assertThat(bookRecord.getBookName(), is("Foundation"));
+ assertThat(bookRecord.getBookAuthor(), is("Asimov I."));
+ assertThat(bookRecord.getBookISBN(), is("ISBN 12839"));
+ assertThat(bookRecord.getBookFormat(), is("hardcover"));
+ assertThat(bookRecord.getPublishingYear(), is("2018"));
+ }
+ itemReader.close();
+ return null;
+ });
+ }
+
+ @Test
+ public void givenMockedStep_whenWriterCalled_thenSuccess() throws Exception {
+
+ // given
+ FileSystemResource expectedResult = new FileSystemResource(EXPECTED_OUTPUT_ONE);
+ FileSystemResource actualResult = new FileSystemResource(TEST_OUTPUT);
+ Book demoBook = new Book();
+ demoBook.setAuthor("Grisham J.");
+ demoBook.setName("The Firm");
+ StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(defaultJobParameters());
+
+ // when
+ StepScopeTestUtils.doInStepScope(stepExecution, () -> {
+
+ jsonItemWriter.open(stepExecution.getExecutionContext());
+ jsonItemWriter.write(Arrays.asList(demoBook));
+ jsonItemWriter.close();
+ return null;
+ });
+
+ // then
+ AssertFile.assertFileEquals(expectedResult, actualResult);
+ }
+}
diff --git a/spring-batch/src/test/resources/input/test-input-one.csv b/spring-batch/src/test/resources/input/test-input-one.csv
new file mode 100644
index 0000000000..2c0a5b1103
--- /dev/null
+++ b/spring-batch/src/test/resources/input/test-input-one.csv
@@ -0,0 +1 @@
+Foundation,Asimov I.,hardcover,ISBN 12839,2018
\ No newline at end of file
diff --git a/spring-batch/src/test/resources/input/test-input.csv b/spring-batch/src/test/resources/input/test-input.csv
new file mode 100644
index 0000000000..5b873241d4
--- /dev/null
+++ b/spring-batch/src/test/resources/input/test-input.csv
@@ -0,0 +1,8 @@
+Foundation,Asimov I.,hardcover,ISBN 12839,2018
+Roadside Picnic,Strugatski A.,paperback,ISBN 12839,1988
+Norwegian Wood,Murakami H.,paperback,ISBN 12839,2015
+Davinci Code,Brown D.,hardcover,ISBN 12839,2005
+Ubik,Dick K. P.,hardcover,ISBN 12839,2013
+JFK,King S.,paperback,ISBN 12839,2017
+Contact,Sagan C.,paperback,ISBN 12839,2000
+Brave New World,Huxley A.,paperback,ISBN 12839,1986
diff --git a/spring-batch/src/test/resources/output/actual-output.json b/spring-batch/src/test/resources/output/actual-output.json
new file mode 100644
index 0000000000..1fd6cfcf37
--- /dev/null
+++ b/spring-batch/src/test/resources/output/actual-output.json
@@ -0,0 +1,3 @@
+[
+ {"author":"Grisham J.","name":"The Firm"}
+]
diff --git a/spring-batch/src/test/resources/output/expected-output-one.json b/spring-batch/src/test/resources/output/expected-output-one.json
new file mode 100644
index 0000000000..36c31c6d54
--- /dev/null
+++ b/spring-batch/src/test/resources/output/expected-output-one.json
@@ -0,0 +1,3 @@
+[
+ {"author":"Grisham J.","name":"The Firm"}
+]
\ No newline at end of file
diff --git a/spring-batch/src/test/resources/output/expected-output.json b/spring-batch/src/test/resources/output/expected-output.json
new file mode 100644
index 0000000000..32ad8b7ead
--- /dev/null
+++ b/spring-batch/src/test/resources/output/expected-output.json
@@ -0,0 +1,10 @@
+[
+ {"author":"Asimov I.","name":"Foundation"},
+ {"author":"Strugatski A.","name":"Roadside Picnic"},
+ {"author":"Murakami H.","name":"Norwegian Wood"},
+ {"author":"Brown D.","name":"Davinci Code"},
+ {"author":"Dick K. P.","name":"Ubik"},
+ {"author":"King S.","name":"JFK"},
+ {"author":"Sagan C.","name":"Contact"},
+ {"author":"Huxley A.","name":"Brave New World"}
+]