From 49f97ae586016800d58907698e5e543f7f1fca9d Mon Sep 17 00:00:00 2001 From: Shubhra Date: Sun, 9 Feb 2020 15:28:19 +0530 Subject: [PATCH 01/16] BAEL-3298 Spring batch retry job --- .../src/main/java/org/baeldung/batch/App.java | 2 + .../org/baeldung/batch/SpringBatchConfig.java | 37 ++++++++++++++++++- .../org/baeldung/batch/model/Transaction.java | 20 +++++++++- .../batch/service/RetryItemProcessor.java | 34 +++++++++++++++++ .../src/main/resources/spring-batch-intro.xml | 15 ++++++++ 5 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 spring-batch/src/main/java/org/baeldung/batch/service/RetryItemProcessor.java 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 91b99ba571..634f0a9014 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/App.java +++ b/spring-batch/src/main/java/org/baeldung/batch/App.java @@ -26,6 +26,8 @@ public class App { runJob(context, "firstBatchJob"); runJob(context, "skippingBatchJob"); runJob(context, "skipPolicyBatchJob"); + runJob(context, "retryBatchJob"); + } private static void runJob(AnnotationConfigApplicationContext context, String batchJobName) { 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 07dd65bcfd..90eb038052 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java @@ -1,14 +1,17 @@ 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; @@ -23,12 +26,15 @@ 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; @@ -69,6 +75,11 @@ public class SpringBatchConfig { return new SkippingItemProcessor(); } + @Bean + public ItemProcessor retryItemProcessor() { + return new RetryItemProcessor(); + } + @Bean public ItemWriter itemWriter(Marshaller marshaller) { StaxEventItemWriter itemWriter = new StaxEventItemWriter<>(); @@ -117,6 +128,22 @@ 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 @@ -125,6 +152,14 @@ 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/model/Transaction.java b/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java index 0ce3a413ab..f34462eadd 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java +++ b/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java @@ -9,6 +9,8 @@ import javax.xml.bind.annotation.XmlRootElement; public class Transaction { private String username; private int userId; + private int age; + private String postCode; private Date transactionDate; private double amount; @@ -46,9 +48,25 @@ public class Transaction { this.amount = amount; } + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getPostCode() { + return postCode; + } + + public void setPostCode(String postCode) { + this.postCode = postCode; + } + @Override public String toString() { - return "Transaction [username=" + username + ", userId=" + userId + ", transactionDate=" + transactionDate + ", amount=" + amount + "]"; + return "Transaction [username=" + username + ", userId=" + userId + ", age=" + age + ", postCode=" + postCode + ", transactionDate=" + transactionDate + ", amount=" + amount + "]"; } } 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 new file mode 100644 index 0000000000..8eb279caf0 --- /dev/null +++ b/spring-batch/src/main/java/org/baeldung/batch/service/RetryItemProcessor.java @@ -0,0 +1,34 @@ +package org.baeldung.batch.service; + +import org.apache.http.HttpResponse; +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.baeldung.batch.model.Transaction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.batch.item.ItemProcessor; + +import java.io.IOException; + +public class RetryItemProcessor implements ItemProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(RetryItemProcessor.class); + + @Override + public Transaction process(Transaction transaction) throws IOException { + LOGGER.info("Attempting to process user with id={}", transaction.getUserId()); + HttpResponse response = fetchMoreUserDetails(transaction.getUserId()); + //parse user's age and postCode from response and update transaction + return transaction; + } + + private HttpResponse fetchMoreUserDetails(int id) throws IOException { + final RequestConfig config = RequestConfig.custom().setConnectTimeout(2 * 1000).build(); + final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build(); + + final HttpGet request = new HttpGet("http://www.baeldung.com:81/user/" + id); + return client.execute(request); + } +} diff --git a/spring-batch/src/main/resources/spring-batch-intro.xml b/spring-batch/src/main/resources/spring-batch-intro.xml index 0f76dd50ff..908b8aa2e1 100644 --- a/spring-batch/src/main/resources/spring-batch-intro.xml +++ b/spring-batch/src/main/resources/spring-batch-intro.xml @@ -54,4 +54,19 @@ + + + + + + + + + + + + + From 7e05fcbe3f7796fec44db648cf25a27f6e0fdbbe Mon Sep 17 00:00:00 2001 From: Shubhra Date: Sun, 9 Feb 2020 18:16:20 +0530 Subject: [PATCH 02/16] 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 From 113e3d8ab3a5727cadc55b5bcb1592886c284c74 Mon Sep 17 00:00:00 2001 From: Shubhra Date: Sun, 9 Feb 2020 19:13:33 +0530 Subject: [PATCH 03/16] BAEL-3298 Some more refactoring --- .../main/java/org/baeldung/batch/SpringBatchRetryConfig.java | 2 +- spring-batch/src/main/resources/input/recordRetry.csv | 3 +++ .../org/baeldung/batch/SpringBatchRetryIntegrationTest.java | 5 ++++- .../src/test/resources/output/batchRetry/retryOutput.xml | 2 +- spring-batch/xml/retryOutput.xml | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 spring-batch/src/main/resources/input/recordRetry.csv diff --git a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java index 65a75c2324..86ee82c7e4 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java @@ -38,7 +38,7 @@ public class SpringBatchRetryConfig { @Autowired private StepBuilderFactory stepBuilderFactory; - @Value("input/record.csv") + @Value("input/recordRetry.csv") private Resource inputCsv; @Value("file:xml/retryOutput.xml") diff --git a/spring-batch/src/main/resources/input/recordRetry.csv b/spring-batch/src/main/resources/input/recordRetry.csv new file mode 100644 index 0000000000..08a6dec658 --- /dev/null +++ b/spring-batch/src/main/resources/input/recordRetry.csv @@ -0,0 +1,3 @@ +username, user_id, transaction_date, transaction_amount +sammy, 1234, 31/10/2015, 10000 +john, 2134, 3/12/2015, 12321 \ No newline at end of file diff --git a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java index f788650c5e..366a028034 100644 --- a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java +++ b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java @@ -92,7 +92,10 @@ public class SpringBatchRetryIntegrationTest { //fails for first two calls and passes third time onwards when(httpResponse.getEntity()).thenReturn(new StringEntity("{ \"age\":10, \"postCode\":\"430222\" }")); - when(httpClient.execute(any())).thenThrow(new ConnectTimeoutException("Timeout count 1")).thenThrow(new ConnectTimeoutException("Timeout count 2")).thenReturn(httpResponse); + when(httpClient.execute(any())) + .thenThrow(new ConnectTimeoutException("Timeout count 1")) + .thenThrow(new ConnectTimeoutException("Timeout count 2")) + .thenReturn(httpResponse); JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters()); JobInstance actualJobInstance = jobExecution.getJobInstance(); diff --git a/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml b/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml index 31da7bd6b3..4170a1dc31 100644 --- a/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml +++ b/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml @@ -1 +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 +1010000.04302222015-10-31T00:00:00+05:301234sammy1012321.04302222015-12-03T00:00:00+05:302134john \ No newline at end of file diff --git a/spring-batch/xml/retryOutput.xml b/spring-batch/xml/retryOutput.xml index 31da7bd6b3..4170a1dc31 100644 --- a/spring-batch/xml/retryOutput.xml +++ b/spring-batch/xml/retryOutput.xml @@ -1 +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 +1010000.04302222015-10-31T00:00:00+05:301234sammy1012321.04302222015-12-03T00:00:00+05:302134john \ No newline at end of file From dfcc982e8fe46d83d8c5e705828073374c7e1dae Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Tue, 11 Feb 2020 07:24:45 +0530 Subject: [PATCH 04/16] Review comments --- .../batch/SpringBatchRetryConfig.java | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java index 86ee82c7e4..4b30e47864 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java @@ -32,6 +32,9 @@ import java.text.ParseException; @Configuration @EnableBatchProcessing public class SpringBatchRetryConfig { + + private static final String[] tokens = { "username", "userid", "transactiondate", "amount" }; + @Autowired private JobBuilderFactory jobBuilderFactory; @@ -45,14 +48,13 @@ public class SpringBatchRetryConfig { 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()); + FlatFileItemReader reader = new FlatFileItemReader<>(); + reader.setResource(inputData); reader.setLinesToSkip(1); reader.setLineMapper(lineMapper); return reader; @@ -80,23 +82,25 @@ public class SpringBatchRetryConfig { } @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(); + 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(); + public Job retryJob(@Qualifier("retryStep") Step retryStep) { + return jobBuilderFactory + .get("retryBatchJob") + .start(retryStep) + .build(); } } From 6dd702867ea34c7e7fbdc448b33ff4caffe972f8 Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Tue, 11 Feb 2020 07:26:44 +0530 Subject: [PATCH 05/16] Some refactoring --- .../main/java/org/baeldung/batch/SpringBatchRetryConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java index 4b30e47864..0144412c58 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java @@ -47,7 +47,7 @@ public class SpringBatchRetryConfig { @Value("file:xml/retryOutput.xml") private Resource outputXml; - public ItemReader itemReader(Resource inputData) throws UnexpectedInputException, ParseException { + public ItemReader itemReader(Resource inputData) throws Exception { DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); tokenizer.setNames(tokens); DefaultLineMapper lineMapper = new DefaultLineMapper<>(); From bc229a692ed21374b2a67a61c816eb383fde13de Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Tue, 11 Feb 2020 07:28:56 +0530 Subject: [PATCH 06/16] Refactoring RetryItemProcessor --- .../org/baeldung/batch/service/RetryItemProcessor.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 736f778424..8f01dea6a8 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 @@ -18,18 +18,19 @@ import java.io.IOException; public class RetryItemProcessor implements ItemProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(RetryItemProcessor.class); - + + private static final int TWO_SECONDS = 2000; + private CloseableHttpClient client; public RetryItemProcessor() { - final RequestConfig config = RequestConfig.custom().setConnectTimeout(2 * 1000).build(); + final RequestConfig config = RequestConfig.custom().setConnectTimeout(TWO_SECONDS).build(); client = HttpClientBuilder.create().setDefaultRequestConfig(config).build(); } @Override public Transaction process(Transaction transaction) throws IOException, JSONException { LOGGER.info("Attempting to process user with id={}", transaction.getUserId()); - System.out.println("Attempting to process user with id=" + transaction.getUserId()); HttpResponse response = fetchMoreUserDetails(transaction.getUserId()); //parse user's age and postCode from response and update transaction From 02f140e1c569943a15fb71a7635debc41de8072d Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Tue, 11 Feb 2020 07:31:32 +0530 Subject: [PATCH 07/16] Minor refactoring in test class --- .../batch/SpringBatchRetryIntegrationTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java index 366a028034..ba38a60df0 100644 --- a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java +++ b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java @@ -66,12 +66,6 @@ public class SpringBatchRetryIntegrationTest { MockitoAnnotations.initMocks(this); } - private JobParameters defaultJobParameters() { - JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - paramsBuilder.addString("jobID", String.valueOf(System.currentTimeMillis())); - return paramsBuilder.toJobParameters(); - } - @Test public void whenEndpointAlwaysFailing_thenJobFails() throws Exception { when(httpClient.execute(any())).thenThrow(new ConnectTimeoutException("Endpoint is down")); @@ -105,4 +99,10 @@ public class SpringBatchRetryIntegrationTest { assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED")); AssertFile.assertFileEquals(expectedResult, actualResult); } + + private JobParameters defaultJobParameters() { + JobParametersBuilder paramsBuilder = new JobParametersBuilder(); + paramsBuilder.addString("jobID", String.valueOf(System.currentTimeMillis())); + return paramsBuilder.toJobParameters(); + } } From db549a4f8fd6c628f9610d640179f95f5edfa818 Mon Sep 17 00:00:00 2001 From: Shubhra Date: Tue, 11 Feb 2020 09:46:58 +0530 Subject: [PATCH 08/16] BAEL-3298 Some more refactoring --- .../baeldung/batch/SpringBatchRetryConfig.java | 14 ++++++++++++-- .../batch/service/RetryItemProcessor.java | 15 ++++----------- .../batch/SpringBatchRetryIntegrationTest.java | 7 +++---- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java index 0144412c58..97f1eff3ea 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java @@ -1,6 +1,9 @@ package org.baeldung.batch; +import org.apache.http.client.config.RequestConfig; import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; import org.baeldung.batch.model.Transaction; import org.baeldung.batch.service.RecordFieldSetMapper; import org.baeldung.batch.service.RetryItemProcessor; @@ -12,7 +15,6 @@ import org.springframework.batch.core.configuration.annotation.StepBuilderFactor 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; @@ -35,6 +37,8 @@ public class SpringBatchRetryConfig { private static final String[] tokens = { "username", "userid", "transactiondate", "amount" }; + private static final int TWO_SECONDS = 2000; + @Autowired private JobBuilderFactory jobBuilderFactory; @@ -47,7 +51,7 @@ public class SpringBatchRetryConfig { @Value("file:xml/retryOutput.xml") private Resource outputXml; - public ItemReader itemReader(Resource inputData) throws Exception { + public ItemReader itemReader(Resource inputData) throws ParseException { DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); tokenizer.setNames(tokens); DefaultLineMapper lineMapper = new DefaultLineMapper<>(); @@ -60,6 +64,12 @@ public class SpringBatchRetryConfig { return reader; } + @Bean + public CloseableHttpClient closeableHttpClient() { + final RequestConfig config = RequestConfig.custom().setConnectTimeout(TWO_SECONDS).build(); + return HttpClientBuilder.create().setDefaultRequestConfig(config).build(); + } + @Bean public ItemProcessor retryItemProcessor() { return new RetryItemProcessor(); 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 8f01dea6a8..d4e82452a7 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 @@ -1,10 +1,8 @@ package org.baeldung.batch.service; import org.apache.http.HttpResponse; -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; @@ -12,21 +10,16 @@ import org.codehaus.jettison.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.ItemProcessor; +import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; public class RetryItemProcessor implements ItemProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(RetryItemProcessor.class); - - private static final int TWO_SECONDS = 2000; - - private CloseableHttpClient client; - public RetryItemProcessor() { - final RequestConfig config = RequestConfig.custom().setConnectTimeout(TWO_SECONDS).build(); - client = HttpClientBuilder.create().setDefaultRequestConfig(config).build(); - } + @Autowired + private CloseableHttpClient closeableHttpClient; @Override public Transaction process(Transaction transaction) throws IOException, JSONException { @@ -44,6 +37,6 @@ public class RetryItemProcessor implements ItemProcessor Date: Tue, 11 Feb 2020 10:16:20 +0530 Subject: [PATCH 09/16] BAEL-3298 Using @MockBean --- .../batch/SpringBatchRetryConfig.java | 9 +++-- .../SpringBatchRetryIntegrationTest.java | 38 +++++-------------- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java index 97f1eff3ea..56088f194b 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchRetryConfig.java @@ -36,7 +36,6 @@ import java.text.ParseException; public class SpringBatchRetryConfig { private static final String[] tokens = { "username", "userid", "transactiondate", "amount" }; - private static final int TWO_SECONDS = 2000; @Autowired @@ -66,7 +65,9 @@ public class SpringBatchRetryConfig { @Bean public CloseableHttpClient closeableHttpClient() { - final RequestConfig config = RequestConfig.custom().setConnectTimeout(TWO_SECONDS).build(); + final RequestConfig config = RequestConfig.custom() + .setConnectTimeout(TWO_SECONDS) + .build(); return HttpClientBuilder.create().setDefaultRequestConfig(config).build(); } @@ -92,8 +93,8 @@ public class SpringBatchRetryConfig { } @Bean - public Step retryStep(@Qualifier("retryItemProcessor") ItemProcessor processor - , ItemWriter writer) throws ParseException { + public Step retryStep(@Qualifier("retryItemProcessor") ItemProcessor processor, + ItemWriter writer) throws ParseException { return stepBuilderFactory.get("retryStep") .chunk(10) .reader(itemReader(inputCsv)) diff --git a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java index 76e04dd5a6..4903185d17 100644 --- a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java +++ b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java @@ -4,13 +4,8 @@ import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import org.baeldung.batch.service.RetryItemProcessor; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobInstance; @@ -21,14 +16,10 @@ import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; 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; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.is; @@ -40,34 +31,24 @@ import static org.mockito.Mockito.when; @SpringBatchTest @EnableAutoConfiguration @ContextConfiguration(classes = { SpringBatchRetryConfig.class }) -@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) public class SpringBatchRetryIntegrationTest { private static final String TEST_OUTPUT = "xml/retryOutput.xml"; - private static final String EXPECTED_OUTPUT = "src/test/resources/output/batchRetry/retryOutput.xml"; @Autowired private JobLauncherTestUtils jobLauncherTestUtils; - @Mock + @MockBean private CloseableHttpClient closeableHttpClient; - @Mock + @MockBean private CloseableHttpResponse httpResponse; - @InjectMocks - private RetryItemProcessor retryItemProcessor; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - @Test public void whenEndpointAlwaysFailing_thenJobFails() throws Exception { - when(closeableHttpClient.execute(any())).thenThrow(new ConnectTimeoutException("Endpoint is down")); + when(closeableHttpClient.execute(any())) + .thenThrow(new ConnectTimeoutException("Endpoint is down")); JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters()); JobInstance actualJobInstance = jobExecution.getJobInstance(); @@ -84,11 +65,12 @@ public class SpringBatchRetryIntegrationTest { FileSystemResource actualResult = new FileSystemResource(TEST_OUTPUT); //fails for first two calls and passes third time onwards - when(httpResponse.getEntity()).thenReturn(new StringEntity("{ \"age\":10, \"postCode\":\"430222\" }")); + when(httpResponse.getEntity()) + .thenReturn(new StringEntity("{ \"age\":10, \"postCode\":\"430222\" }")); when(closeableHttpClient.execute(any())) - .thenThrow(new ConnectTimeoutException("Timeout count 1")) - .thenThrow(new ConnectTimeoutException("Timeout count 2")) - .thenReturn(httpResponse); + .thenThrow(new ConnectTimeoutException("Timeout count 1")) + .thenThrow(new ConnectTimeoutException("Timeout count 2")) + .thenReturn(httpResponse); JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters()); JobInstance actualJobInstance = jobExecution.getJobInstance(); From 1f19079901dbbd0d80ed0176033a02575f47fa9a Mon Sep 17 00:00:00 2001 From: Shubhra Date: Tue, 11 Feb 2020 10:18:39 +0530 Subject: [PATCH 10/16] BAEL-3298 minor update --- .../org/baeldung/batch/SpringBatchRetryIntegrationTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java index 4903185d17..049f6a756f 100644 --- a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java +++ b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java @@ -6,6 +6,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobInstance; @@ -42,7 +43,7 @@ public class SpringBatchRetryIntegrationTest { @MockBean private CloseableHttpClient closeableHttpClient; - @MockBean + @Mock private CloseableHttpResponse httpResponse; @Test From 7703582c8c29b0e755181336adeac884311fb471 Mon Sep 17 00:00:00 2001 From: Shubhra Date: Tue, 11 Feb 2020 10:46:23 +0530 Subject: [PATCH 11/16] BAEL-3298 Updating names of testcases --- .../org/baeldung/batch/SpringBatchRetryIntegrationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java index 049f6a756f..293c97ac5d 100644 --- a/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java +++ b/spring-batch/src/test/java/org/baeldung/batch/SpringBatchRetryIntegrationTest.java @@ -47,7 +47,7 @@ public class SpringBatchRetryIntegrationTest { private CloseableHttpResponse httpResponse; @Test - public void whenEndpointAlwaysFailing_thenJobFails() throws Exception { + public void whenEndpointAlwaysFail_thenJobFails() throws Exception { when(closeableHttpClient.execute(any())) .thenThrow(new ConnectTimeoutException("Endpoint is down")); @@ -61,7 +61,7 @@ public class SpringBatchRetryIntegrationTest { } @Test - public void whenEndpointFailsTwiceAndPassesThirdTime_thenSuccess() throws Exception { + public void whenEndpointFailsTwicePasses3rdTime_thenSuccess() throws Exception { FileSystemResource expectedResult = new FileSystemResource(EXPECTED_OUTPUT); FileSystemResource actualResult = new FileSystemResource(TEST_OUTPUT); From 6bc2f14a93034a03630327b4a0c68693b073db7d Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Wed, 19 Feb 2020 11:00:39 +0530 Subject: [PATCH 12/16] updating id to 9999 --- spring-batch/src/main/resources/input/recordRetry.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-batch/src/main/resources/input/recordRetry.csv b/spring-batch/src/main/resources/input/recordRetry.csv index 08a6dec658..1b1e3e1ac9 100644 --- a/spring-batch/src/main/resources/input/recordRetry.csv +++ b/spring-batch/src/main/resources/input/recordRetry.csv @@ -1,3 +1,3 @@ username, user_id, transaction_date, transaction_amount sammy, 1234, 31/10/2015, 10000 -john, 2134, 3/12/2015, 12321 \ No newline at end of file +john, 9999, 3/12/2015, 12321 From a21e5ff7fecd994342dc024c4bc70a5d7777bf42 Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Wed, 19 Feb 2020 11:01:34 +0530 Subject: [PATCH 13/16] Updating id to 9999 --- .../src/test/resources/output/batchRetry/retryOutput.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml b/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml index 4170a1dc31..0de35670f4 100644 --- a/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml +++ b/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml @@ -1 +1 @@ -1010000.04302222015-10-31T00:00:00+05:301234sammy1012321.04302222015-12-03T00:00:00+05:302134john \ No newline at end of file +1010000.04302222015-10-31T00:00:00+05:301234sammy1012321.04302222015-12-03T00:00:00+05:309999john From ca3be1f372df951ff9aae598322a30b0b026a976 Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Wed, 19 Feb 2020 11:02:31 +0530 Subject: [PATCH 14/16] Updating id to 9999 --- spring-batch/xml/retryOutput.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-batch/xml/retryOutput.xml b/spring-batch/xml/retryOutput.xml index 4170a1dc31..0de35670f4 100644 --- a/spring-batch/xml/retryOutput.xml +++ b/spring-batch/xml/retryOutput.xml @@ -1 +1 @@ -1010000.04302222015-10-31T00:00:00+05:301234sammy1012321.04302222015-12-03T00:00:00+05:302134john \ No newline at end of file +1010000.04302222015-10-31T00:00:00+05:301234sammy1012321.04302222015-12-03T00:00:00+05:309999john From 65c76344c74f8b602fba1a6cf913f0634bf3c756 Mon Sep 17 00:00:00 2001 From: Shubhra Date: Fri, 13 Mar 2020 00:06:57 +0530 Subject: [PATCH 15/16] BAEL-3298 Updating Date to LocalDateTime to avoid timezone related issues --- .../org/baeldung/batch/model/Transaction.java | 11 +++++++---- .../batch/service/RecordFieldSetMapper.java | 16 +++++++--------- .../service/adapter/LocalDateTimeAdapter.java | 19 +++++++++++++++++++ .../src/main/resources/output/output1.xml | 6 +++--- .../src/main/resources/output/output2.xml | 6 +++--- .../src/main/resources/output/output3.xml | 6 +++--- .../src/main/resources/output/output4.xml | 6 +++--- .../src/main/resources/output/output5.xml | 6 +++--- spring-batch/xml/output.xml | 2 +- spring-batch/xml/retryOutput.xml | 2 +- 10 files changed, 50 insertions(+), 30 deletions(-) create mode 100644 spring-batch/src/main/java/org/baeldung/batch/service/adapter/LocalDateTimeAdapter.java diff --git a/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java b/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java index f34462eadd..8ed1d29e3b 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java +++ b/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java @@ -1,8 +1,10 @@ package org.baeldung.batch.model; -import java.util.Date; +import org.baeldung.batch.service.adapter.LocalDateTimeAdapter; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.time.LocalDateTime; @SuppressWarnings("restriction") @XmlRootElement(name = "transactionRecord") @@ -11,7 +13,7 @@ public class Transaction { private int userId; private int age; private String postCode; - private Date transactionDate; + private LocalDateTime transactionDate; private double amount; /* getters and setters for the attributes */ @@ -32,11 +34,12 @@ public class Transaction { this.userId = userId; } - public Date getTransactionDate() { + @XmlJavaTypeAdapter(LocalDateTimeAdapter.class) + public LocalDateTime getTransactionDate() { return transactionDate; } - public void setTransactionDate(Date transactionDate) { + public void setTransactionDate(LocalDateTime transactionDate) { this.transactionDate = transactionDate; } diff --git a/spring-batch/src/main/java/org/baeldung/batch/service/RecordFieldSetMapper.java b/spring-batch/src/main/java/org/baeldung/batch/service/RecordFieldSetMapper.java index fa6f0870aa..e61c54193a 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/service/RecordFieldSetMapper.java +++ b/spring-batch/src/main/java/org/baeldung/batch/service/RecordFieldSetMapper.java @@ -1,18 +1,19 @@ package org.baeldung.batch.service; -import java.text.ParseException; -import java.text.SimpleDateFormat; - import org.baeldung.batch.model.Transaction; import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.validation.BindException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + public class RecordFieldSetMapper implements FieldSetMapper { public Transaction mapFieldSet(FieldSet fieldSet) throws BindException { - SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyy"); + Transaction transaction = new Transaction(); // you can either use the indices or custom names // I personally prefer the custom names easy for debugging and @@ -20,13 +21,10 @@ public class RecordFieldSetMapper implements FieldSetMapper { transaction.setUsername(fieldSet.readString("username")); transaction.setUserId(fieldSet.readInt("userid")); transaction.setAmount(fieldSet.readDouble(3)); + // Converting the date String dateString = fieldSet.readString(2); - try { - transaction.setTransactionDate(dateFormat.parse(dateString)); - } catch (ParseException e) { - e.printStackTrace(); - } + transaction.setTransactionDate(LocalDate.parse(dateString, formatter).atStartOfDay()); return transaction; diff --git a/spring-batch/src/main/java/org/baeldung/batch/service/adapter/LocalDateTimeAdapter.java b/spring-batch/src/main/java/org/baeldung/batch/service/adapter/LocalDateTimeAdapter.java new file mode 100644 index 0000000000..45c35b87f1 --- /dev/null +++ b/spring-batch/src/main/java/org/baeldung/batch/service/adapter/LocalDateTimeAdapter.java @@ -0,0 +1,19 @@ +package org.baeldung.batch.service.adapter; + +import javax.xml.bind.annotation.adapters.XmlAdapter; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class LocalDateTimeAdapter extends XmlAdapter { + + private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT); + + public LocalDateTime unmarshal(String v) throws Exception { + return LocalDateTime.parse(v, DATE_TIME_FORMATTER); + } + + public String marshal(LocalDateTime v) throws Exception { + return DATE_TIME_FORMATTER.format(v); + } +} \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output1.xml b/spring-batch/src/main/resources/output/output1.xml index 194b860813..838d04882a 100644 --- a/spring-batch/src/main/resources/output/output1.xml +++ b/spring-batch/src/main/resources/output/output1.xml @@ -2,19 +2,19 @@ 10000.0 - 2015-10-31T00:00:00+05:30 + 2015-10-31 00:00:00 1234 devendra 12321.0 - 2015-12-03T00:00:00+05:30 + 2015-12-03 00:00:00 2134 john 23411.0 - 2015-02-02T00:00:00+05:30 + 2015-02-02 00:00:00 2134 robin diff --git a/spring-batch/src/main/resources/output/output2.xml b/spring-batch/src/main/resources/output/output2.xml index 194b860813..838d04882a 100644 --- a/spring-batch/src/main/resources/output/output2.xml +++ b/spring-batch/src/main/resources/output/output2.xml @@ -2,19 +2,19 @@ 10000.0 - 2015-10-31T00:00:00+05:30 + 2015-10-31 00:00:00 1234 devendra 12321.0 - 2015-12-03T00:00:00+05:30 + 2015-12-03 00:00:00 2134 john 23411.0 - 2015-02-02T00:00:00+05:30 + 2015-02-02 00:00:00 2134 robin diff --git a/spring-batch/src/main/resources/output/output3.xml b/spring-batch/src/main/resources/output/output3.xml index 194b860813..838d04882a 100644 --- a/spring-batch/src/main/resources/output/output3.xml +++ b/spring-batch/src/main/resources/output/output3.xml @@ -2,19 +2,19 @@ 10000.0 - 2015-10-31T00:00:00+05:30 + 2015-10-31 00:00:00 1234 devendra 12321.0 - 2015-12-03T00:00:00+05:30 + 2015-12-03 00:00:00 2134 john 23411.0 - 2015-02-02T00:00:00+05:30 + 2015-02-02 00:00:00 2134 robin diff --git a/spring-batch/src/main/resources/output/output4.xml b/spring-batch/src/main/resources/output/output4.xml index 194b860813..838d04882a 100644 --- a/spring-batch/src/main/resources/output/output4.xml +++ b/spring-batch/src/main/resources/output/output4.xml @@ -2,19 +2,19 @@ 10000.0 - 2015-10-31T00:00:00+05:30 + 2015-10-31 00:00:00 1234 devendra 12321.0 - 2015-12-03T00:00:00+05:30 + 2015-12-03 00:00:00 2134 john 23411.0 - 2015-02-02T00:00:00+05:30 + 2015-02-02 00:00:00 2134 robin diff --git a/spring-batch/src/main/resources/output/output5.xml b/spring-batch/src/main/resources/output/output5.xml index 194b860813..838d04882a 100644 --- a/spring-batch/src/main/resources/output/output5.xml +++ b/spring-batch/src/main/resources/output/output5.xml @@ -2,19 +2,19 @@ 10000.0 - 2015-10-31T00:00:00+05:30 + 2015-10-31 00:00:00 1234 devendra 12321.0 - 2015-12-03T00:00:00+05:30 + 2015-12-03 00:00:00 2134 john 23411.0 - 2015-02-02T00:00:00+05:30 + 2015-02-02 00:00:00 2134 robin diff --git a/spring-batch/xml/output.xml b/spring-batch/xml/output.xml index acf4969341..d2bed5fcd3 100644 --- a/spring-batch/xml/output.xml +++ b/spring-batch/xml/output.xml @@ -1 +1 @@ -10000.02015-10-31T00:00:00+05:301234devendra12321.02015-12-03T00:00:00+05:302134john23411.02015-02-02T00:00:00+05:302134robin \ No newline at end of file +10000.02015-10-31 00:00:001234devendra12321.02015-12-03 00:00:002134john23411.02015-02-02 00:00:002134robin \ No newline at end of file diff --git a/spring-batch/xml/retryOutput.xml b/spring-batch/xml/retryOutput.xml index 4170a1dc31..57b0e27254 100644 --- a/spring-batch/xml/retryOutput.xml +++ b/spring-batch/xml/retryOutput.xml @@ -1 +1 @@ -1010000.04302222015-10-31T00:00:00+05:301234sammy1012321.04302222015-12-03T00:00:00+05:302134john \ No newline at end of file +1010000.04302222015-10-31 00:00:001234sammy1012321.04302222015-12-03 00:00:002134john \ No newline at end of file From 30322eca9e8c7ac266127fb3ca2daef2afb073f5 Mon Sep 17 00:00:00 2001 From: Shubhra Date: Fri, 13 Mar 2020 00:21:20 +0530 Subject: [PATCH 16/16] BAEL-3298 Some merge changes --- .../src/test/resources/output/batchRetry/retryOutput.xml | 2 +- spring-batch/xml/retryOutput.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml b/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml index 0de35670f4..4cc8db7542 100644 --- a/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml +++ b/spring-batch/src/test/resources/output/batchRetry/retryOutput.xml @@ -1 +1 @@ -1010000.04302222015-10-31T00:00:00+05:301234sammy1012321.04302222015-12-03T00:00:00+05:309999john +1010000.04302222015-10-31 00:00:001234sammy1012321.04302222015-12-03 00:00:009999john diff --git a/spring-batch/xml/retryOutput.xml b/spring-batch/xml/retryOutput.xml index 57b0e27254..d30f2c4a32 100644 --- a/spring-batch/xml/retryOutput.xml +++ b/spring-batch/xml/retryOutput.xml @@ -1 +1 @@ -1010000.04302222015-10-31 00:00:001234sammy1012321.04302222015-12-03 00:00:002134john \ No newline at end of file +1010000.04302222015-10-31 00:00:001234sammy1012321.04302222015-12-03 00:00:009999john \ No newline at end of file