Skip to content

Commit 52beed4

Browse files
committed
Add java configuration for the Repository item reader/writer sample
Issue spring-projects#3663
1 parent d68dd3c commit 52beed4

File tree

8 files changed

+250
-59
lines changed

8 files changed

+250
-59
lines changed

spring-batch-samples/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ efficient updates to a database table.
109109

110110
[Jdbc Readers and Batch Update sample](./src/main/java/org/springframework/batch/sample/jdbc/README.md)
111111

112-
### JPA Reader and Writer sample
112+
### JPA Readers and Writers sample
113113

114-
The purpose of this sample is to show to usage of the `JpaPagingItemReader`
115-
and the `JpaItemWriter` to read and write data from/to a database with JPA.
114+
The purpose of this sample is to show to usage of the JPA item readers and writers
115+
to read and write data from/to a database with JPA and Hibernate.
116116

117-
[JPA Reader and Writer sample](./src/main/java/org/springframework/batch/sample/jpa/README.md)
117+
[JPA Readers and Writers sample](./src/main/java/org/springframework/batch/sample/jpa/README.md)
118118

119119
### Amqp Job Sample
120120

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 the original author or authors.
2+
* Copyright 2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package org.springframework.batch.sample.data;
16+
package org.springframework.batch.sample.jpa;
1717

1818
import org.springframework.batch.sample.domain.trade.CustomerCredit;
1919

Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package org.springframework.batch.sample.data;
16+
package org.springframework.batch.sample.jpa;
1717

1818
import java.math.BigDecimal;
1919

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright 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.jpa;
17+
18+
import java.math.BigDecimal;
19+
import java.util.Map;
20+
21+
import javax.sql.DataSource;
22+
import jakarta.persistence.EntityManagerFactory;
23+
24+
import org.springframework.batch.core.Job;
25+
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
26+
import org.springframework.batch.core.configuration.annotation.StepScope;
27+
import org.springframework.batch.core.job.builder.JobBuilder;
28+
import org.springframework.batch.core.repository.JobRepository;
29+
import org.springframework.batch.core.step.builder.StepBuilder;
30+
import org.springframework.batch.item.data.RepositoryItemReader;
31+
import org.springframework.batch.item.data.RepositoryItemWriter;
32+
import org.springframework.batch.item.data.builder.RepositoryItemReaderBuilder;
33+
import org.springframework.batch.item.data.builder.RepositoryItemWriterBuilder;
34+
import org.springframework.batch.item.database.JpaItemWriter;
35+
import org.springframework.batch.item.database.JpaPagingItemReader;
36+
import org.springframework.batch.sample.domain.trade.CustomerCredit;
37+
import org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor;
38+
import org.springframework.beans.factory.annotation.Value;
39+
import org.springframework.context.annotation.Bean;
40+
import org.springframework.context.annotation.Configuration;
41+
import org.springframework.data.domain.Sort;
42+
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
43+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
44+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
45+
import org.springframework.orm.jpa.JpaTransactionManager;
46+
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
47+
import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
48+
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
49+
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
50+
51+
/**
52+
* Hibernate JPA dialect does not support custom tx isolation levels => overwrite with
53+
* ISOLATION_DEFAULT.
54+
*
55+
* @author Mahmoud Ben Hassine
56+
*/
57+
@Configuration
58+
@EnableBatchProcessing(isolationLevelForCreate = "ISOLATION_DEFAULT")
59+
@EnableJpaRepositories(basePackages = "org.springframework.batch.sample.jpa")
60+
public class JpaRepositoryJobConfiguration {
61+
62+
@Bean
63+
@StepScope
64+
public RepositoryItemReader<CustomerCredit> itemReader(@Value("#{jobParameters['credit']}") Double credit,
65+
CustomerCreditPagingAndSortingRepository repository) {
66+
return new RepositoryItemReaderBuilder<CustomerCredit>().name("itemReader")
67+
.pageSize(2)
68+
.methodName("findByCreditGreaterThan")
69+
.repository(repository)
70+
.arguments(BigDecimal.valueOf(credit))
71+
.sorts(Map.of("id", Sort.Direction.ASC))
72+
.build();
73+
}
74+
75+
@Bean
76+
public RepositoryItemWriter<CustomerCredit> itemWriter(CustomerCreditCrudRepository repository) {
77+
return new RepositoryItemWriterBuilder<CustomerCredit>().repository(repository).methodName("save").build();
78+
}
79+
80+
@Bean
81+
public Job job(JobRepository jobRepository, JpaTransactionManager transactionManager,
82+
RepositoryItemReader<CustomerCredit> itemReader, RepositoryItemWriter<CustomerCredit> itemWriter) {
83+
return new JobBuilder("ioSampleJob", jobRepository)
84+
.start(new StepBuilder("step1", jobRepository).<CustomerCredit, CustomerCredit>chunk(2, transactionManager)
85+
.reader(itemReader)
86+
.processor(new CustomerCreditIncreaseProcessor())
87+
.writer(itemWriter)
88+
.build())
89+
.build();
90+
}
91+
92+
// Infrastructure beans
93+
94+
@Bean
95+
public DataSource dataSource() {
96+
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
97+
.addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql")
98+
.addScript("/org/springframework/batch/core/schema-hsqldb.sql")
99+
.addScript("/org/springframework/batch/sample/jpa/sql/schema.sql")
100+
.build();
101+
}
102+
103+
@Bean
104+
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
105+
return new JpaTransactionManager(entityManagerFactory);
106+
}
107+
108+
@Bean
109+
public EntityManagerFactory entityManagerFactory(PersistenceUnitManager persistenceUnitManager,
110+
DataSource dataSource) {
111+
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
112+
factoryBean.setDataSource(dataSource);
113+
factoryBean.setPersistenceUnitManager(persistenceUnitManager);
114+
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
115+
factoryBean.afterPropertiesSet();
116+
return factoryBean.getObject();
117+
}
118+
119+
@Bean
120+
public PersistenceUnitManager persistenceUnitManager(DataSource dataSource) {
121+
DefaultPersistenceUnitManager persistenceUnitManager = new DefaultPersistenceUnitManager();
122+
persistenceUnitManager.setDefaultDataSource(dataSource);
123+
persistenceUnitManager.afterPropertiesSet();
124+
return persistenceUnitManager;
125+
}
126+
127+
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
### JPA Reader and Writer sample
1+
### JPA Readers and Writers sample
22

