Skip to content

Commit fdd5566

Browse files
committed
Spring batch
A sample application with spring-batch is implemented
1 parent 61430a9 commit fdd5566

File tree

11 files changed

+382
-0
lines changed

11 files changed

+382
-0
lines changed

spring-batch/output.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Person(name=JILL, surname=DOE)Person(name=JOE, surname=DOE)Person(name=JUSTIN, surname=DOE)Person(name=JANE, surname=DOE)Person(name=JOHN, surname=DOE)

spring-batch/pom.xml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.fd</groupId>
8+
<parent>
9+
<groupId>org.springframework.boot</groupId>
10+
<artifactId>spring-boot-starter-parent</artifactId>
11+
<version>2.0.6.RELEASE</version>
12+
</parent>
13+
<artifactId>spring-batch</artifactId>
14+
<version>1.0-SNAPSHOT</version>
15+
16+
<properties>
17+
<java.version>1.8</java.version>
18+
<maven.compiler.source>${java.version}</maven.compiler.source>
19+
<maven.compiler.target>${java.version}</maven.compiler.target>
20+
21+
<mapstruct.version>1.2.0.Final</mapstruct.version>
22+
<hamcrest-version>1.3</hamcrest-version>
23+
<lombok-version>1.18.2</lombok-version>
24+
</properties>
25+
26+
<developers>
27+
<developer>
28+
<id>fdanismaz</id>
29+
<name>Furkan Danismaz</name>
30+
<email>danismaz.frkan@gmail.com</email>
31+
<url>http://github.com/fdanismaz</url>
32+
<organization>Solidground</organization>
33+
<roles>
34+
<role>architect</role>
35+
<role>developer</role>
36+
</roles>
37+
</developer>
38+
</developers>
39+
40+
<dependencies>
41+
<dependency>
42+
<groupId>org.springframework.boot</groupId>
43+
<artifactId>spring-boot-starter-web</artifactId>
44+
<exclusions>
45+
<exclusion>
46+
<groupId>ch.qos.logback</groupId>
47+
<artifactId>logback-classic</artifactId>
48+
</exclusion>
49+
50+
<exclusion>
51+
<groupId>org.apache.logging.log4j</groupId>
52+
<artifactId>log4j-to-slf4j</artifactId>
53+
</exclusion>
54+
</exclusions>
55+
</dependency>
56+
57+
<dependency>
58+
<groupId>org.projectlombok</groupId>
59+
<artifactId>lombok</artifactId>
60+
<version>${lombok-version}</version>
61+
</dependency>
62+
63+
<dependency>
64+
<groupId>org.springframework.boot</groupId>
65+
<artifactId>spring-boot-starter-batch</artifactId>
66+
<exclusions>
67+
<exclusion>
68+
<groupId>org.springframework</groupId>
69+
<artifactId>spring-jdbc</artifactId>
70+
</exclusion>
71+
</exclusions>
72+
</dependency>
73+
74+
<dependency>
75+
<groupId>org.hamcrest</groupId>
76+
<artifactId>hamcrest-all</artifactId>
77+
<version>${hamcrest-version}</version>
78+
<scope>test</scope>
79+
</dependency>
80+
81+
<dependency>
82+
<groupId>org.apache.logging.log4j</groupId>
83+
<artifactId>log4j-core</artifactId>
84+
</dependency>
85+
86+
<dependency>
87+
<groupId>org.apache.logging.log4j</groupId>
88+
<artifactId>log4j-slf4j-impl</artifactId>
89+
</dependency>
90+
</dependencies>
91+
92+
93+
</project>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.fd.tryout.springbatch;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.SpringBootApplication;
6+
7+
/**
8+
* @author furkand
9+
* 10/26/2018 5:51 PM
10+
*/
11+
@Slf4j
12+
@SpringBootApplication
13+
public class App {
14+
15+
public static void main(String[] args) {
16+
SpringApplication.run(App.class);
17+
log.info("Application started...");
18+
}
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.fd.tryout.springbatch.batch;
2+
3+
import com.fd.tryout.springbatch.model.Person;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.batch.item.ItemProcessor;
6+
7+
/**
8+
* @author furkand
9+
* 10/26/2018 6:04 PM
10+
*/
11+
@Slf4j
12+
public class PersonProcessor implements ItemProcessor<Person, Person> {
13+
14+
@Override
15+
public Person process(Person person) throws Exception {
16+
log.info("Converting person: " + person.toString());
17+
return Person.builder()
18+
.name(person.getName().toUpperCase())
19+
.surname(person.getSurname().toUpperCase()).build();
20+
}
21+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.fd.tryout.springbatch.batch;
2+
3+
import com.fd.tryout.springbatch.model.Person;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.batch.item.ExecutionContext;
6+
import org.springframework.batch.item.ItemStreamException;
7+
import org.springframework.batch.item.ItemStreamWriter;
8+
9+
import java.io.File;
10+
import java.io.FileOutputStream;
11+
import java.io.IOException;
12+
import java.io.OutputStream;
13+
import java.util.List;
14+
15+
/**
16+
* @author furkand
17+
* 10/26/2018 6:09 PM
18+
*/
19+
@Slf4j
20+
public class PersonStreamWriter implements ItemStreamWriter<Person> {
21+
22+
OutputStream outputStream;
23+
24+
@Override
25+
public void open(ExecutionContext executionContext) throws ItemStreamException {
26+
try {
27+
File file = new File(System.getProperty("user.dir") + "/output.txt");
28+
if (!file.exists()) {
29+
file.createNewFile();
30+
}
31+
32+
this.outputStream = new FileOutputStream(file);
33+
} catch (Exception e) {
34+
throw new ItemStreamException(e.getMessage(), e);
35+
}
36+
}
37+
38+
@Override
39+
public void update(ExecutionContext executionContext) throws ItemStreamException {
40+
// N/A
41+
}
42+
43+
@Override
44+
public void close() throws ItemStreamException {
45+
if (this.outputStream != null) {
46+
try {
47+
this.outputStream.close();
48+
} catch (IOException e) {
49+
log.error("Cannot close stream");
50+
}
51+
}
52+
}
53+
54+
@Override
55+
public void write(List<? extends Person> list) throws Exception {
56+
list.stream().forEach(x -> {
57+
try {
58+
this.outputStream.write(((Person) x).toString().getBytes());
59+
} catch (IOException e) {
60+
log.error("Cannot write person");
61+
}
62+
});
63+
}
64+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.fd.tryout.springbatch.batch;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.springframework.batch.core.BatchStatus;
5+
import org.springframework.batch.core.JobExecution;
6+
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
7+
8+
/**
9+
* @author furkand
10+
* 10/26/2018 6:40 PM
11+
*/
12+
@Slf4j
13+
public class ToUpperCaseJobExecutionListener extends JobExecutionListenerSupport {
14+
15+
@Override
16+
public void afterJob(JobExecution jobExecution) {
17+
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
18+
log.info("JOB COMPLETED !!! Go ahead and check the results");
19+
}
20+
}
21+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.fd.tryout.springbatch.config;
2+
3+
import com.fd.tryout.springbatch.batch.PersonProcessor;
4+
import com.fd.tryout.springbatch.batch.PersonStreamWriter;
5+
import com.fd.tryout.springbatch.batch.ToUpperCaseJobExecutionListener;
6+
import com.fd.tryout.springbatch.model.Person;
7+
import org.springframework.batch.core.Job;
8+
import org.springframework.batch.core.Step;
9+
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
10+
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
11+
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
12+
import org.springframework.batch.item.ItemStreamWriter;
13+
import org.springframework.batch.item.file.FlatFileItemReader;
14+
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
15+
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
16+
import org.springframework.beans.factory.annotation.Autowired;
17+
import org.springframework.context.annotation.Bean;
18+
import org.springframework.context.annotation.Configuration;
19+
import org.springframework.core.io.ClassPathResource;
20+
21+
/**
22+
* @author furkand
23+
* 10/26/2018 5:57 PM
24+
*/
25+
@Configuration
26+
@EnableBatchProcessing
27+
public class Config {
28+
29+
@Autowired
30+
public JobBuilderFactory jobBuilderFactory;
31+
32+
@Autowired
33+
public StepBuilderFactory stepBuilderFactory;
34+
35+
@Autowired
36+
private Step toUpperCaseConverter;
37+
38+
@Bean
39+
public FlatFileItemReader<Person> reader() {
40+
return new FlatFileItemReaderBuilder<Person>()
41+
.name("personReader")
42+
.resource(new ClassPathResource("data.csv"))
43+
.delimited()
44+
.names(new String[]{"name", "surname"})
45+
.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
46+
setTargetType(Person.class);
47+
}})
48+
.build();
49+
}
50+
51+
@Bean
52+
public PersonProcessor processor() {
53+
return new PersonProcessor();
54+
}
55+
56+
@Bean
57+
public PersonStreamWriter writer() {
58+
return new PersonStreamWriter();
59+
}
60+
61+
@Bean
62+
public ToUpperCaseJobExecutionListener listener() {
63+
return new ToUpperCaseJobExecutionListener();
64+
}
65+
66+
@Bean("toUpperCaseJob")
67+
public Job convertToUpperCaseJob(ToUpperCaseJobExecutionListener listener) {
68+
return this.jobBuilderFactory.get("toUpperCaseJob")
69+
.listener(listener)
70+
.flow(this.toUpperCaseConverter)
71+
.end()
72+
.build();
73+
}
74+
75+
@Bean
76+
public Step toUpperCaseConverter(PersonStreamWriter writer) {
77+
return this.stepBuilderFactory.get("toUpperCase")
78+
.<Person, Person>chunk(10)
79+
.reader(this.reader())
80+
.processor(this.processor())
81+
.writer(this.writer())
82+
.build();
83+
}
84+
85+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.fd.tryout.springbatch.controller;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.springframework.batch.core.Job;
5+
import org.springframework.batch.core.JobParameter;
6+
import org.springframework.batch.core.JobParameters;
7+
import org.springframework.batch.core.JobParametersBuilder;
8+
import org.springframework.batch.core.launch.JobLauncher;
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.beans.factory.annotation.Qualifier;
11+
import org.springframework.web.bind.annotation.GetMapping;
12+
import org.springframework.web.bind.annotation.RequestMapping;
13+
import org.springframework.web.bind.annotation.RestController;
14+
15+
/**
16+
* @author furkand
17+
* 10/26/2018 6:51 PM
18+
*/
19+
@Slf4j
20+
@RestController
21+
@RequestMapping("/job")
22+
public class JobLauncherController {
23+
24+
@Autowired
25+
JobLauncher jobLauncher;
26+
27+
@Autowired
28+
@Qualifier("toUpperCaseJob")
29+
Job toUpperCaseJob;
30+
31+
@GetMapping("/run")
32+
public String runJob() {
33+
try {
34+
log.info("Starting job...");
35+
JobParameters jobParameters = new JobParametersBuilder()
36+
.addLong("time", System.currentTimeMillis())
37+
.toJobParameters();
38+
this.jobLauncher.run(this.toUpperCaseJob, jobParameters);
39+
}
40+
catch (Exception e) {
41+
log.error(e.getMessage());
42+
}
43+
44+
return "DONE!";
45+
}
46+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.fd.tryout.springbatch.model;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
/**
9+
* @author furkand
10+
* 10/26/2018 6:03 PM
11+
*/
12+
@Data
13+
@Builder
14+
@AllArgsConstructor
15+
@NoArgsConstructor
16+
public class Person {
17+
18+
private String name;
19+
private String surname;
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
logging:
2+
level:
3+
ROOT: INFO
4+
org.springframework: ERROR
5+
com.fd: TRACE
6+
pattern:
7+
console: "%-5level %d{yyyy-MM-dd HH:mm:ss} - %msg%n"

0 commit comments

Comments
 (0)