Skip to content

Commit

Permalink
Refactor the JSON job sample
Browse files Browse the repository at this point in the history
Issue #3663
  • Loading branch information
fmbenhassine committed Oct 3, 2023
1 parent 11e6532 commit 327faa8
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 140 deletions.
14 changes: 14 additions & 0 deletions spring-batch-samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,20 @@ streaming and Spring OXM marshallers and unmarshallers.

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

### JSON Input Output

The goal of this sample is to show how to read and write JSON files:

```json
[
{"isin":"123","quantity":5,"price":10.5,"customer":"foo","id":1,"version":0},
{"isin":"456","quantity":10,"price":20.5,"customer":"bar","id":2,"version":0},
{"isin":"789","quantity":15,"price":30.5,"customer":"baz","id":3,"version":0}
]
```

[JSON Input Output](./src/main/java/org/springframework/batch/sample/file/json/README.md)

### MultiResource Input Output Job

This sample shows how to use the `MultiResourceItemReader` and `MultiResourceItemWriter`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright 2018-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.file.json;

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.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.json.GsonJsonObjectReader;
import org.springframework.batch.item.json.JacksonJsonObjectMarshaller;
import org.springframework.batch.item.json.JsonFileItemWriter;
import org.springframework.batch.item.json.JsonItemReader;
import org.springframework.batch.item.json.builder.JsonFileItemWriterBuilder;
import org.springframework.batch.item.json.builder.JsonItemReaderBuilder;
import org.springframework.batch.sample.domain.trade.Trade;
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.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.support.JdbcTransactionManager;

/**
* @author Mahmoud Ben Hassine
*/
@Configuration
@EnableBatchProcessing
public class JsonJobConfiguration {

@Bean
@StepScope
public JsonItemReader<Trade> itemReader(@Value("#{jobParameters[inputFile]}") Resource resource) {
return new JsonItemReaderBuilder<Trade>().name("tradesJsonItemReader")
.resource(resource)
.jsonObjectReader(new GsonJsonObjectReader<>(Trade.class))
.build();
}

@Bean
@StepScope
public JsonFileItemWriter<Trade> itemWriter(@Value("#{jobParameters[outputFile]}") WritableResource resource) {
return new JsonFileItemWriterBuilder<Trade>().resource(resource)
.lineSeparator("\n")
.jsonObjectMarshaller(new JacksonJsonObjectMarshaller<>())
.name("tradesJsonFileItemWriter")
.shouldDeleteIfExists(true)
.build();
}

@Bean
public Step step(JobRepository jobRepository, JdbcTransactionManager transactionManager,
JsonItemReader<Trade> itemReader, JsonFileItemWriter<Trade> itemWriter) {
return new StepBuilder("step", jobRepository).<Trade, Trade>chunk(2, transactionManager)
.reader(itemReader)
.writer(itemWriter)
.build();
}

@Bean
public Job job(JobRepository jobRepository, Step step) {
return new JobBuilder("job", jobRepository).start(step).build();
}

// Infrastructure beans

@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql")
.addScript("/org/springframework/batch/core/schema-hsqldb.sql")
.generateUniqueName(true)
.build();
}

@Bean
public JdbcTransactionManager transactionManager(DataSource dataSource) {
return new JdbcTransactionManager(dataSource);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### Json Input Output Job

## About

The goal of this sample is to show how to read and write JSON files:

```json
[
{"isin":"123","quantity":5,"price":10.5,"customer":"foo","id":1,"version":0},
{"isin":"456","quantity":10,"price":20.5,"customer":"bar","id":2,"version":0},
{"isin":"789","quantity":15,"price":30.5,"customer":"baz","id":3,"version":0}
]
```

## Run the sample

You can run the sample from the command line as following:

```
$>cd spring-batch-samples
$>../mvnw -Dtest=JsonFunctionalTests#testJsonReadingAndWriting test
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2018-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.batch.sample.file.json;

import java.io.File;
import java.io.FileInputStream;

import org.junit.jupiter.api.Test;

import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.util.DigestUtils;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* @author Mahmoud Ben Hassine
* @author Glenn Renfro
*/
class JsonFunctionalTests {

public static final String INPUT_FILE = "org/springframework/batch/sample/file/json/data/trades.json";

public static final String OUTPUT_FILE = "target/test-outputs/trades.json";

@Test
void testJsonReadingAndWriting() throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(JsonJobConfiguration.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
JobParameters jobParameters = new JobParametersBuilder().addString("inputFile", INPUT_FILE)
.addString("outputFile", "file:./" + OUTPUT_FILE)
.toJobParameters();
JobExecution jobExecution = jobLauncher.run(job, jobParameters);

assertEquals(ExitStatus.COMPLETED.getExitCode(), jobExecution.getExitStatus().getExitCode());
assertFileEquals(new File("src/main/resources/" + INPUT_FILE), new File(OUTPUT_FILE));
}

private void assertFileEquals(File expected, File actual) throws Exception {
String expectedHash = DigestUtils.md5DigestAsHex(new FileInputStream(expected));
String actualHash = DigestUtils.md5DigestAsHex(new FileInputStream(actual));
assertEquals(expectedHash, actualHash);
}

}

This file was deleted.

0 comments on commit 327faa8

Please sign in to comment.