33
## About
44

5-
The purpose of this sample is to show to usage of the `JpaPagingItemReader`
6-
and the `JpaItemWriter` to read and write data from/to a database with JPA.
5+
The purpose of this sample is to show to usage of the JPA item readers and writers
6+
to read and write data from/to a database with JPA and Hibernate.
77

8-
## Run the sample
8+
## Run the samples
99

10-
You can run the sample from the command line as following:
10+
You can run the sample of the `JpaPagingItemReader`/`JpaItemWriter` from the command line as following:
1111

1212
```
1313
$>cd spring-batch-samples
@@ -16,3 +16,13 @@ $>../mvnw -Dtest=JpaFunctionalTests#testLaunchJobWithXmlConfig test
1616
# Launch the sample using the Java configuration
1717
$>../mvnw -Dtest=JpaFunctionalTests#testLaunchJobWithJavaConfig test
1818
```
19+
20+
You can run the sample of the `RepositoryItemReader`/`RepositoryItemWriter` from the command line as following:
21+
22+
```
23+
$>cd spring-batch-samples
24+
# Launch the sample using the XML configuration
25+
$>../mvnw -Dtest=RepositoryFunctionalTests#testLaunchJobWithXmlConfig test
26+
# Launch the sample using the Java configuration
27+
$>../mvnw -Dtest=RepositoryFunctionalTests#testLaunchJobWithJavaConfig test
28+
```

spring-batch-samples/src/main/resources/jobs/iosample/repository.xml renamed to spring-batch-samples/src/main/resources/org/springframework/batch/sample/jpa/job/repository.xml

