Add sample job based on PetClinic application
Signed-off-by: Mahmoud Ben Hassine <mbenhassine@vmware.com>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 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.samples.petclinic;
|
||||
|
||||
public record Owner(int id, String firstname, String lastname, String address, String city, String telephone) {
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2025 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.samples.petclinic;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
|
||||
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.database.JdbcCursorItemReader;
|
||||
import org.springframework.batch.item.database.builder.JdbcCursorItemReaderBuilder;
|
||||
import org.springframework.batch.item.file.FlatFileItemWriter;
|
||||
import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;
|
||||
import org.springframework.batch.samples.common.DataSourceConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.jdbc.core.DataClassRowMapper;
|
||||
import org.springframework.jdbc.support.JdbcTransactionManager;
|
||||
|
||||
@Configuration
|
||||
@EnableBatchProcessing
|
||||
@Import(DataSourceConfiguration.class)
|
||||
public class OwnersExportJobConfiguration {
|
||||
|
||||
@Bean
|
||||
public JdbcCursorItemReader<Owner> ownersReader(DataSource dataSource) {
|
||||
return new JdbcCursorItemReaderBuilder<Owner>().name("ownersReader")
|
||||
.sql("SELECT * FROM OWNERS")
|
||||
.dataSource(dataSource)
|
||||
.rowMapper(new DataClassRowMapper<>(Owner.class))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlatFileItemWriter<Owner> ownersWriter() {
|
||||
return new FlatFileItemWriterBuilder<Owner>().name("ownersWriter")
|
||||
.resource(new FileSystemResource("owners.csv"))
|
||||
.delimited()
|
||||
.names("id", "firstname", "lastname", "address", "city", "telephone")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Job job(JobRepository jobRepository, JdbcTransactionManager transactionManager,
|
||||
JdbcCursorItemReader<Owner> ownersReader, FlatFileItemWriter<Owner> ownersWriter) {
|
||||
return new JobBuilder("ownersExportJob", jobRepository)
|
||||
.start(new StepBuilder("ownersExportStep", jobRepository).<Owner, Owner>chunk(5, transactionManager)
|
||||
.reader(ownersReader)
|
||||
.writer(ownersWriter)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# PetClinic Job
|
||||
|
||||
## About the sample
|
||||
|
||||
This sample uses the [PetClinic Spring application](https://github.com/spring-projects/spring-petclinic) to show how to use
|
||||
Spring Batch to export data from a relational database table to a flat file.
|
||||
|
||||
The job in this sample is a single-step job that exports data from the `owners` table
|
||||
to a flat file named `owners.csv`.
|
||||
|
||||
## 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=PetClinicJobFunctionalTests#testLaunchJobWithXmlConfiguration test
|
||||
# Launch the sample using the Java configuration
|
||||
$>../mvnw -Dtest=PetClinicJobFunctionalTests#testLaunchJobWithJavaConfiguration test
|
||||
```
|
||||
@@ -100,3 +100,26 @@ CREATE TABLE ERROR_LOG (
|
||||
STEP_NAME CHAR(20) ,
|
||||
MESSAGE VARCHAR(300) NOT NULL
|
||||
) ;
|
||||
|
||||
-- PetClinic sample tables
|
||||
|
||||
CREATE TABLE OWNERS (
|
||||
ID INTEGER IDENTITY PRIMARY KEY,
|
||||
FIRSTNAME VARCHAR(30),
|
||||
LASTNAME VARCHAR(30),
|
||||
ADDRESS VARCHAR(255),
|
||||
CITY VARCHAR(80),
|
||||
TELEPHONE VARCHAR(20)
|
||||
);
|
||||
|
||||
INSERT INTO OWNERS VALUES (1, 'George', 'Franklin', '110 W. Liberty St.', 'Madison', '6085551023');
|
||||
INSERT INTO OWNERS VALUES (2, 'Betty', 'Davis', '638 Cardinal Ave.', 'Sun Prairie', '6085551749');
|
||||
INSERT INTO OWNERS VALUES (3, 'Eduardo', 'Rodriquez', '2693 Commerce St.', 'McFarland', '6085558763');
|
||||
INSERT INTO OWNERS VALUES (4, 'Harold', 'Davis', '563 Friendly St.', 'Windsor', '6085553198');
|
||||
INSERT INTO OWNERS VALUES (5, 'Peter', 'McTavish', '2387 S. Fair Way', 'Madison', '6085552765');
|
||||
INSERT INTO OWNERS VALUES (6, 'Jean', 'Coleman', '105 N. Lake St.', 'Monona', '6085552654');
|
||||
INSERT INTO OWNERS VALUES (7, 'Jeff', 'Black', '1450 Oak Blvd.', 'Monona', '6085555387');
|
||||
INSERT INTO OWNERS VALUES (8, 'Maria', 'Escobito', '345 Maple St.', 'Madison', '6085557683');
|
||||
INSERT INTO OWNERS VALUES (9, 'David', 'Schroeder', '2749 Blackhawk Trail', 'Madison', '6085559435');
|
||||
INSERT INTO OWNERS VALUES (10, 'Carlos', 'Estaban', '2335 Independence La.', 'Waunakee', '6085555487');
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
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="ownersExportJob" xmlns="http://www.springframework.org/schema/batch">
|
||||
<batch:step id="ownersExportStep">
|
||||
<batch:tasklet>
|
||||
<batch:chunk reader="ownersReader" writer="ownersWriter" commit-interval="5"/>
|
||||
</batch:tasklet>
|
||||
</batch:step>
|
||||
</batch:job>
|
||||
|
||||
<bean id="ownersReader" class="org.springframework.batch.item.database.JdbcCursorItemReader">
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
<property name="sql" value="select * from owners"/>
|
||||
<property name="rowMapper">
|
||||
<bean class="org.springframework.jdbc.core.DataClassRowMapper">
|
||||
<constructor-arg value="org.springframework.batch.samples.petclinic.Owner"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="ownersWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
|
||||
<property name="resource" value="file:owners.csv" />
|
||||
<property name="lineAggregator">
|
||||
<bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
|
||||
<property name="delimiter" value=","/>
|
||||
<property name="fieldExtractor">
|
||||
<bean class="org.springframework.batch.item.file.transform.RecordFieldExtractor">
|
||||
<constructor-arg value="org.springframework.batch.samples.petclinic.Owner"/>
|
||||
<property name="names" value="id,firstname,lastname,address,city,telephone"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2025 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.samples.petclinic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
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.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 = { "/simple-job-launcher-context.xml",
|
||||
"/org/springframework/batch/samples/petclinic/job/ownersExportJob.xml" })
|
||||
class PetClinicJobFunctionalTests {
|
||||
|
||||
@Autowired
|
||||
private JobLauncherTestUtils jobLauncherTestUtils;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws IOException {
|
||||
Files.deleteIfExists(Paths.get("owners.csv"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLaunchJobWithXmlConfiguration() throws Exception {
|
||||
// when
|
||||
JobExecution jobExecution = jobLauncherTestUtils.launchJob();
|
||||
|
||||
// then
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLaunchJobWithJavaConfiguration() throws Exception {
|
||||
// given
|
||||
ApplicationContext context = new AnnotationConfigApplicationContext(OwnersExportJobConfiguration.class);
|
||||
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
|
||||
Job job = context.getBean(Job.class);
|
||||
|
||||
// when
|
||||
JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
|
||||
|
||||
// then
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user