Skip to content

Commit 327faa8

Browse files
committed
Refactor the JSON job sample
Issue #3663
1 parent 11e6532 commit 327faa8

File tree

5 files changed

+201
-140
lines changed

5 files changed

+201
-140
lines changed

spring-batch-samples/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,20 @@ streaming and Spring OXM marshallers and unmarshallers.
183183

184184
[XML Input Output](./src/main/java/org/springframework/batch/sample/file/xml/README.md)
185185

186+
### JSON Input Output
187+
188+
The goal of this sample is to show how to read and write JSON files:
189+
190+
```json
191+
[
192+
{"isin":"123","quantity":5,"price":10.5,"customer":"foo","id":1,"version":0},
193+
{"isin":"456","quantity":10,"price":20.5,"customer":"bar","id":2,"version":0},
194+
{"isin":"789","quantity":15,"price":30.5,"customer":"baz","id":3,"version":0}
195+
]
196+
```
197+
198+
[JSON Input Output](./src/main/java/org/springframework/batch/sample/file/json/README.md)
199+
186200
### MultiResource Input Output Job
187201

188202
This sample shows how to use the `MultiResourceItemReader` and `MultiResourceItemWriter`
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2018-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.sample.file.json;
17+
18+
import javax.sql.DataSource;
19+
20+
import org.springframework.batch.core.Job;
21+
import org.springframework.batch.core.Step;
22+
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
23+
import org.springframework.batch.core.configuration.annotation.StepScope;
24+
import org.springframework.batch.core.job.builder.JobBuilder;
25+
import org.springframework.batch.core.repository.JobRepository;
26+
import org.springframework.batch.core.step.builder.StepBuilder;
27+
import org.springframework.batch.item.json.GsonJsonObjectReader;
28+
import org.springframework.batch.item.json.JacksonJsonObjectMarshaller;
29+
import org.springframework.batch.item.json.JsonFileItemWriter;
30+
import org.springframework.batch.item.json.JsonItemReader;
31+
import org.springframework.batch.item.json.builder.JsonFileItemWriterBuilder;
32+
import org.springframework.batch.item.json.builder.JsonItemReaderBuilder;
33+
import org.springframework.batch.sample.domain.trade.Trade;
34+
import org.springframework.beans.factory.annotation.Value;
35+
import org.springframework.context.annotation.Bean;
36+
import org.springframework.context.annotation.Configuration;
37+
import org.springframework.core.io.Resource;
38+
import org.springframework.core.io.WritableResource;
39+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
40+
import org.springframework.jdbc.support.JdbcTransactionManager;
41+
42+
/**
43+
* @author Mahmoud Ben Hassine
44+
*/
45+
@Configuration
46+
@EnableBatchProcessing
47+
public class JsonJobConfiguration {
48+
49+
@Bean
50+
@StepScope
51+
public JsonItemReader<Trade> itemReader(@Value("#{jobParameters[inputFile]}") Resource resource) {
52+
return new JsonItemReaderBuilder<Trade>().name("tradesJsonItemReader")
53+
.resource(resource)
54+
.jsonObjectReader(new GsonJsonObjectReader<>(Trade.class))
55+
.build();
56+
}
57+
58+
@Bean
59+
@StepScope
60+
public JsonFileItemWriter<Trade> itemWriter(@Value("#{jobParameters[outputFile]}") WritableResource resource) {
61+
return new JsonFileItemWriterBuilder<Trade>().resource(resource)
62+
.lineSeparator("\n")
63+
.jsonObjectMarshaller(new JacksonJsonObjectMarshaller<>())
64+
.name("tradesJsonFileItemWriter")
65+
.shouldDeleteIfExists(true)
66+
.build();
67+
}
68+
69+
@Bean
70+
public Step step(JobRepository jobRepository, JdbcTransactionManager transactionManager,
71+
JsonItemReader<Trade> itemReader, JsonFileItemWriter<Trade> itemWriter) {
72+
return new StepBuilder("step", jobRepository).<Trade, Trade>chunk(2, transactionManager)
73+
.reader(itemReader)
74+
.writer(itemWriter)
75+
.build();
76+
}
77+
78+
@Bean
79+
public Job job(JobRepository jobRepository, Step step) {
80+
return new JobBuilder("job", jobRepository).start(step).build();
81+
}
82+
83+
// Infrastructure beans
84+
85+
@Bean
86+
public DataSource dataSource() {
87+
return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql")
88+
.addScript("/org/springframework/batch/core/schema-hsqldb.sql")
89+
.generateUniqueName(true)
90+
.build();
91+
}
92+
93+
@Bean
94+
public JdbcTransactionManager transactionManager(DataSource dataSource) {
95+
return new JdbcTransactionManager(dataSource);
96+
}
97+
98+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
### Json Input Output Job
2+
3+
## About
4+
5+
The goal of this sample is to show how to read and write JSON files:
6+
7+
```json
8+
[
9+
{"isin":"123","quantity":5,"price":10.5,"customer":"foo","id":1,"version":0},
10+
{"isin":"456","quantity":10,"price":20.5,"customer":"bar","id":2,"version":0},
11+
{"isin":"789","quantity":15,"price":30.5,"customer":"baz","id":3,"version":0}
12+
]
13+
```
14+
15+
## Run the sample
16+
17+
You can run the sample from the command line as following:
18+
19+
```
20+
$>cd spring-batch-samples
21+
$>../mvnw -Dtest=JsonFunctionalTests#testJsonReadingAndWriting test
22+
```
23+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2018-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.batch.sample.file.json;
18+
19+
import java.io.File;
20+
import java.io.FileInputStream;
21+
22+
import org.junit.jupiter.api.Test;
23+
24+
import org.springframework.batch.core.ExitStatus;
25+
import org.springframework.batch.core.Job;
26+
import org.springframework.batch.core.JobExecution;
27+
import org.springframework.batch.core.JobParameters;
28+
import org.springframework.batch.core.JobParametersBuilder;
29+
import org.springframework.batch.core.launch.JobLauncher;
30+
import org.springframework.context.ApplicationContext;
31+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
32+
import org.springframework.util.DigestUtils;
33+
34+
import static org.junit.jupiter.api.Assertions.assertEquals;
35+
36+
/**
37+
* @author Mahmoud Ben Hassine
38+
* @author Glenn Renfro
39+
*/
40+
class JsonFunctionalTests {
41+
42+
public static final String INPUT_FILE = "org/springframework/batch/sample/file/json/data/trades.json";
43+
44+
public static final String OUTPUT_FILE = "target/test-outputs/trades.json";
45+
46+
@Test
47+
void testJsonReadingAndWriting() throws Exception {
48+
ApplicationContext context = new AnnotationConfigApplicationContext(JsonJobConfiguration.class);
49+
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
50+
Job job = context.getBean(Job.class);
51+
JobParameters jobParameters = new JobParametersBuilder().addString("inputFile", INPUT_FILE)
52+
.addString("outputFile", "file:./" + OUTPUT_FILE)
53+
.toJobParameters();
54+
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
55+
56+
assertEquals(ExitStatus.COMPLETED.getExitCode(), jobExecution.getExitStatus().getExitCode());
57+
assertFileEquals(new File("src/main/resources/" + INPUT_FILE), new File(OUTPUT_FILE));
58+
}
59+
60+
private void assertFileEquals(File expected, File actual) throws Exception {
61+
String expectedHash = DigestUtils.md5DigestAsHex(new FileInputStream(expected));
62+
String actualHash = DigestUtils.md5DigestAsHex(new FileInputStream(actual));
63+
assertEquals(expectedHash, actualHash);
64+
}
65+
66+
}

spring-batch-samples/src/test/java/org/springframework/batch/sample/file/json/JsonSupportIntegrationTests.java

Lines changed: 0 additions & 140 deletions
This file was deleted.

0 commit comments

Comments
 (0)