Skip to content

Commit 88ebaab

Browse files
committed
GH-4826: Add support for job descriptions
- Add description field and methods to AbstractJob class - Implement description setting in JobBuilderHelper - Add test cases for both XML and Java configurations - Update documentation with usage examples Signed-off-by: minkukjo <[email protected]>
1 parent d7e13fb commit 88ebaab

File tree

7 files changed

+201
-2
lines changed

7 files changed

+201
-2
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2023 the original author or authors.
2+
* Copyright 2006-2025 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.
@@ -71,6 +71,7 @@
7171
* @author Lucas Ward
7272
* @author Dave Syer
7373
* @author Mahmoud Ben Hassine
74+
* @author Minkuk Jo
7475
*/
7576
public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, InitializingBean {
7677

@@ -96,6 +97,8 @@ public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, In
9697

9798
private BatchJobObservationConvention observationConvention = new DefaultBatchJobObservationConvention();
9899

100+
private String description;
101+
99102
/**
100103
* Default constructor.
101104
*/
@@ -112,6 +115,24 @@ public AbstractJob(String name) {
112115
this.name = name;
113116
}
114117

118+
/**
119+
* Set the description of the job.
120+
* @param description the job description
121+
* @since 6.0
122+
*/
123+
public void setDescription(String description) {
124+
this.description = description;
125+
}
126+
127+
/**
128+
* Get the description of the job.
129+
* @return the job description
130+
* @since 6.0
131+
*/
132+
public String getDescription() {
133+
return this.description;
134+
}
135+
115136
/**
116137
* A validator for job parameters. Defaults to a vanilla
117138
* {@link DefaultJobParametersValidator}.

spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java

+30
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
* @author Dave Syer
4747
* @author Mahmoud Ben Hassine
4848
* @author Taeik Lim
49+
* @author Minkuk Jo
4950
* @since 2.2
5051
*/
5152
public abstract class JobBuilderHelper<B extends JobBuilderHelper<B>> {
@@ -180,6 +181,19 @@ public B preventRestart() {
180181
return result;
181182
}
182183

184+
/**
185+
* Add a description to the job.
186+
* @param description the job description
187+
* @return this to enable fluent chaining
188+
* @since 6.0
189+
*/
190+
public B description(String description) {
191+
properties.description = description;
192+
@SuppressWarnings("unchecked")
193+
B result = (B) this;
194+
return result;
195+
}
196+
183197
protected String getName() {
184198
return properties.name;
185199
}
@@ -221,6 +235,11 @@ protected void enhance(AbstractJob job) {
221235
job.setRestartable(restartable);
222236
}
223237

238+
String description = properties.getDescription();
239+
if (description != null) {
240+
job.setDescription(properties.description);
241+
}
242+
224243
List<JobExecutionListener> listeners = properties.getJobExecutionListeners();
225244
if (!listeners.isEmpty()) {
226245
job.setJobExecutionListeners(listeners.toArray(new JobExecutionListener[0]));
@@ -245,6 +264,8 @@ public static class CommonJobProperties {
245264

246265
private JobParametersValidator jobParametersValidator;
247266

267+
private String description;
268+
248269
public CommonJobProperties() {
249270
}
250271

@@ -258,6 +279,7 @@ public CommonJobProperties(CommonJobProperties properties) {
258279
this.jobExecutionListeners = new LinkedHashSet<>(properties.jobExecutionListeners);
259280
this.jobParametersIncrementer = properties.jobParametersIncrementer;
260281
this.jobParametersValidator = properties.jobParametersValidator;
282+
this.description = properties.description;
261283
}
262284

263285
public JobParametersIncrementer getJobParametersIncrementer() {
@@ -336,6 +358,14 @@ public void setRestartable(boolean restartable) {
336358
this.restartable = restartable;
337359
}
338360

361+
public String getDescription() {
362+
return description;
363+
}
364+
365+
public void setDescription(String description) {
366+
this.description = description;
367+
}
368+
339369
private String name;
340370

341371
}

spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2025 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.
@@ -24,11 +24,14 @@
2424
import org.springframework.batch.core.JobExecution;
2525
import org.springframework.batch.core.JobExecutionListener;
2626
import org.springframework.batch.core.JobParameters;
27+
import org.springframework.batch.core.Step;
2728
import org.springframework.batch.core.annotation.AfterJob;
2829
import org.springframework.batch.core.annotation.BeforeJob;
2930
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
31+
import org.springframework.batch.core.job.SimpleJob;
3032
import org.springframework.batch.core.launch.JobLauncher;
3133
import org.springframework.batch.core.repository.JobRepository;
34+
import org.springframework.batch.core.step.JobRepositorySupport;
3235
import org.springframework.batch.core.step.builder.StepBuilder;
3336
import org.springframework.batch.repeat.RepeatStatus;
3437
import org.springframework.context.ApplicationContext;
@@ -40,9 +43,11 @@
4043
import org.springframework.transaction.PlatformTransactionManager;
4144

4245
import static org.junit.jupiter.api.Assertions.assertEquals;
46+
import static org.assertj.core.api.Assertions.assertThat;
4347

4448
/**
4549
* @author Mahmoud Ben Hassine
50+
* @author Minkuk Jo
4651
*/
4752
class JobBuilderTests {
4853

@@ -65,6 +70,24 @@ void testListeners() throws Exception {
6570

6671
}
6772

73+
@Test
74+
void testJobDescription() {
75+
// given
76+
ApplicationContext context = new AnnotationConfigApplicationContext(MyJobConfiguration.class);
77+
JobRepository jobRepository = context.getBean(JobRepository.class);
78+
PlatformTransactionManager transactionManager = context.getBean(PlatformTransactionManager.class);
79+
Step step = new StepBuilder("step", jobRepository)
80+
.tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED, transactionManager)
81+
.build();
82+
83+
// when
84+
Job job = new JobBuilder("job", jobRepository).description("This is a test job").start(step).build();
85+
86+
// then
87+
assertThat(job).isInstanceOf(SimpleJob.class);
88+
assertThat(((SimpleJob) job).getDescription()).isEqualTo("This is a test job");
89+
}
90+
6891
@Configuration
6992
@EnableBatchProcessing
7093
static class MyJobConfiguration {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2020-2025 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.core.job.builder;
17+
18+
import org.junit.jupiter.api.Test;
19+
import org.springframework.batch.core.Job;
20+
import org.springframework.batch.core.job.SimpleJob;
21+
import org.springframework.context.support.ClassPathXmlApplicationContext;
22+
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
25+
/**
26+
* @author Minkuk Jo
27+
*/
28+
class JobXmlDescriptionTests {
29+
30+
@Test
31+
void testJobDescriptionFromXml() {
32+
// given
33+
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
34+
"/org/springframework/batch/core/job/builder/JobXmlDescriptionTests-context.xml");
35+
36+
// when
37+
Job job = context.getBean("job", Job.class);
38+
39+
// then
40+
assertThat(job).isInstanceOf(SimpleJob.class);
41+
assertThat(((SimpleJob) job).getDescription()).isEqualTo("A job that processes football data");
42+
}
43+
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2020-2025 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.core.job.builder;
17+
18+
import org.springframework.batch.core.StepContribution;
19+
import org.springframework.batch.core.scope.context.ChunkContext;
20+
import org.springframework.batch.core.step.tasklet.Tasklet;
21+
import org.springframework.batch.repeat.RepeatStatus;
22+
23+
/**
24+
* @author Minkuk Jo
25+
*/
26+
public class TestTasklet implements Tasklet {
27+
28+
@Override
29+
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
30+
return RepeatStatus.FINISHED;
31+
}
32+
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<beans xmlns="http://www.springframework.org/schema/beans"
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+
xsi:schemaLocation="http://www.springframework.org/schema/beans
7+
http://www.springframework.org/schema/beans/spring-beans.xsd
8+
http://www.springframework.org/schema/batch
9+
http://www.springframework.org/schema/batch/spring-batch.xsd
10+
http://www.springframework.org/schema/jdbc
11+
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
12+
13+
<bean id="job" class="org.springframework.batch.core.job.SimpleJob">
14+
<property name="name" value="job"/>
15+
<property name="description" value="A job that processes football data"/>
16+
<property name="jobRepository" ref="jobRepository"/>
17+
<property name="steps">
18+
<list>
19+
<ref bean="step1"/>
20+
</list>
21+
</property>
22+
</bean>
23+
24+
<bean id="step1" class="org.springframework.batch.core.step.tasklet.TaskletStep">
25+
<property name="tasklet" ref="tasklet"/>
26+
<property name="jobRepository" ref="jobRepository"/>
27+
<property name="transactionManager" ref="transactionManager"/>
28+
</bean>
29+
30+
<bean id="tasklet" class="org.springframework.batch.core.job.builder.TestTasklet"/>
31+
32+
<jdbc:embedded-database id="dataSource" type="HSQL">
33+
<jdbc:script location="classpath:org/springframework/batch/core/schema-hsqldb.sql"/>
34+
</jdbc:embedded-database>
35+
36+
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
37+
<property name="databaseType" value="hsql"/>
38+
<property name="dataSource" ref="dataSource"/>
39+
<property name="transactionManager" ref="transactionManager"/>
40+
</bean>
41+
42+
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
43+
<property name="dataSource" ref="dataSource"/>
44+
</bean>
45+
46+
</beans>

spring-batch-docs/modules/ROOT/pages/job/configuring.adoc

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Java::
1414
@Bean
1515
public Job footballJob(JobRepository jobRepository) {
1616
return new JobBuilder("footballJob", jobRepository)
17+
.description("A job that processes football data")
1718
.start(playerLoad())
1819
.next(gameLoad())
1920
.next(playerSummarization())
@@ -38,6 +39,7 @@ The following example creates a `footballJob`:
3839
[source, xml]
3940
----
4041
<job id="footballJob">
42+
<description>A job that processes football data</description>
4143
<step id="playerload" parent="s1" next="gameLoad"/>
4244
<step id="gameLoad" parent="s2" next="playerSummarization"/>
4345
<step id="playerSummarization" parent="s3"/>

0 commit comments

Comments
 (0)