JAVA-18609 GitHub Issue: Spring Batch - JobBuilderFactory and StepBui… (#13618)

* JAVA-18609 GitHub Issue: Spring Batch - JobBuilderFactory and StepBuilderFactory are deprecated

---------

Co-authored-by: timis1 <noreplay@yahoo.com>
This commit is contained in:
timis1 2023-04-05 12:46:50 +03:00 committed by GitHub
parent d0d58509e2
commit d1249befd1
53 changed files with 548 additions and 742 deletions

View File

@ -759,6 +759,7 @@
<module>javafx</module>
<module>spring-batch</module>
<module>spring-batch-2</module>
<module>spring-boot-rest</module>
<module>spring-drools</module>
<module>spring-exceptions</module>
@ -781,7 +782,6 @@
<module>server-modules</module>
<module>apache-cxf-modules</module>
<module>spring-aop</module>
<module>jmeter</module>
<module>spring-aop-2</module>
@ -928,7 +928,6 @@
<module>spring-5-webflux</module>
<module>spring-5-webflux-2</module>
<module>spring-activiti</module>
<module>spring-batch-2</module>
<module>spring-core-2</module>
<module>spring-core-3</module>
<module>spring-core-5</module>
@ -1012,6 +1011,7 @@
<module>javafx</module>
<module>spring-batch</module>
<module>spring-batch-2</module>
<module>spring-boot-rest</module>
<module>spring-drools</module>
<module>spring-exceptions</module>
@ -1180,7 +1180,6 @@
<module>spring-5-webflux</module>
<module>spring-5-webflux-2</module>
<module>spring-activiti</module>
<module>spring-batch-2</module>
<module>spring-core-2</module>
<module>spring-core-3</module>
<module>spring-core-5</module>

View File

@ -11,9 +11,9 @@
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
<relativePath>../parent-boot-3</relativePath>
</parent>
<dependencies>
@ -51,8 +51,9 @@
</dependencies>
<properties>
<spring.batch.version>4.3.0</spring.batch.version>
<awaitility.version>3.1.1</awaitility.version>
<spring.batch.version>5.0.0</spring.batch.version>
<awaitility.version>4.2.0</awaitility.version>
<start-class>com.baeldung.batch.SpringBootBatchProcessingApplication</start-class>
</properties>
</project>

View File

@ -4,32 +4,25 @@ import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
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.ClassPathResource;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Value("${file.input}")
private String fileInput;
@ -59,8 +52,8 @@ public class BatchConfiguration {
}
@Bean
public Job importUserJob(JobCompletionNotificationListener listener, Step step1) {
return jobBuilderFactory.get("importUserJob")
public Job importUserJob(JobRepository jobRepository, JobCompletionNotificationListener listener, Step step1) {
return new JobBuilder("importUserJob", jobRepository)
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1)
@ -69,9 +62,9 @@ public class BatchConfiguration {
}
@Bean
public Step step1(JdbcBatchItemWriter<Coffee> writer) {
return stepBuilderFactory.get("step1")
.<Coffee, Coffee> chunk(10)
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, JdbcBatchItemWriter<Coffee> writer) {
return new StepBuilder("step1", jobRepository)
.<Coffee, Coffee> chunk(10, transactionManager)
.reader(reader())
.processor(processor())
.writer(writer)

View File

@ -10,7 +10,7 @@ public class CoffeeItemProcessor implements ItemProcessor<Coffee, Coffee> {
private static final Logger LOGGER = LoggerFactory.getLogger(CoffeeItemProcessor.class);
@Override
public Coffee process(final Coffee coffee) throws Exception {
public Coffee process(final Coffee coffee) {
String brand = coffee.getBrand().toUpperCase();
String origin = coffee.getOrigin().toUpperCase();
String chracteristics = coffee.getCharacteristics().toUpperCase();

View File

@ -4,13 +4,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class JobCompletionNotificationListener extends JobExecutionListenerSupport {
public class JobCompletionNotificationListener implements JobExecutionListener {
private static final Logger LOGGER = LoggerFactory.getLogger(JobCompletionNotificationListener.class);

View File

@ -7,15 +7,16 @@ import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
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.job.builder.JobBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
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.BeanWrapperFieldSetMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
@ -24,17 +25,16 @@ import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.ScheduledMethodRunnable;
import org.springframework.transaction.PlatformTransactionManager;
import java.util.Date;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@Configuration
@EnableBatchProcessing
@EnableScheduling
public class SpringBatchScheduler {
@ -46,21 +46,21 @@ public class SpringBatchScheduler {
private final Map<Object, ScheduledFuture<?>> scheduledTasks = new IdentityHashMap<>();
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Autowired
private JobLauncher jobLauncher;
@Autowired
private JobRepository jobRepository;
@Autowired
private PlatformTransactionManager transactionManager;
@Scheduled(fixedRate = 2000)
public void launchJob() throws Exception {
Date date = new Date();
logger.debug("scheduler starts at " + date);
if (enabled.get()) {
JobExecution jobExecution = jobLauncher.run(job(), new JobParametersBuilder().addDate("launchDate", date)
JobExecution jobExecution = jobLauncher.run(job(jobRepository, transactionManager), new JobParametersBuilder().addDate("launchDate", date)
.toJobParameters());
batchRunCounter.incrementAndGet();
logger.debug("Batch job ends with status as " + jobExecution.getStatus());
@ -106,17 +106,16 @@ public class SpringBatchScheduler {
}
@Bean
public Job job() {
return jobBuilderFactory
.get("job")
.start(readBooks())
public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("job", jobRepository)
.start(readBooks(jobRepository, transactionManager))
.build();
}
@Bean
protected Step readBooks() {
return stepBuilderFactory.get("readBooks")
.<Book, Book> chunk(2)
protected Step readBooks(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("readBooks", jobRepository)
.<Book, Book> chunk(2, transactionManager)
.reader(reader())
.writer(writer())
.build();
@ -128,7 +127,7 @@ public class SpringBatchScheduler {
.resource(new ClassPathResource("books.csv"))
.delimited()
.names(new String[] { "id", "name" })
.fieldSetMapper(new BeanWrapperFieldSetMapper<Book>() {
.fieldSetMapper(new BeanWrapperFieldSetMapper<>() {
{
setTargetType(Book.class);
}
@ -138,15 +137,10 @@ public class SpringBatchScheduler {
@Bean
public ItemWriter<Book> writer() {
return new ItemWriter<Book>() {
@Override
public void write(List<? extends Book> items) throws Exception {
logger.debug("writer..." + items.size());
for (Book item : items) {
logger.debug(item.toString());
}
return items -> {
logger.debug("writer..." + items.size());
for (Book item : items) {
logger.debug(item.toString());
}
};
}

View File

@ -1,11 +1,10 @@
package com.baeldung.batch;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
@ -13,16 +12,17 @@ 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.test.context.SpringBootTest;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringBatchTest
@SpringBootTest
@DirtiesContext
@SpringJUnitConfig(BatchConfiguration.class)
@PropertySource("classpath:application.properties")
@RunWith(SpringRunner.class)
@EnableAutoConfiguration
public class SpringBootBatchIntegrationTest {
@Autowired
@ -31,7 +31,10 @@ public class SpringBootBatchIntegrationTest {
@Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
@After
@MockBean
private JobCompletionNotificationListener jobCompletionNotificationListener;
@AfterEach
public void cleanUp() {
jobRepositoryTestUtils.removeJobExecutions();
}
@ -42,8 +45,8 @@ public class SpringBootBatchIntegrationTest {
JobInstance jobInstance = jobExecution.getJobInstance();
ExitStatus jobExitStatus = jobExecution.getExitStatus();
assertThat(jobInstance.getJobName(), is("importUserJob"));
assertThat(jobExitStatus.getExitCode(), is("COMPLETED"));
assertEquals("importUserJob", jobInstance.getJobName());
assertEquals("COMPLETED", jobExitStatus.getExitCode());
}
}

View File

@ -1,28 +1,20 @@
package com.baeldung.batchscheduler;
import com.baeldung.batchscheduler.SpringBatchScheduler;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.test.context.SpringBatchTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import static org.awaitility.Awaitility.await;
import static java.util.concurrent.TimeUnit.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBatchTest
@SpringBootTest
@DirtiesContext
@PropertySource("classpath:application.properties")
@RunWith(SpringRunner.class)
public class SpringBatchSchedulerIntegrationTest {
@Autowired
@ -31,37 +23,36 @@ public class SpringBatchSchedulerIntegrationTest {
@Test
public void stopJobsWhenSchedulerDisabled() {
SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class);
await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
await().untilAsserted(() -> assertEquals(2, schedulerBean.getBatchRunCounter()
.get()));
schedulerBean.stop();
await().atLeast(3, SECONDS);
Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
.get());
assertEquals(2, schedulerBean.getBatchRunCounter().get());
}
@Test
public void stopJobSchedulerWhenSchedulerDestroyed() throws Exception {
public void stopJobSchedulerWhenSchedulerDestroyed() {
ScheduledAnnotationBeanPostProcessor bean = context.getBean(ScheduledAnnotationBeanPostProcessor.class);
SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class);
await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
await().untilAsserted(() -> assertEquals(2, schedulerBean.getBatchRunCounter()
.get()));
bean.postProcessBeforeDestruction(schedulerBean, "SpringBatchScheduler");
await().atLeast(3, SECONDS);
Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
assertEquals(2, schedulerBean.getBatchRunCounter()
.get());
}
@Test
public void stopJobSchedulerWhenFutureTasksCancelled() throws Exception {
public void stopJobSchedulerWhenFutureTasksCancelled() {
SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class);
await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
await().untilAsserted(() -> assertEquals(2, schedulerBean.getBatchRunCounter()
.get()));
schedulerBean.cancelFutureSchedulerTasks();
await().atLeast(3, SECONDS);
Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
assertEquals(2, schedulerBean.getBatchRunCounter()
.get());
}

View File

@ -11,9 +11,9 @@
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
<relativePath>../parent-boot-3</relativePath>
</parent>
<dependencies>
@ -22,25 +22,15 @@
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson-datatype.version}</version>
</dependency>
<!-- JAXB APIs & runtime no longer provided in JDK 11 -->
<!-- see http://openjdk.java.net/jeps/320 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>${jaxb.version}</version>
</dependency>
<!-- SQLite database driver -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>${sqlite.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@ -53,20 +43,9 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
@ -78,19 +57,29 @@
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${http-client.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>${jettison.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<properties>
<spring.version>5.3.0</spring.version>
<spring.batch.version>4.3.0</spring.batch.version>
<sqlite.version>3.15.1</sqlite.version>
<opencsv.version>4.1</opencsv.version>
<jaxb.version>2.3.1</jaxb.version>
<jackson-datatype.version>2.12.3</jackson-datatype.version>
<spring.version>6.0.6</spring.version>
<opencsv.version>5.7.1</opencsv.version>
<jaxb.version>4.0.2</jaxb.version>
<jackson-datatype.version>2.14.2</jackson-datatype.version>
<http-client.version>4.5.14</http-client.version>
<jettison.version>1.5.3</jettison.version>
<start-class>com.baeldung.batchtesting.SpringBatchApplication</start-class>
</properties>
</project>

Binary file not shown.

View File

@ -18,20 +18,19 @@ public class App {
public static void main(final String[] args) {
// Spring Java config
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(SpringConfig.class);
context.getEnvironment().addActiveProfile("spring");
context.register(SpringBatchConfig.class);
context.register(SpringBatchRetryConfig.class);
context.refresh();
// Spring xml config
// ApplicationContext context = new ClassPathXmlApplicationContext("spring-batch.xml");
// ApplicationContext context = new ClassPathXmlApplicationContext("spring-batch-intro.xml");
runJob(context, "firstBatchJob");
runJob(context, "skippingBatchJob");
runJob(context, "skipPolicyBatchJob");
runJob(context, "retryBatchJob");
}
private static void runJob(AnnotationConfigApplicationContext context, String batchJobName) {

View File

@ -1,5 +1,7 @@
package com.baeldung.batch;
import javax.sql.DataSource;
import com.baeldung.batch.model.Transaction;
import com.baeldung.batch.service.CustomItemProcessor;
import com.baeldung.batch.service.CustomSkipPolicy;
@ -7,10 +9,15 @@ import com.baeldung.batch.service.MissingUsernameException;
import com.baeldung.batch.service.NegativeAmountException;
import com.baeldung.batch.service.RecordFieldSetMapper;
import com.baeldung.batch.service.SkippingItemProcessor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
@ -19,24 +26,23 @@ 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.batch.support.transaction.ResourcelessTransactionManager;
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.core.io.WritableResource;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.transaction.PlatformTransactionManager;
import java.text.ParseException;
@Configuration
@Profile("spring")
public class SpringBatchConfig {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Value("input/record.csv")
private Resource inputCsv;
@ -45,9 +51,9 @@ public class SpringBatchConfig {
private Resource invalidInputCsv;
@Value("file:xml/output.xml")
private Resource outputXml;
private WritableResource outputXml;
public ItemReader<Transaction> itemReader(Resource inputData) throws UnexpectedInputException, ParseException {
public ItemReader<Transaction> itemReader(Resource inputData) throws UnexpectedInputException {
FlatFileItemReader<Transaction> reader = new FlatFileItemReader<>();
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
String[] tokens = {"username", "userid", "transactiondate", "amount"};
@ -88,10 +94,10 @@ public class SpringBatchConfig {
}
@Bean
protected Step step1(@Qualifier("itemProcessor") ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> writer) throws ParseException {
return stepBuilderFactory
.get("step1")
.<Transaction, Transaction> chunk(10)
protected Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("itemProcessor") ItemProcessor<Transaction,
Transaction> processor, ItemWriter<Transaction> writer) {
return new StepBuilder("step1", jobRepository)
.<Transaction, Transaction> chunk(10, transactionManager)
.reader(itemReader(inputCsv))
.processor(processor)
.writer(writer)
@ -99,16 +105,15 @@ public class SpringBatchConfig {
}
@Bean(name = "firstBatchJob")
public Job job(@Qualifier("step1") Step step1) {
return jobBuilderFactory.get("firstBatchJob").start(step1).build();
public Job job(JobRepository jobRepository, @Qualifier("step1") Step step1) {
return new JobBuilder("firstBatchJob", jobRepository).preventRestart().start(step1).build();
}
@Bean
public Step skippingStep(@Qualifier("skippingItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> writer) throws ParseException {
return stepBuilderFactory
.get("skippingStep")
.<Transaction, Transaction>chunk(10)
public Step skippingStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingItemProcessor") ItemProcessor<Transaction,
Transaction> processor, ItemWriter<Transaction> writer) {
return new StepBuilder("skippingStep", jobRepository)
.<Transaction, Transaction>chunk(10, transactionManager)
.reader(itemReader(invalidInputCsv))
.processor(processor)
.writer(writer)
@ -120,19 +125,18 @@ public class SpringBatchConfig {
}
@Bean(name = "skippingBatchJob")
public Job skippingJob(@Qualifier("skippingStep") Step skippingStep) {
return jobBuilderFactory
.get("skippingBatchJob")
public Job skippingJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingStep") Step skippingStep) {
return new JobBuilder("skippingBatchJob", jobRepository)
.start(skippingStep)
.preventRestart()
.build();
}
@Bean
public Step skipPolicyStep(@Qualifier("skippingItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> writer) throws ParseException {
return stepBuilderFactory
.get("skipPolicyStep")
.<Transaction, Transaction>chunk(10)
public Step skipPolicyStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> writer) {
return new StepBuilder("skipPolicyStep", jobRepository)
.<Transaction, Transaction>chunk(10, transactionManager)
.reader(itemReader(invalidInputCsv))
.processor(processor)
.writer(writer)
@ -142,11 +146,44 @@ public class SpringBatchConfig {
}
@Bean(name = "skipPolicyBatchJob")
public Job skipPolicyBatchJob(@Qualifier("skipPolicyStep") Step skipPolicyStep) {
return jobBuilderFactory
.get("skipPolicyBatchJob")
public Job skipPolicyBatchJob(JobRepository jobRepository, @Qualifier("skipPolicyStep") Step skipPolicyStep) {
return new JobBuilder("skipPolicyBatchJob", jobRepository)
.start(skipPolicyStep)
.preventRestart()
.build();
}
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql")
.addScript("classpath:org/springframework/batch/core/schema-h2.sql")
.build();
}
@Bean(name = "transactionManager")
public PlatformTransactionManager getTransactionManager() {
return new ResourcelessTransactionManager();
}
@Bean(name = "jobRepository")
public JobRepository getJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource());
factory.setTransactionManager(getTransactionManager());
// JobRepositoryFactoryBean's methods Throws Generic Exception,
// it would have been better to have a specific one
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean(name = "jobLauncher")
public JobLauncher getJobLauncher() throws Exception {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
// TaskExecutorJobLauncher's methods Throws Generic Exception,
// it would have been better to have a specific one
jobLauncher.setJobRepository(getJobRepository());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}

View File

@ -1,17 +1,18 @@
package com.baeldung.batch;
import com.baeldung.batch.model.Transaction;
import com.baeldung.batch.service.RecordFieldSetMapper;
import com.baeldung.batch.service.RetryItemProcessor;
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 com.baeldung.batch.model.Transaction;
import com.baeldung.batch.service.RecordFieldSetMapper;
import com.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.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
@ -19,38 +20,30 @@ 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.core.io.WritableResource;
import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import java.text.ParseException;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@EnableBatchProcessing
public class SpringBatchRetryConfig {
private static final String[] tokens = { "username", "userid", "transactiondate", "amount" };
private static final int TWO_SECONDS = 2000;
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Value("input/recordRetry.csv")
private Resource inputCsv;
@Value("file:xml/retryOutput.xml")
private Resource outputXml;
private WritableResource outputXml;
public ItemReader<Transaction> itemReader(Resource inputData) throws ParseException {
public ItemReader<Transaction> itemReader(Resource inputData) {
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
tokenizer.setNames(tokens);
DefaultLineMapper<Transaction> lineMapper = new DefaultLineMapper<>();
@ -93,10 +86,11 @@ public class SpringBatchRetryConfig {
}
@Bean
public Step retryStep(@Qualifier("retryItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> writer) throws ParseException {
return stepBuilderFactory.get("retryStep")
.<Transaction, Transaction>chunk(10)
public Step retryStep(
JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("retryItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> writer) {
return new StepBuilder("retryStep", jobRepository)
.<Transaction, Transaction>chunk(10, transactionManager)
.reader(itemReader(inputCsv))
.processor(processor)
.writer(writer)
@ -108,9 +102,8 @@ public class SpringBatchRetryConfig {
}
@Bean(name = "retryBatchJob")
public Job retryJob(@Qualifier("retryStep") Step retryStep) {
return jobBuilderFactory
.get("retryBatchJob")
public Job retryJob(JobRepository jobRepository, @Qualifier("retryStep") Step retryStep) {
return new JobBuilder("retryBatchJob", jobRepository)
.start(retryStep)
.build();
}

View File

@ -1,80 +0,0 @@
package com.baeldung.batch;
import java.net.MalformedURLException;
import javax.sql.DataSource;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
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;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@EnableBatchProcessing
@Profile("spring")
public class SpringConfig {
@Value("org/springframework/batch/core/schema-drop-sqlite.sql")
private Resource dropReopsitoryTables;
@Value("org/springframework/batch/core/schema-sqlite.sql")
private Resource dataReopsitorySchema;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.sqlite.JDBC");
dataSource.setUrl("jdbc:sqlite:repository.sqlite");
return dataSource;
}
@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) throws MalformedURLException {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.addScript(dropReopsitoryTables);
databasePopulator.addScript(dataReopsitorySchema);
databasePopulator.setIgnoreFailedDrops(true);
DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
initializer.setDatabasePopulator(databasePopulator);
return initializer;
}
private JobRepository getJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource());
factory.setTransactionManager(getTransactionManager());
// JobRepositoryFactoryBean's methods Throws Generic Exception,
// it would have been better to have a specific one
factory.afterPropertiesSet();
return (JobRepository) factory.getObject();
}
private PlatformTransactionManager getTransactionManager() {
return new ResourcelessTransactionManager();
}
public JobLauncher getJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
// SimpleJobLauncher's methods Throws Generic Exception,
// it would have been better to have a specific one
jobLauncher.setJobRepository(getJobRepository());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}

View File

@ -1,10 +1,11 @@
package com.baeldung.batch.model;
import java.time.LocalDateTime;
import com.baeldung.batch.service.adapter.LocalDateTimeAdapter;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.time.LocalDateTime;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@SuppressWarnings("restriction")
@XmlRootElement(name = "transactionRecord")

View File

@ -60,7 +60,7 @@ public class CustomMultiResourcePartitioner implements Partitioner {
*/
@Override
public Map<String, ExecutionContext> partition(int gridSize) {
Map<String, ExecutionContext> map = new HashMap<String, ExecutionContext>(gridSize);
Map<String, ExecutionContext> map = new HashMap<>(gridSize);
int i = 0, k = 1;
for (Resource resource : resources) {
ExecutionContext context = new ExecutionContext();

View File

@ -5,13 +5,13 @@ import com.baeldung.batch.service.RecordFieldSetMapper;
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.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
@ -36,42 +36,35 @@ import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.ParseException;
@Configuration
@EnableBatchProcessing
public class SpringbatchPartitionConfig {
public class SpringBatchPartitionConfig {
@Autowired
ResourcePatternResolver resoursePatternResolver;
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
private ResourcePatternResolver resourcePatternResolver;
@Bean(name = "partitionerJob")
public Job partitionerJob() throws UnexpectedInputException, MalformedURLException, ParseException {
return jobs.get("partitionerJob")
.start(partitionStep())
public Job partitionerJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws UnexpectedInputException, ParseException {
return new JobBuilder("partitionerJob", jobRepository)
.start(partitionStep(jobRepository, transactionManager))
.build();
}
@Bean
public Step partitionStep() throws UnexpectedInputException, MalformedURLException, ParseException {
return steps.get("partitionStep")
public Step partitionStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws UnexpectedInputException, ParseException {
return new StepBuilder("partitionStep", jobRepository)
.partitioner("slaveStep", partitioner())
.step(slaveStep())
.step(slaveStep(jobRepository, transactionManager))
.taskExecutor(taskExecutor())
.build();
}
@Bean
public Step slaveStep() throws UnexpectedInputException, MalformedURLException, ParseException {
return steps.get("slaveStep")
.<Transaction, Transaction>chunk(1)
public Step slaveStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws UnexpectedInputException, ParseException {
return new StepBuilder("slaveStep", jobRepository)
.<Transaction, Transaction>chunk(1, transactionManager)
.reader(itemReader(null))
.writer(itemWriter(marshaller(), null))
.build();
@ -82,7 +75,7 @@ public class SpringbatchPartitionConfig {
CustomMultiResourcePartitioner partitioner = new CustomMultiResourcePartitioner();
Resource[] resources;
try {
resources = resoursePatternResolver.getResources("file:src/main/resources/input/partitioner/*.csv");
resources = resourcePatternResolver.getResources("file:src/main/resources/input/partitioner/*.csv");
} catch (IOException e) {
throw new RuntimeException("I/O problems when resolving the input file pattern.", e);
}
@ -108,7 +101,7 @@ public class SpringbatchPartitionConfig {
@Bean(destroyMethod = "")
@StepScope
public StaxEventItemWriter<Transaction> itemWriter(Marshaller marshaller, @Value("#{stepExecutionContext[opFileName]}") String filename) throws MalformedURLException {
public StaxEventItemWriter<Transaction> itemWriter(Marshaller marshaller, @Value("#{stepExecutionContext[opFileName]}") String filename) {
StaxEventItemWriter<Transaction> itemWriter = new StaxEventItemWriter<>();
itemWriter.setMarshaller(marshaller);
itemWriter.setRootTagName("transactionRecord");
@ -133,7 +126,8 @@ public class SpringbatchPartitionConfig {
return taskExecutor;
}
private JobRepository getJobRepository() throws Exception {
@Bean(name = "jobRepository")
public JobRepository getJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource());
factory.setTransactionManager(getTransactionManager());
@ -143,20 +137,23 @@ public class SpringbatchPartitionConfig {
return factory.getObject();
}
private DataSource dataSource() {
@Bean(name = "dataSource")
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.HSQL)
return builder.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql")
.addScript("classpath:org/springframework/batch/core/schema-h2.sql")
.build();
}
private PlatformTransactionManager getTransactionManager() {
@Bean(name = "transactionManager")
public PlatformTransactionManager getTransactionManager() {
return new ResourcelessTransactionManager();
}
@Bean(name = "jobLauncher")
public JobLauncher getJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
// SimpleJobLauncher's methods Throws Generic Exception,
// it would have been better to have a specific one
jobLauncher.setJobRepository(getJobRepository());

View File

@ -8,14 +8,14 @@ import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringbatchPartitionerApp {
public class SpringBatchPartitionerApp {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringbatchPartitionerApp.class);
private static final Logger LOGGER = LoggerFactory.getLogger(SpringBatchPartitionerApp.class);
public static void main(final String[] args) {
// Spring Java config
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(SpringbatchPartitionConfig.class);
context.register(SpringBatchPartitionConfig.class);
context.refresh();
final JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");

View File

@ -9,19 +9,13 @@ public class CustomSkipPolicy implements SkipPolicy {
private static final int INVALID_TX_AMOUNT_LIMIT = -1000;
@Override
public boolean shouldSkip(Throwable throwable, int skipCount) throws SkipLimitExceededException {
public boolean shouldSkip(Throwable throwable, long skipCount) throws SkipLimitExceededException {
if (throwable instanceof MissingUsernameException && skipCount < MAX_SKIP_COUNT) {
return true;
}
if (throwable instanceof NegativeAmountException && skipCount < MAX_SKIP_COUNT ) {
NegativeAmountException ex = (NegativeAmountException) throwable;
if(ex.getAmount() < INVALID_TX_AMOUNT_LIMIT){
return false;
} else{
return true;
}
if (throwable instanceof NegativeAmountException ex && skipCount < MAX_SKIP_COUNT ) {
return ex.getAmount() >= INVALID_TX_AMOUNT_LIMIT;
}
return false;

View File

@ -10,7 +10,7 @@ import java.time.format.DateTimeFormatter;
public class RecordFieldSetMapper implements FieldSetMapper<Transaction> {
public Transaction mapFieldSet(FieldSet fieldSet) throws BindException {
public Transaction mapFieldSet(FieldSet fieldSet) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyy");

View File

@ -5,15 +5,13 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import com.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;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
public class RetryItemProcessor implements ItemProcessor<Transaction, Transaction> {
private static final Logger LOGGER = LoggerFactory.getLogger(RetryItemProcessor.class);
@ -22,7 +20,7 @@ public class RetryItemProcessor implements ItemProcessor<Transaction, Transactio
private CloseableHttpClient closeableHttpClient;
@Override
public Transaction process(Transaction transaction) throws IOException, JSONException {
public Transaction process(Transaction transaction) throws Exception {
LOGGER.info("Attempting to process user with id={}", transaction.getUserId());
HttpResponse response = fetchMoreUserDetails(transaction.getUserId());
@ -35,7 +33,7 @@ public class RetryItemProcessor implements ItemProcessor<Transaction, Transactio
return transaction;
}
private HttpResponse fetchMoreUserDetails(int id) throws IOException {
private HttpResponse fetchMoreUserDetails(int id) throws Exception {
final HttpGet request = new HttpGet("http://www.baeldung.com:81/user/" + id);
return closeableHttpClient.execute(request);
}

View File

@ -1,9 +1,10 @@
package com.baeldung.batch.service.adapter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
public class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime> {
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

View File

@ -5,8 +5,9 @@ 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.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
@ -15,27 +16,21 @@ 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.core.io.WritableResource;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import java.text.ParseException;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@EnableBatchProcessing
@Profile("spring-boot")
public class SpringBootBatchConfig {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Value("input/record.csv")
private Resource inputCsv;
@ -44,9 +39,9 @@ public class SpringBootBatchConfig {
private Resource invalidInputCsv;
@Value("file:xml/output.xml")
private Resource outputXml;
private WritableResource outputXml;
public ItemReader<Transaction> itemReader(Resource inputData) throws UnexpectedInputException, ParseException {
public ItemReader<Transaction> itemReader(Resource inputData) throws UnexpectedInputException {
FlatFileItemReader<Transaction> reader = new FlatFileItemReader<>();
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
String[] tokens = {"username", "userid", "transactiondate", "amount"};
@ -86,11 +81,10 @@ public class SpringBootBatchConfig {
return marshaller3;
}
@Bean
protected Step step1(@Qualifier("itemProcessor") ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> itemWriter3) throws ParseException {
return stepBuilderFactory
.get("step1")
.<Transaction, Transaction> chunk(10)
@Bean(name = "step1")
protected Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("itemProcessor") ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> itemWriter3) {
return new StepBuilder("step1", jobRepository)
.<Transaction, Transaction> chunk(10, transactionManager)
.reader(itemReader(inputCsv))
.processor(processor)
.writer(itemWriter3)
@ -98,16 +92,15 @@ public class SpringBootBatchConfig {
}
@Bean(name = "firstBatchJob")
public Job job(@Qualifier("step1") Step step1) {
return jobBuilderFactory.get("firstBatchJob").start(step1).build();
public Job job(@Qualifier("step1") Step step1, JobRepository jobRepository) {
return new JobBuilder("firstBatchJob", jobRepository).start(step1).build();
}
@Bean
public Step skippingStep(@Qualifier("skippingItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> itemWriter3) throws ParseException {
return stepBuilderFactory
.get("skippingStep")
.<Transaction, Transaction>chunk(10)
public Step skippingStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> itemWriter3) {
return new StepBuilder("skippingStep", jobRepository)
.<Transaction, Transaction>chunk(10, transactionManager)
.reader(itemReader(invalidInputCsv))
.processor(processor)
.writer(itemWriter3)
@ -119,19 +112,17 @@ public class SpringBootBatchConfig {
}
@Bean(name = "skippingBatchJob")
public Job skippingJob(@Qualifier("skippingStep") Step skippingStep) {
return jobBuilderFactory
.get("skippingBatchJob")
public Job skippingJob(JobRepository jobRepository, @Qualifier("skippingStep") Step skippingStep) {
return new JobBuilder("skippingBatchJob", jobRepository)
.start(skippingStep)
.build();
}
@Bean
public Step skipPolicyStep(@Qualifier("skippingItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> itemWriter3) throws ParseException {
return stepBuilderFactory
.get("skipPolicyStep")
.<Transaction, Transaction>chunk(10)
@Bean(name = "skipPolicyStep")
public Step skipPolicyStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingItemProcessor") ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> itemWriter3) {
return new StepBuilder("skipPolicyStep", jobRepository)
.<Transaction, Transaction>chunk(10, transactionManager)
.reader(itemReader(invalidInputCsv))
.processor(processor)
.writer(itemWriter3)
@ -141,11 +132,9 @@ public class SpringBootBatchConfig {
}
@Bean(name = "skipPolicyBatchJob")
public Job skipPolicyBatchJob(@Qualifier("skipPolicyStep") Step skipPolicyStep) {
return jobBuilderFactory
.get("skipPolicyBatchJob")
public Job skipPolicyBatchJob(JobRepository jobRepository, @Qualifier("skipPolicyStep") Step skipPolicyStep) {
return new JobBuilder("skipPolicyBatchJob", jobRepository)
.start(skipPolicyStep)
.build();
}
}

View File

@ -1,7 +1,5 @@
package com.baeldung.batchtesting;
import java.io.IOException;
import com.baeldung.batchtesting.model.Book;
import com.baeldung.batchtesting.model.BookDetails;
import com.baeldung.batchtesting.model.BookRecord;
@ -12,10 +10,10 @@ 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.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
@ -25,27 +23,19 @@ 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;
import org.springframework.transaction.PlatformTransactionManager;
@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<BookRecord> csvItemReader(@Value("#{jobParameters['file.input']}") String input) {
@ -65,7 +55,7 @@ public class SpringBatchConfiguration {
@Bean
@StepScope
public JsonFileItemWriter<Book> jsonItemWriter(@Value("#{jobParameters['file.output']}") String output) throws IOException {
public JsonFileItemWriter<Book> jsonItemWriter(@Value("#{jobParameters['file.output']}") String output) {
JsonFileItemWriterBuilder<Book> builder = new JsonFileItemWriterBuilder<>();
JacksonJsonObjectMarshaller<Book> marshaller = new JacksonJsonObjectMarshaller<>();
LOGGER.info("Configuring writer to output {}", output);
@ -81,7 +71,7 @@ public class SpringBatchConfiguration {
@Bean
@StepScope
public ListItemWriter<BookDetails> listItemWriter() {
return new ListItemWriter<BookDetails>();
return new ListItemWriter<>();
}
@Bean
@ -96,12 +86,11 @@ public class SpringBatchConfiguration {
return new BookDetailsItemProcessor();
}
@Bean
public Step step1(ItemReader<BookRecord> csvItemReader, ItemWriter<Book> jsonItemWriter) throws IOException {
@Bean(name = "step1")
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, ItemReader<BookRecord> csvItemReader, ItemWriter<Book> jsonItemWriter) {
// @formatter:off
return stepBuilderFactory
.get("step1")
.<BookRecord, Book> chunk(3)
return new StepBuilder("step1", jobRepository)
.<BookRecord, Book> chunk(3, transactionManager)
.reader(csvItemReader)
.processor(bookItemProcessor())
.writer(jsonItemWriter)
@ -109,12 +98,11 @@ public class SpringBatchConfiguration {
// @formatter:on
}
@Bean
public Step step2(ItemReader<BookRecord> csvItemReader, ItemWriter<BookDetails> listItemWriter) {
@Bean(name = "step2")
public Step step2(JobRepository jobRepository, PlatformTransactionManager transactionManager, ItemReader<BookRecord> csvItemReader, ItemWriter<BookDetails> listItemWriter) {
// @formatter:off
return stepBuilderFactory
.get("step2")
.<BookRecord, BookDetails> chunk(3)
return new StepBuilder("step2", jobRepository)
.<BookRecord, BookDetails> chunk(3, transactionManager)
.reader(csvItemReader)
.processor(bookDetailsItemProcessor())
.writer(listItemWriter)
@ -123,15 +111,13 @@ public class SpringBatchConfiguration {
}
@Bean(name = "transformBooksRecords")
public Job transformBookRecords(Step step1, Step step2) throws IOException {
public Job transformBookRecords(JobRepository jobRepository, Step step1, Step step2) {
// @formatter:off
return jobBuilderFactory
.get("transformBooksRecords")
return new JobBuilder("transformBooksRecords", jobRepository)
.flow(step1)
.next(step2)
.end()
.build();
// @formatter:on
}
}

View File

@ -11,7 +11,7 @@ public class BookDetailsItemProcessor implements ItemProcessor<BookRecord, BookD
private static Logger LOGGER = LoggerFactory.getLogger(BookDetailsItemProcessor.class);
@Override
public BookDetails process(BookRecord item) throws Exception {
public BookDetails process(BookRecord item) {
BookDetails bookDetails = new BookDetails();
bookDetails.setBookFormat(item.getBookFormat());
bookDetails.setBookISBN(item.getBookISBN());

View File

@ -11,7 +11,7 @@ public class BookItemProcessor implements ItemProcessor<BookRecord, Book> {
private static Logger LOGGER = LoggerFactory.getLogger(BookItemProcessor.class);
@Override
public Book process(BookRecord item) throws Exception {
public Book process(BookRecord item) {
Book book = new Book();
book.setAuthor(item.getBookAuthor());
book.setName(item.getBookName());

View File

@ -9,7 +9,7 @@ import org.springframework.validation.BindException;
public class BookRecordFieldSetMapper implements FieldSetMapper<BookRecord> {
@Override
public BookRecord mapFieldSet(FieldSet fieldSet) throws BindException {
public BookRecord mapFieldSet(FieldSet fieldSet) {
BookRecord bookRecord = new BookRecord();
bookRecord.setBookName(fieldSet.readString("bookname"));
bookRecord.setBookAuthor(fieldSet.readString("bookauthor"));

View File

@ -21,9 +21,9 @@ public class LineReader implements ItemReader<Line>, StepExecutionListener {
}
@Override
public Line read() throws Exception {
public Line read() {
Line line = fu.readLine();
if (line != null) logger.debug("Read line: " + line.toString());
if (line != null) logger.debug("Read line: " + line);
return line;
}

View File

@ -7,10 +7,9 @@ import org.slf4j.LoggerFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.item.Chunk;
import org.springframework.batch.item.ItemWriter;
import java.util.List;
public class LinesWriter implements ItemWriter<Line>, StepExecutionListener {
private final Logger logger = LoggerFactory.getLogger(LinesWriter.class);
@ -30,7 +29,7 @@ public class LinesWriter implements ItemWriter<Line>, StepExecutionListener {
}
@Override
public void write(List<? extends Line> lines) throws Exception {
public void write(Chunk<? extends Line> lines) {
for (Line line : lines) {
fu.writeLine(line);
logger.debug("Wrote line " + line.toString());

View File

@ -6,67 +6,19 @@ import com.baeldung.taskletsvschunks.chunks.LinesWriter;
import com.baeldung.taskletsvschunks.model.Line;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
@EnableBatchProcessing
public class ChunksConfig {
@Autowired private JobBuilderFactory jobs;
@Autowired private StepBuilderFactory steps;
@Bean
public JobLauncherTestUtils jobLauncherTestUtils() {
return new JobLauncherTestUtils();
}
@Bean
public JobRepository jobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource());
factory.setTransactionManager(transactionManager());
return factory.getObject();
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.sqlite.JDBC");
dataSource.setUrl("jdbc:sqlite:repository.sqlite");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
@Bean
public JobLauncher jobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository());
return jobLauncher;
}
@Bean
public ItemReader<Line> itemReader() {
return new LineReader();
@ -82,20 +34,19 @@ public class ChunksConfig {
return new LinesWriter();
}
@Bean
protected Step processLines(ItemReader<Line> reader, ItemProcessor<Line, Line> processor, ItemWriter<Line> writer) {
return steps.get("processLines").<Line, Line> chunk(2)
@Bean(name = "processLines")
protected Step processLines(JobRepository jobRepository, PlatformTransactionManager transactionManager, ItemReader<Line> reader, ItemProcessor<Line, Line> processor, ItemWriter<Line> writer) {
return new StepBuilder("processLines", jobRepository).<Line, Line> chunk(2, transactionManager)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
@Bean
public Job job() {
return jobs
.get("chunksJob")
.start(processLines(itemReader(), itemProcessor(), itemWriter()))
@Bean(name = "chunksJob")
public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("chunksJob", jobRepository)
.start(processLines(jobRepository, transactionManager, itemReader(), itemProcessor(), itemWriter()))
.build();
}

View File

@ -5,64 +5,16 @@ import com.baeldung.taskletsvschunks.tasklets.LinesReader;
import com.baeldung.taskletsvschunks.tasklets.LinesWriter;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
@EnableBatchProcessing
public class TaskletsConfig {
@Autowired private JobBuilderFactory jobs;
@Autowired private StepBuilderFactory steps;
@Bean
public JobLauncherTestUtils jobLauncherTestUtils() {
return new JobLauncherTestUtils();
}
@Bean
public JobRepository jobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource());
factory.setTransactionManager(transactionManager());
return factory.getObject();
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.sqlite.JDBC");
dataSource.setUrl("jdbc:sqlite:repository.sqlite");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
@Bean
public JobLauncher jobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository());
return jobLauncher;
}
@Bean
public LinesReader linesReader() {
return new LinesReader();
@ -79,36 +31,32 @@ public class TaskletsConfig {
}
@Bean
protected Step readLines() {
return steps
.get("readLines")
.tasklet(linesReader())
protected Step readLines(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("readLines", jobRepository)
.tasklet(linesReader(), transactionManager)
.build();
}
@Bean
protected Step processLines() {
return steps
.get("processLines")
.tasklet(linesProcessor())
protected Step processLines(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("processLines", jobRepository)
.tasklet(linesProcessor(), transactionManager)
.build();
}
@Bean
protected Step writeLines() {
return steps
.get("writeLines")
.tasklet(linesWriter())
protected Step writeLines(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("writeLines", jobRepository)
.tasklet(linesWriter(), transactionManager)
.build();
}
@Bean
public Job job() {
return jobs
.get("taskletsJob")
.start(readLines())
.next(processLines())
.next(writeLines())
public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("taskletsJob", jobRepository)
.start(readLines(jobRepository, transactionManager))
.next(processLines(jobRepository, transactionManager))
.next(writeLines(jobRepository, transactionManager))
.build();
}

View File

@ -24,7 +24,7 @@ public class LinesReader implements Tasklet, StepExecutionListener {
@Override
public void beforeStep(StepExecution stepExecution) {
lines = new ArrayList<Line>();
lines = new ArrayList<>();
fu = new FileUtils("taskletsvschunks/input/tasklets-vs-chunks.csv");
logger.debug("Lines Reader initialized.");
}

View File

@ -15,7 +15,7 @@ public class ConditionalFlowApplication implements CommandLineRunner {
}
@Override
public void run(String... args) throws Exception {
public void run(String... args) {
logger.info("Running conditional flow application...");
}
}

View File

@ -6,39 +6,49 @@ import org.baeldung.conditionalflow.step.*;
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.job.builder.JobBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.transaction.PlatformTransactionManager;
import static org.baeldung.conditionalflow.NumberInfoDecider.NOTIFY;
import javax.sql.DataSource;
@Configuration
@EnableBatchProcessing
public class NumberInfoConfig {
@Bean
@Qualifier("NotificationStep")
public Step notificationStep(StepBuilderFactory sbf) {
return sbf.get("Notify step")
.tasklet(new NotifierTasklet())
public Step notificationStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("Notify step", jobRepository)
.tasklet(new NotifierTasklet(), transactionManager)
.build();
}
public Step numberGeneratorStep(StepBuilderFactory sbf, int[] values, String prepend) {
return sbf.get("Number generator")
.<NumberInfo, Integer> chunk(1)
public Step numberGeneratorStep(JobRepository jobRepositories, PlatformTransactionManager transactionManager, int[] values, String prepend) {
return new StepBuilder("Number generator", jobRepositories)
.<NumberInfo, Integer> chunk(1, transactionManager)
.reader(new NumberInfoGenerator(values))
.processor(new NumberInfoClassifier())
.writer(new PrependingStdoutWriter<>(prepend))
.build();
}
public Step numberGeneratorStepDecider(StepBuilderFactory sbf, int[] values, String prepend) {
return sbf.get("Number generator decider")
.<NumberInfo, Integer> chunk(1)
public Step numberGeneratorStepDecider(JobRepository jobRepositories, PlatformTransactionManager transactionManager, int[] values, String prepend) {
return new StepBuilder("Number generator decider", jobRepositories)
.<NumberInfo, Integer> chunk(1, transactionManager)
.reader(new NumberInfoGenerator(values))
.processor(new NumberInfoClassifierWithDecider())
.writer(new PrependingStdoutWriter<>(prepend))
@ -47,10 +57,10 @@ public class NumberInfoConfig {
@Bean
@Qualifier("first_job")
public Job numberGeneratorNonNotifierJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, @Qualifier("NotificationStep") Step notificationStep) {
public Job numberGeneratorNonNotifierJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("NotificationStep") Step notificationStep) {
int[] nonNotifierData = { -1, -2, -3 };
Step step = numberGeneratorStep(stepBuilderFactory, nonNotifierData, "First Dataset Processor");
return jobBuilderFactory.get("Number generator - first dataset")
Step step = numberGeneratorStep(jobRepository, transactionManager, nonNotifierData, "First Dataset Processor");
return new JobBuilder("Number generator - first dataset", jobRepository)
.start(step)
.on(NOTIFY)
.to(notificationStep)
@ -63,10 +73,10 @@ public class NumberInfoConfig {
@Bean
@Qualifier("second_job")
public Job numberGeneratorNotifierJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, @Qualifier("NotificationStep") Step notificationStep) {
public Job numberGeneratorNotifierJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("NotificationStep") Step notificationStep) {
int[] billableData = { 11, -2, -3 };
Step dataProviderStep = numberGeneratorStep(stepBuilderFactory, billableData, "Second Dataset Processor");
return jobBuilderFactory.get("Number generator - second dataset")
Step dataProviderStep = numberGeneratorStep(jobRepository, transactionManager, billableData, "Second Dataset Processor");
return new JobBuilder("Number generator - second dataset", jobRepository)
.start(dataProviderStep)
.on(NOTIFY)
.to(notificationStep)
@ -77,10 +87,10 @@ public class NumberInfoConfig {
@Bean
@Qualifier("third_job")
@Primary
public Job numberGeneratorNotifierJobWithDecider(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, @Qualifier("NotificationStep") Step notificationStep) {
public Job numberGeneratorNotifierJobWithDecider(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("NotificationStep") Step notificationStep) {
int[] billableData = { 11, -2, -3 };
Step dataProviderStep = numberGeneratorStepDecider(stepBuilderFactory, billableData, "Third Dataset Processor");
return jobBuilderFactory.get("Number generator - third dataset")
Step dataProviderStep = numberGeneratorStepDecider(jobRepository, transactionManager, billableData, "Third Dataset Processor");
return new JobBuilder("Number generator - third dataset", jobRepository)
.start(dataProviderStep)
.next(new NumberInfoDecider())
.on(NOTIFY)
@ -88,4 +98,39 @@ public class NumberInfoConfig {
.end()
.build();
}
@Bean(name = "jobRepository")
public JobRepository getJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource());
factory.setTransactionManager(getTransactionManager());
// JobRepositoryFactoryBean's methods Throws Generic Exception,
// it would have been better to have a specific one
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean(name = "dataSource")
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql")
.addScript("classpath:org/springframework/batch/core/schema-h2.sql")
.build();
}
@Bean(name = "transactionManager")
public PlatformTransactionManager getTransactionManager() {
return new ResourcelessTransactionManager();
}
@Bean(name = "jobLauncher")
public JobLauncher getJobLauncher() throws Exception {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
// SimpleJobLauncher's methods Throws Generic Exception,
// it would have been better to have a specific one
jobLauncher.setJobRepository(getJobRepository());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}

View File

@ -7,9 +7,8 @@ import org.springframework.batch.repeat.RepeatStatus;
public class NotifierTasklet implements Tasklet {
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
System.err.println("[" + chunkContext.getStepContext()
.getJobName() + "] contains interesting data!!");
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) {
System.err.println("[" + chunkContext.getStepContext().getJobName() + "] contains interesting data!!");
return RepeatStatus.FINISHED;
}
}

View File

@ -29,7 +29,7 @@ public class NumberInfoClassifier extends ItemListenerSupport<NumberInfo, Intege
}
@Override
public Integer process(NumberInfo numberInfo) throws Exception {
return Integer.valueOf(numberInfo.getNumber());
public Integer process(NumberInfo numberInfo) {
return numberInfo.getNumber();
}
}

View File

@ -7,7 +7,7 @@ import org.springframework.batch.item.ItemProcessor;
public class NumberInfoClassifierWithDecider extends ItemListenerSupport<NumberInfo, Integer> implements ItemProcessor<NumberInfo, Integer> {
@Override
public Integer process(NumberInfo numberInfo) throws Exception {
public Integer process(NumberInfo numberInfo) {
return Integer.valueOf(numberInfo.getNumber());
}
}

View File

@ -1,7 +1,6 @@
package org.baeldung.conditionalflow.step;
import java.util.List;
import org.springframework.batch.item.Chunk;
import org.springframework.batch.item.ItemWriter;
public class PrependingStdoutWriter<T> implements ItemWriter<T> {
@ -12,8 +11,8 @@ public class PrependingStdoutWriter<T> implements ItemWriter<T> {
}
@Override
public void write(List<? extends T> list) {
for (T listItem : list) {
public void write(Chunk<? extends T> chunk) {
for (T listItem : chunk) {
System.out.println(prependText + " " + listItem.toString());
}
}

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
</transactionRecord>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
</transactionRecord>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
</transactionRecord>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
</transactionRecord>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31 00:00:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03 00:00:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02 00:00:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
</transactionRecord>

View File

@ -17,7 +17,7 @@
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names"
value="username,userid,transaction_date,transaction_amount" />
value="username,userid,transactiondate,amount" />
</bean>
</property>
<property name="fieldSetMapper">
@ -33,11 +33,11 @@
<bean id="itemWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="resource" value="file:xml/output.xml" />
<property name="marshaller" ref="recordMarshaller" />
<property name="marshaller" ref="marshaller" />
<property name="rootTagName" value="transactionRecord" />
</bean>
<bean id="recordMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.baeldung.batch.model.Transaction</value>

View File

@ -9,8 +9,8 @@
<!-- connect to SQLite database -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.sqlite.JDBC" />
<property name="url" value="jdbc:sqlite:repository.sqlite" />
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:repository.sqlite" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
@ -18,8 +18,8 @@
<!-- create job-meta tables automatically -->
<jdbc:initialize-database data-source="dataSource">
<jdbc:script
location="org/springframework/batch/core/schema-drop-sqlite.sql" />
<jdbc:script location="org/springframework/batch/core/schema-sqlite.sql" />
location="org/springframework/batch/core/schema-drop-h2.sql" />
<jdbc:script location="org/springframework/batch/core/schema-h2.sql" />
</jdbc:initialize-database>
<!-- stored job-meta in memory -->
@ -31,7 +31,6 @@
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseType" value="sqlite" />
</bean>
<bean id="transactionManager"

View File

@ -1,19 +1,16 @@
package com.baeldung.batch;
import com.baeldung.batch.SpringBatchRetryConfig;
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.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
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.test.AssertFile;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
@ -21,15 +18,15 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.core.io.FileSystemResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.batch.test.AssertFile.assertFileEquals;
@RunWith(SpringRunner.class)
@SpringBatchTest
@EnableAutoConfiguration
@ContextConfiguration(classes = { SpringBatchRetryConfig.class })
@ -56,8 +53,8 @@ public class SpringBatchRetryIntegrationTest {
JobInstance actualJobInstance = jobExecution.getJobInstance();
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
assertThat(actualJobInstance.getJobName(), is("retryBatchJob"));
assertThat(actualJobExitStatus.getExitCode(), is("FAILED"));
assertEquals("retryBatchJob", actualJobInstance.getJobName());
assertEquals("FAILED", actualJobExitStatus.getExitCode());
assertThat(actualJobExitStatus.getExitDescription(), containsString("org.apache.http.conn.ConnectTimeoutException"));
}
@ -78,9 +75,9 @@ public class SpringBatchRetryIntegrationTest {
JobInstance actualJobInstance = jobExecution.getJobInstance();
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
assertThat(actualJobInstance.getJobName(), is("retryBatchJob"));
assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED"));
AssertFile.assertFileEquals(expectedResult, actualResult);
assertEquals("retryBatchJob", actualJobInstance.getJobName());
assertEquals("COMPLETED", actualJobExitStatus.getExitCode());
assertFileEquals(expectedResult, actualResult);
}
private JobParameters defaultJobParameters() {

View File

@ -1,14 +1,11 @@
package com.baeldung.batchtesting;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Collection;
import com.baeldung.batchtesting.SpringBatchConfiguration;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
@ -22,20 +19,11 @@ 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";
@ -50,7 +38,7 @@ public class SpringBatchIntegrationTest {
@Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
@After
@AfterEach
public void cleanUp() {
jobRepositoryTestUtils.removeJobExecutions();
}
@ -74,8 +62,8 @@ public class SpringBatchIntegrationTest {
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
// then
assertThat(actualJobInstance.getJobName(), is("transformBooksRecords"));
assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED"));
assertEquals("transformBooksRecords", actualJobInstance.getJobName());
assertEquals("COMPLETED", actualJobExitStatus.getExitCode());
AssertFile.assertFileEquals(expectedResult, actualResult);
}
@ -92,8 +80,8 @@ public class SpringBatchIntegrationTest {
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
// then
assertThat(actualStepExecutions.size(), is(1));
assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED"));
assertEquals(1, actualStepExecutions.size());
assertEquals("COMPLETED", actualJobExitStatus.getExitCode());
AssertFile.assertFileEquals(expectedResult, actualResult);
}
@ -106,10 +94,10 @@ public class SpringBatchIntegrationTest {
ExitStatus actualExitStatus = jobExecution.getExitStatus();
// then
assertThat(actualStepExecutions.size(), is(1));
assertThat(actualExitStatus.getExitCode(), is("COMPLETED"));
assertEquals(1, actualStepExecutions.size());
assertEquals("COMPLETED", actualExitStatus.getExitCode());
actualStepExecutions.forEach(stepExecution -> {
assertThat(stepExecution.getWriteCount(), is(8));
assertEquals(8L, stepExecution.getWriteCount());
});
}

View File

@ -1,22 +1,21 @@
package com.baeldung.batchtesting;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.batch.test.AssertFile.assertFileEquals;
import java.util.Arrays;
import java.util.List;
import com.baeldung.batchtesting.SpringBatchConfiguration;
import com.baeldung.batchtesting.model.Book;
import com.baeldung.batchtesting.model.BookRecord;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.item.Chunk;
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;
@ -24,21 +23,12 @@ 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";
@ -62,7 +52,7 @@ public class SpringBatchStepScopeIntegrationTest {
return paramsBuilder.toJobParameters();
}
@After
@AfterEach
public void cleanUp() {
jobRepositoryTestUtils.removeJobExecutions();
}
@ -80,11 +70,11 @@ public class SpringBatchStepScopeIntegrationTest {
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"));
assertEquals("Foundation", bookRecord.getBookName());
assertEquals("Asimov I.", bookRecord.getBookAuthor());
assertEquals("ISBN 12839", bookRecord.getBookISBN());
assertEquals("hardcover", bookRecord.getBookFormat());
assertEquals("2018", bookRecord.getPublishingYear());
}
itemReader.close();
return null;
@ -106,12 +96,12 @@ public class SpringBatchStepScopeIntegrationTest {
StepScopeTestUtils.doInStepScope(stepExecution, () -> {
jsonItemWriter.open(stepExecution.getExecutionContext());
jsonItemWriter.write(Arrays.asList(demoBook));
jsonItemWriter.write(new Chunk<>(List.of(demoBook)));
jsonItemWriter.close();
return null;
});
// then
AssertFile.assertFileEquals(expectedResult, actualResult);
assertFileEquals(expectedResult, actualResult);
}
}

View File

@ -1,25 +1,29 @@
package com.baeldung.taskletsvschunks.chunks;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.baeldung.taskletsvschunks.config.ChunksConfig;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
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.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ChunksConfig.class)
@SpringBatchTest
@EnableAutoConfiguration
@ContextConfiguration(classes = ChunksConfig.class)
public class ChunksIntegrationTest {
@Autowired private JobLauncherTestUtils jobLauncherTestUtils;
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void givenChunksJob_WhenJobEnds_ThenStatusCompleted() throws Exception {
JobExecution jobExecution = jobLauncherTestUtils.launchJob();
Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}

View File

@ -1,25 +1,29 @@
package com.baeldung.taskletsvschunks.tasklets;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.baeldung.taskletsvschunks.config.TaskletsConfig;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
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.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBatchTest
@EnableAutoConfiguration
@ContextConfiguration(classes = TaskletsConfig.class)
public class TaskletsIntegrationTest {
@Autowired private JobLauncherTestUtils jobLauncherTestUtils;
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void givenTaskletsJob_WhenJobEnds_ThenStatusCompleted() throws Exception {
JobExecution jobExecution = jobLauncherTestUtils.launchJob();
Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}

View File

@ -1,8 +1,10 @@
package org.baeldung.conditionalflow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.baeldung.conditionalflow.config.NumberInfoConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
@ -10,26 +12,16 @@ 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.test.annotation.DirtiesContext;
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 java.util.Collection;
import java.util.Iterator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RunWith(SpringRunner.class)
@SpringBatchTest
@EnableAutoConfiguration
@ContextConfiguration(classes = { NumberInfoConfig.class })
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class DeciderJobIntegrationTest {
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@ -39,8 +31,7 @@ public class DeciderJobIntegrationTest {
Collection<StepExecution> actualStepExecutions = jobExecution.getStepExecutions();
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
assertEquals("COMPLETED", actualJobExitStatus.getExitCode()
.toString());
assertEquals("COMPLETED", actualJobExitStatus.getExitCode());
assertEquals(2, actualStepExecutions.size());
boolean notifyStepDidRun = false;
Iterator<StepExecution> iterator = actualStepExecutions.iterator();

View File

@ -5,10 +5,10 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@RunWith(SpringJUnit4ClassRunner.class)
@ExtendWith(SpringExtension.class)
class NumberInfoUnitTest {
@Test

View File

@ -1,3 +1,10 @@
[
{"author":"Grisham J.","name":"The Firm"}
{"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"}
]