From 7e05fcbe3f7796fec44db648cf25a27f6e0fdbbe Mon Sep 17 00:00:00 2001 From: Shubhra Date: Sun, 9 Feb 2020 18:16:20 +0530 Subject: [PATCH] BAEL-3298 Adding tests and refactoring --- .../src/main/java/org/baeldung/batch/App.java | 2 + .../org/baeldung/batch/SpringBatchConfig.java | 37 +----- .../batch/SpringBatchRetryConfig.java | 102 +++++++++++++++++ .../batch/service/RetryItemProcessor.java | 22 +++- .../SpringBatchRetryIntegrationTest.java | 105 ++++++++++++++++++ .../output/batchRetry/retryOutput.xml | 1 + spring-batch/xml/retryOutput.xml | 1 + 7 files changed, 230 insertions(+), 40 deletions(-) create mode 100644 spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java create mode 100644 spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java create mode 100644 spring-batch/src/test/resources/output/batchRetry/retryOutput.xml create mode 100644 spring-batch/xml/retryOutput.xml 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 634f0a9014..764ef72a35 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/App.java +++ b/spring-batch/src/main/java/org/baeldung/batch/App.java @@ -18,6 +18,8 @@ public class App { final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(SpringConfig.class); context.register(SpringBatchConfig.class); + context.register(SpringBatchRetryConfig.class); + context.refresh(); // Spring xml config 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 90eb038052..07dd65bcfd 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java @@ -1,17 +1,14 @@ package org.baeldung.batch; -import org.apache.http.conn.ConnectTimeoutException; import org.baeldung.batch.model.Transaction; import org.baeldung.batch.service.CustomItemProcessor; import org.baeldung.batch.service.CustomSkipPolicy; import org.baeldung.batch.service.MissingUsernameException; import org.baeldung.batch.service.NegativeAmountException; import org.baeldung.batch.service.RecordFieldSetMapper; -import org.baeldung.batch.service.RetryItemProcessor; import org.baeldung.batch.service.SkippingItemProcessor; 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.item.ItemProcessor; @@ -26,15 +23,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; -import org.springframework.dao.DeadlockLoserDataAccessException; import org.springframework.oxm.Marshaller; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import java.text.ParseException; -@Configuration -@EnableBatchProcessing + public class SpringBatchConfig { @Autowired private JobBuilderFactory jobBuilderFactory; @@ -75,11 +69,6 @@ public class SpringBatchConfig { return new SkippingItemProcessor(); } - @Bean - public ItemProcessor retryItemProcessor() { - return new RetryItemProcessor(); - } - @Bean public ItemWriter itemWriter(Marshaller marshaller) { StaxEventItemWriter itemWriter = new StaxEventItemWriter<>(); @@ -128,22 +117,6 @@ public class SpringBatchConfig { .build(); } - @Bean - public Step retryStep(@Qualifier("retryItemProcessor") ItemProcessor processor, - ItemWriter writer) throws ParseException { - return stepBuilderFactory - .get("retryStep") - .chunk(10) - .reader(itemReader(inputCsv)) - .processor(processor) - .writer(writer) - .faultTolerant() - .retryLimit(3) - .retry(ConnectTimeoutException.class) - .retry(DeadlockLoserDataAccessException.class) - .build(); - } - @Bean(name = "skippingBatchJob") public Job skippingJob(@Qualifier("skippingStep") Step skippingStep) { return jobBuilderFactory @@ -152,14 +125,6 @@ public class SpringBatchConfig { .build(); } - @Bean(name = "retryBatchJob") - public Job retryJob(@Qualifier("retryStep") Step retryStep) { - return jobBuilderFactory - .get("retryBatchJob") - .start(retryStep) - .build(); - } - @Bean public Step skipPolicyStep(@Qualifier("skippingItemProcessor") ItemProcessor processor, ItemWriter writer) throws ParseException { diff --git a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java new file mode 100644 index 0000000000..65a75c2324 --- /dev/null +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java @@ -0,0 +1,102 @@ +package org.baeldung.batch; + +import org.apache.http.conn.ConnectTimeoutException; +import org.baeldung.batch.model.Transaction; +import org.baeldung.batch.service.RecordFieldSetMapper; +import org.baeldung.batch.service.RetryItemProcessor; +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.item.ItemProcessor; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.UnexpectedInputException; +import org.springframework.batch.item.file.FlatFileItemReader; +import org.springframework.batch.item.file.mapping.DefaultLineMapper; +import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; +import org.springframework.batch.item.xml.StaxEventItemWriter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.dao.DeadlockLoserDataAccessException; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; + +import java.text.ParseException; + +@Configuration +@EnableBatchProcessing +public class SpringBatchRetryConfig { + @Autowired + private JobBuilderFactory jobBuilderFactory; + + @Autowired + private StepBuilderFactory stepBuilderFactory; + + @Value("input/record.csv") + private Resource inputCsv; + + @Value("file:xml/retryOutput.xml") + private Resource outputXml; + + public ItemReader itemReader(Resource inputData) throws UnexpectedInputException, ParseException { + FlatFileItemReader reader = new FlatFileItemReader<>(); + DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); + String[] tokens = { "username", "userid", "transactiondate", "amount" }; + tokenizer.setNames(tokens); + reader.setResource(inputData); + DefaultLineMapper lineMapper = new DefaultLineMapper<>(); + lineMapper.setLineTokenizer(tokenizer); + lineMapper.setFieldSetMapper(new RecordFieldSetMapper()); + reader.setLinesToSkip(1); + reader.setLineMapper(lineMapper); + return reader; + } + + @Bean + public ItemProcessor retryItemProcessor() { + return new RetryItemProcessor(); + } + + @Bean + public ItemWriter itemWriter(Marshaller marshaller) { + StaxEventItemWriter itemWriter = new StaxEventItemWriter<>(); + itemWriter.setMarshaller(marshaller); + itemWriter.setRootTagName("transactionRecord"); + itemWriter.setResource(outputXml); + return itemWriter; + } + + @Bean + public Marshaller marshaller() { + Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); + marshaller.setClassesToBeBound(Transaction.class); + return marshaller; + } + + @Bean + public Step retryStep( + @Qualifier("retryItemProcessor") + ItemProcessor processor, ItemWriter writer) throws ParseException { + return stepBuilderFactory.get("retryStep").chunk(10).reader(itemReader(inputCsv)) + .processor(processor) + .writer(writer) + .faultTolerant() + .retryLimit(3) + .retry(ConnectTimeoutException.class) + .retry(DeadlockLoserDataAccessException.class) + .build(); + } + + @Bean(name = "retryBatchJob") + public Job retryJob( + @Qualifier("retryStep") + Step retryStep) { + return jobBuilderFactory.get("retryBatchJob").start(retryStep).build(); + } +} diff --git a/spring-batch/src/main/java/org/baeldung/batch/service/RetryItemProcessor.java b/spring-batch/src/main/java/org/baeldung/batch/service/RetryItemProcessor.java index 8eb279caf0..736f778424 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/service/RetryItemProcessor.java +++ b/spring-batch/src/main/java/org/baeldung/batch/service/RetryItemProcessor.java @@ -5,7 +5,10 @@ import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; import org.baeldung.batch.model.Transaction; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.ItemProcessor; @@ -16,18 +19,29 @@ public class RetryItemProcessor implements ItemProcessor1010000.04302222015-10-31T00:00:00+05:301234devendra1012321.04302222015-12-03T00:00:00+05:302134john1023411.04302222015-02-02T00:00:00+05:302134robin \ No newline at end of file diff --git a/spring-batch/xml/retryOutput.xml b/spring-batch/xml/retryOutput.xml new file mode 100644 index 0000000000..31da7bd6b3 --- /dev/null +++ b/spring-batch/xml/retryOutput.xml @@ -0,0 +1 @@ +1010000.04302222015-10-31T00:00:00+05:301234devendra1012321.04302222015-12-03T00:00:00+05:302134john1023411.04302222015-02-02T00:00:00+05:302134robin \ No newline at end of file