diff --git a/spring-batch/src/main/java/com/baeldung/batch/App.java b/spring-batch/src/main/java/com/baeldung/batch/App.java index 0f888a77b3..c2db446965 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/App.java +++ b/spring-batch/src/main/java/com/baeldung/batch/App.java @@ -8,7 +8,9 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Profile; +@Profile("spring") public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); diff --git a/spring-batch/src/main/java/com/baeldung/batch/SpringBatchConfig.java b/spring-batch/src/main/java/com/baeldung/batch/SpringBatchConfig.java index e1c52e1582..5546df22fc 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/SpringBatchConfig.java +++ b/spring-batch/src/main/java/com/baeldung/batch/SpringBatchConfig.java @@ -23,12 +23,14 @@ 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.Profile; import org.springframework.core.io.Resource; import org.springframework.oxm.Marshaller; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import java.text.ParseException; +@Profile("spring") public class SpringBatchConfig { @Autowired private JobBuilderFactory jobBuilderFactory; diff --git a/spring-batch/src/main/java/com/baeldung/batch/SpringConfig.java b/spring-batch/src/main/java/com/baeldung/batch/SpringConfig.java index 73a07482ce..dc6c242996 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/SpringConfig.java +++ b/spring-batch/src/main/java/com/baeldung/batch/SpringConfig.java @@ -13,6 +13,7 @@ import org.springframework.batch.support.transaction.ResourcelessTransactionMana import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.core.io.Resource; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.jdbc.datasource.init.DataSourceInitializer; @@ -21,6 +22,7 @@ import org.springframework.transaction.PlatformTransactionManager; @Configuration @EnableBatchProcessing +@Profile("spring") public class SpringConfig { @Value("org/springframework/batch/core/schema-drop-sqlite.sql") diff --git a/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBatchApplication.java b/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBatchApplication.java new file mode 100644 index 0000000000..a3c6a45197 --- /dev/null +++ b/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBatchApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.batch.springboot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBatchApplication { + + public static void main(String[] args) { + SpringApplication springApp = new SpringApplication(SpringBatchApplication.class); + springApp.setAdditionalProfiles("spring-boot"); + springApp.run(args); + } + +} diff --git a/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBootBatchConfig.java b/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBootBatchConfig.java new file mode 100644 index 0000000000..57531ebc39 --- /dev/null +++ b/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBootBatchConfig.java @@ -0,0 +1,151 @@ +package com.baeldung.batch.springboot; + +import com.baeldung.batch.model.Transaction; +import com.baeldung.batch.service.*; +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.context.annotation.Profile; +import org.springframework.core.io.Resource; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; + +import java.text.ParseException; + +@Configuration +@EnableBatchProcessing +@Profile("spring-boot") +public class SpringBootBatchConfig { + @Autowired + private JobBuilderFactory jobBuilderFactory; + + @Autowired + private StepBuilderFactory stepBuilderFactory; + + @Value("input/record.csv") + private Resource inputCsv; + + @Value("input/recordWithInvalidData.csv") + private Resource invalidInputCsv; + + @Value("file:xml/output.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 itemProcessor() { + return new CustomItemProcessor(); + } + + @Bean + public ItemProcessor skippingItemProcessor() { + return new SkippingItemProcessor(); + } + + @Bean + public ItemWriter itemWriter3(Marshaller marshaller) { + StaxEventItemWriter itemWriter3 = new StaxEventItemWriter<>(); + itemWriter3.setMarshaller(marshaller); + itemWriter3.setRootTagName("transactionRecord"); + itemWriter3.setResource(outputXml); + return itemWriter3; + } + + @Bean + public Marshaller marshaller3() { + Jaxb2Marshaller marshaller3 = new Jaxb2Marshaller(); + marshaller3.setClassesToBeBound(Transaction.class); + return marshaller3; + } + + @Bean + protected Step step1(@Qualifier("itemProcessor") ItemProcessor processor, ItemWriter itemWriter3) throws ParseException { + return stepBuilderFactory + .get("step1") + . chunk(10) + .reader(itemReader(inputCsv)) + .processor(processor) + .writer(itemWriter3) + .build(); + } + + @Bean(name = "firstBatchJob") + public Job job(@Qualifier("step1") Step step1) { + return jobBuilderFactory.get("firstBatchJob").start(step1).build(); + } + + @Bean + public Step skippingStep(@Qualifier("skippingItemProcessor") ItemProcessor processor, + ItemWriter itemWriter3) throws ParseException { + return stepBuilderFactory + .get("skippingStep") + .chunk(10) + .reader(itemReader(invalidInputCsv)) + .processor(processor) + .writer(itemWriter3) + .faultTolerant() + .skipLimit(2) + .skip(MissingUsernameException.class) + .skip(NegativeAmountException.class) + .build(); + } + + @Bean(name = "skippingBatchJob") + public Job skippingJob(@Qualifier("skippingStep") Step skippingStep) { + return jobBuilderFactory + .get("skippingBatchJob") + .start(skippingStep) + .build(); + } + + @Bean + public Step skipPolicyStep(@Qualifier("skippingItemProcessor") ItemProcessor processor, + ItemWriter itemWriter3) throws ParseException { + return stepBuilderFactory + .get("skipPolicyStep") + .chunk(10) + .reader(itemReader(invalidInputCsv)) + .processor(processor) + .writer(itemWriter3) + .faultTolerant() + .skipPolicy(new CustomSkipPolicy()) + .build(); + } + + @Bean(name = "skipPolicyBatchJob") + public Job skipPolicyBatchJob(@Qualifier("skipPolicyStep") Step skipPolicyStep) { + return jobBuilderFactory + .get("skipPolicyBatchJob") + .start(skipPolicyStep) + .build(); + } + +}