Skip to content

Commit

Permalink
Add java configuration for the fixed length file import sample
Browse files Browse the repository at this point in the history
Issue #3663
  • Loading branch information
fmbenhassine committed Sep 26, 2023
1 parent 2750238 commit 43e7c8c
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 85 deletions.
39 changes: 3 additions & 36 deletions spring-batch-samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,43 +171,10 @@ from a delimited file, processing it and writing it to another file.

### Fixed Length Import Job

The goal is to demonstrate a typical scenario of importing data
from a fixed-length file to database

This job shows a typical scenario, when reading input data and
processing the data is cleanly separated. The data provider is
responsible for reading input and mapping each record to a domain
object, which is then passed to the module processor. The module
processor handles the processing of the domain objects, in this case
it only writes them to database.

In this example we are using a simple fixed length record structure
that can be found in the project at
`data/iosample/input`. A considerable amount of
thought can go into designing the folder structures for batch file
management. The fixed length records look like this:

UK21341EAH4597898.34customer1
UK21341EAH4611218.12customer2
UK21341EAH4724512.78customer2
UK21341EAH48108109.25customer3
UK21341EAH49854123.39customer4

Looking back to the configuration file you will see where this is
documented in the property of the `FixedLengthTokenizer`. You can
infer the following properties:


FieldName | Length
--------- | :----:
ISIN | 12
Quantity | 3
Price | 5
Customer | 9

*Output target:* database - writes the data to database using a DAO
object
The goal is to demonstrate a typical scenario of reading data
from a fixed length file, processing it and writing it to another file.

[Fixed Length Import Job sample](./src/main/java/org/springframework/batch/sample/file/fixed/README.md)

### Football Job

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.springframework.batch.sample.file.fixed;

import javax.sql.DataSource;

import org.springframework.batch.core.Job;
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.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;
import org.springframework.batch.item.file.transform.Range;
import org.springframework.batch.sample.domain.trade.CustomerCredit;
import org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor;
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.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.jdbc.support.JdbcTransactionManager;

@Configuration
@EnableBatchProcessing
public class FixedLengthJobConfiguration {

@Bean
@StepScope
public FlatFileItemReader<CustomerCredit> itemReader(@Value("#{jobParameters[inputFile]}") Resource resource) {
return new FlatFileItemReaderBuilder<CustomerCredit>().name("itemReader")
.resource(resource)
.fixedLength()
.columns(new Range(1, 9), new Range(10, 11))
.names("name", "credit")
.targetType(CustomerCredit.class)
.build();
}

@Bean
@StepScope
public FlatFileItemWriter<CustomerCredit> itemWriter(
@Value("#{jobParameters[outputFile]}") WritableResource resource) {
return new FlatFileItemWriterBuilder<CustomerCredit>().name("itemWriter")
.resource(resource)
.formatted()
.format("%-9s%-2.0f")
.names("name", "credit")
.build();
}

@Bean
public Job job(JobRepository jobRepository, JdbcTransactionManager transactionManager,
ItemReader<CustomerCredit> itemReader, ItemWriter<CustomerCredit> itemWriter) {
return new JobBuilder("ioSampleJob", jobRepository)
.start(new StepBuilder("step1", jobRepository).<CustomerCredit, CustomerCredit>chunk(2, transactionManager)
.reader(itemReader)
.processor(new CustomerCreditIncreaseProcessor())
.writer(itemWriter)
.build())
.build();
}

// Infrastructure beans

@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
.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,41 @@
### Fixed Length File Import Job

## About

The goal is to demonstrate a typical scenario of reading data
from a fixed length file, processing it and writing it to another file.

In this example we are using a simple fixed length record structure
that can be found in the project at
`src/main/resources/org/springframework/batch/sample/file/fixed/data`.
The fixed length records look like this:

```
customer110
customer220
customer330
customer440
customer550
customer660
```

Looking back to the configuration of the reader you will this is
configured in the fixed column ranges:

FieldName | Range
--------- | :----:
name | 1,9
credit | 10,11

## Run the sample

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

```
$>cd spring-batch-samples
# Launch the sample using the XML configuration
$>../mvnw -Dtest=FixedLengthFunctionalTests#testLaunchJobWithXmlConfig test
# Launch the sample using the Java configuration
$>../mvnw -Dtest=FixedLengthFunctionalTests#testLaunchJobWithJavaConfig test
```

Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="
http://www.springframework.org/schema/batch https://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

<batch:job id="ioSampleJob" xmlns="http://www.springframework.org/schema/batch">
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter"
commit-interval="2"/>
</batch:tasklet>
</batch:step>
</batch:job>

<bean id="itemProcessor" class="org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor" />

<bean id="itemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="resource" value="#{jobParameters[inputFile]}" />
<property name="lineMapper">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2006-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.fixed;

import org.junit.jupiter.api.Test;

import org.springframework.batch.core.BatchStatus;
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.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

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

@SpringJUnitConfig(locations = { "/org/springframework/batch/sample/file/fixed/job/fixedLength.xml",
"/simple-job-launcher-context.xml", "/job-runner-context.xml" })
class FixedLengthFunctionalTests {

@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;

@Test
void testLaunchJobWithXmlConfig() throws Exception {
// given
JobParameters jobParameters = new JobParametersBuilder()
.addString("inputFile", "org/springframework/batch/sample/file/fixed/data/fixedLength.txt")
.addString("outputFile", "file:./target/test-outputs/fixedLengthOutput.txt")
.toJobParameters();

// when
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);

// then
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
}

@Test
public void testLaunchJobWithJavaConfig() throws Exception {
// given
ApplicationContext context = new AnnotationConfigApplicationContext(FixedLengthJobConfiguration.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
JobParameters jobParameters = new JobParametersBuilder()
.addString("inputFile", "org/springframework/batch/sample/file/fixed/data/fixedLength.txt")
.addString("outputFile", "file:./target/test-outputs/fixedLengthOutput.txt")
.toJobParameters();

// when
JobExecution jobExecution = jobLauncher.run(job, jobParameters);

// then
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
}

}

This file was deleted.

0 comments on commit 43e7c8c

Please sign in to comment.