+33-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<beans xmlns="http://www.springframework.org/schema/beans"
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
5-
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
6-
http://www.springframework.org/schema/data/jpa https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:batch="http://www.springframework.org/schema/batch"
5+
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
6+
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
7+
xsi:schemaLocation="
8+
http://www.springframework.org/schema/batch https://www.springframework.org/schema/batch/spring-batch.xsd
9+
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
10+
http://www.springframework.org/schema/jdbc https://www.springframework.org/schema/jdbc/spring-jdbc.xsd
11+
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
712

8-
<jpa:repositories base-package="org.springframework.batch.sample.data"/>
13+
<jpa:repositories base-package="org.springframework.batch.sample.jpa"/>
14+
15+
<batch:job id="ioSampleJob" xmlns="http://www.springframework.org/schema/batch">
16+
<batch:step id="step1">
17+
<batch:tasklet>
18+
<batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter"
19+
commit-interval="2"/>
20+
</batch:tasklet>
21+
</batch:step>
22+
</batch:job>
23+
24+
<bean id="itemProcessor" class="org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor" />
925

1026
<bean id="itemReader"
1127
class="org.springframework.batch.item.data.RepositoryItemReader" scope="step">
@@ -58,4 +74,16 @@
5874
<property name="dataSource" ref="dataSource" />
5975
<property name="transactionManager" ref="transactionManager" />
6076
</bean>
77+
78+
<bean id="jobLauncher"
79+
class="org.springframework.batch.core.launch.support.TaskExecutorJobLauncher">
80+
<property name="jobRepository" ref="jobRepository" />
81+
</bean>
82+
83+
<jdbc:embedded-database id="dataSource" generate-name="true">
84+
<jdbc:script location="org/springframework/batch/core/schema-drop-hsqldb.sql"/>
85+
<jdbc:script location="org/springframework/batch/core/schema-hsqldb.sql"/>
86+
<jdbc:script location="org/springframework/batch/sample/jpa/sql/schema.sql"/>
87+
</jdbc:embedded-database>
88+
6189
</beans>

spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/RepositoryFunctionalTests.java

-42
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2013-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.jpa;
17+
18+
import org.junit.jupiter.api.Test;
19+
20+
import org.springframework.batch.core.BatchStatus;
21+
import org.springframework.batch.core.Job;
22+
import org.springframework.batch.core.JobExecution;
23+
import org.springframework.batch.core.JobParameters;
24+
import org.springframework.batch.core.JobParametersBuilder;
25+
import org.springframework.batch.core.launch.JobLauncher;
26+
import org.springframework.batch.test.JobLauncherTestUtils;
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.context.ApplicationContext;
29+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
30+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
31+
32+
import static org.junit.jupiter.api.Assertions.assertEquals;
33+
34+
@SpringJUnitConfig(
35+
locations = { "/org/springframework/batch/sample/jpa/job/repository.xml", "/job-runner-context.xml" })
36+
class RepositoryFunctionalTests {
37+
38+
@Autowired
39+
private JobLauncherTestUtils jobLauncherTestUtils;
40+
41+
@Test
42+
void testLaunchJobWithXmlConfig() throws Exception {
43+
// given
44+
JobParameters jobParameters = new JobParametersBuilder().addDouble("credit", 10000D).toJobParameters();
45+
46+
// when
47+
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
48+
49+
// then
50+
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
51+
}
52+
53+
@Test
54+
public void testLaunchJobWithJavaConfig() throws Exception {
55+
// given
56+
ApplicationContext context = new AnnotationConfigApplicationContext(JpaRepositoryJobConfiguration.class);
57+
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
58+
Job job = context.getBean(Job.class);
59+
JobParameters jobParameters = new JobParametersBuilder().addDouble("credit", 10000D).toJobParameters();
60+
61+
// when
62+
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
63+
64+
// then
65+
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
66+
}
67+
68+
}

0 commit comments

Comments
 (0)