Skip to content

Commit 21af80d

Browse files
committed
Refine contribution #4990
This commit updates nullability checks based on the new changes introduced in #1870. The main refinements are: - Add constructors with mandatory properties - Avoid accepting nullable parameters where appropriate Some classes have been excluded from nullability checks util we fully remove the "no-arg constructor + setters + afterPropertiesSet" approach to creating objects. Resolves #4673
1 parent 551e26d commit 21af80d

File tree

300 files changed

+1538
-2032
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

300 files changed

+1538
-2032
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.io.Serializable;
2020
import java.util.Objects;
2121

22+
import org.jspecify.annotations.Nullable;
23+
2224
import org.springframework.util.ClassUtils;
2325

2426
/**
@@ -35,7 +37,7 @@ public class Entity implements Serializable {
3537

3638
private final long id;
3739

38-
private Integer version;
40+
private @Nullable Integer version;
3941

4042
/**
4143
* The constructor for the {@link Entity} where the ID is established.
@@ -55,7 +57,7 @@ public long getId() {
5557
/**
5658
* @return the version.
5759
*/
58-
public Integer getVersion() {
60+
public @Nullable Integer getVersion() {
5961
return version;
6062
}
6163

spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchObservabilityBeanPostProcessor.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.micrometer.observation.ObservationRegistry;
1919
import org.apache.commons.logging.Log;
2020
import org.apache.commons.logging.LogFactory;
21+
import org.jspecify.annotations.Nullable;
2122

2223
import org.springframework.batch.core.job.AbstractJob;
2324
import org.springframework.batch.core.launch.support.TaskExecutorJobOperator;
@@ -39,7 +40,7 @@ public class BatchObservabilityBeanPostProcessor implements BeanFactoryPostProce
3940

4041
private static final Log LOGGER = LogFactory.getLog(BatchObservabilityBeanPostProcessor.class);
4142

42-
private ConfigurableListableBeanFactory beanFactory;
43+
private @Nullable ConfigurableListableBeanFactory beanFactory;
4344

4445
@Override
4546
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
@@ -48,6 +49,10 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
4849

4950
@Override
5051
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
52+
if (this.beanFactory == null) {
53+
LOGGER.warn("BeanFactory is not initialized, skipping observation registry injection");
54+
return bean;
55+
}
5156
try {
5257
if (bean instanceof AbstractJob || bean instanceof AbstractStep
5358
|| bean instanceof TaskExecutorJobOperator) {

spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.batch.core.configuration.support;
1717

1818
import io.micrometer.observation.ObservationRegistry;
19+
import org.jspecify.annotations.NullUnmarked;
1920

2021
import org.springframework.batch.core.configuration.DuplicateJobException;
2122
import org.springframework.batch.core.configuration.annotation.BatchObservabilityBeanPostProcessor;
@@ -78,6 +79,7 @@
7879
*/
7980
@Configuration(proxyBeanMethods = false)
8081
@Import({ ScopeConfiguration.class, BatchObservabilityBeanPostProcessor.class })
82+
@NullUnmarked
8183
public class DefaultBatchConfiguration implements ApplicationContextAware {
8284

8385
protected ApplicationContext applicationContext;

spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java

Lines changed: 3 additions & 12 deletions
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.
@@ -48,21 +48,12 @@ public class GroupAwareJob implements Job {
4848

4949
private final String groupName;
5050

51-
/**
52-
* Create a new {@link Job} with the delegate and no group name.
53-
* @param delegate a delegate for the features of a regular Job
54-
*/
55-
public GroupAwareJob(Job delegate) {
56-
this(null, delegate);
57-
}
58-
5951
/**
6052
* Create a new {@link Job} with the given group name and delegate.
6153
* @param groupName the group name to prepend (can be {@code null})
6254
* @param delegate a delegate for the features of a regular Job
6355
*/
64-
public GroupAwareJob(@Nullable String groupName, Job delegate) {
65-
super();
56+
public GroupAwareJob(String groupName, Job delegate) {
6657
this.groupName = groupName;
6758
this.delegate = delegate;
6859
}
@@ -79,7 +70,7 @@ public void execute(JobExecution execution) {
7970
*/
8071
@Override
8172
public String getName() {
82-
return groupName == null ? delegate.getName() : groupName + SEPARATOR + delegate.getName();
73+
return groupName + SEPARATOR + delegate.getName();
8374
}
8475

8576
@Override

spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
import org.apache.commons.logging.Log;
2525
import org.apache.commons.logging.LogFactory;
26-
import org.jspecify.annotations.Nullable;
26+
import org.jspecify.annotations.NullUnmarked;
2727

2828
import org.springframework.batch.core.job.Job;
2929
import org.springframework.batch.core.configuration.DuplicateJobException;
@@ -44,6 +44,7 @@
4444
* @author Robert Fischer
4545
* @author Mahmoud Ben Hassine
4646
*/
47+
@NullUnmarked // FIXME how to fix nullability checks for the applicationContext field?
4748
public class MapJobRegistry implements JobRegistry, SmartInitializingSingleton, ApplicationContextAware {
4849

4950
protected final Log logger = LogFactory.getLog(getClass());
@@ -84,7 +85,7 @@ public void unregister(String name) {
8485
}
8586

8687
@Override
87-
public Job getJob(@Nullable String name) throws NoSuchJobException {
88+
public Job getJob(String name) throws NoSuchJobException {
8889
Job job = this.map.get(name);
8990
if (job == null) {
9091
throw new NoSuchJobException("No job with the name [" + name + "] was registered");

spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2022 the original author or authors.
2+
* Copyright 2012-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.
@@ -64,7 +64,7 @@ public void unregisterStepsFromJob(String jobName) {
6464
}
6565

6666
@Override
67-
public @Nullable Step getStep(String jobName, String stepName) throws NoSuchJobException {
67+
public Step getStep(String jobName, String stepName) throws NoSuchJobException {
6868
Assert.notNull(jobName, "The job name cannot be null.");
6969
Assert.notNull(stepName, "The step name cannot be null.");
7070
if (!map.containsKey(jobName)) {

spring-batch-core/src/main/java/org/springframework/batch/core/converter/JsonJobParametersConverter.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022-2023 the original author or authors.
2+
* Copyright 2022-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.
@@ -17,6 +17,7 @@
1717

1818
import com.fasterxml.jackson.core.JsonProcessingException;
1919
import com.fasterxml.jackson.databind.ObjectMapper;
20+
import org.jspecify.annotations.Nullable;
2021

2122
import org.springframework.batch.core.job.parameters.JobParameter;
2223
import org.springframework.batch.core.job.parameters.JobParameters;
@@ -91,6 +92,10 @@ protected String encode(JobParameter<?> jobParameter) {
9192
Object parameterTypedValue = jobParameter.getValue();
9293
boolean parameterIdentifying = jobParameter.isIdentifying();
9394
String parameterStringValue = this.conversionService.convert(parameterTypedValue, String.class);
95+
if (parameterStringValue == null) {
96+
throw new JobParametersConversionException(
97+
"Unable to encode job parameter of type " + parameterType + " with value " + parameterTypedValue);
98+
}
9499
try {
95100
return this.objectMapper.writeValueAsString(new JobParameterDefinition(parameterStringValue,
96101
parameterType.getName(), Boolean.toString(parameterIdentifying)));
@@ -122,7 +127,7 @@ protected JobParameter decode(String encodedJobParameter) {
122127
}
123128
}
124129

125-
public record JobParameterDefinition(String value, String type, String identifying) {
130+
public record JobParameterDefinition(String value, @Nullable String type, @Nullable String identifying) {
126131
}
127132

128133
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import io.micrometer.observation.ObservationRegistry;
2626
import org.apache.commons.logging.Log;
2727
import org.apache.commons.logging.LogFactory;
28-
import org.jspecify.annotations.Nullable;
28+
import org.jspecify.annotations.NullUnmarked;
2929

3030
import org.springframework.batch.core.BatchStatus;
3131
import org.springframework.batch.core.ExitStatus;
@@ -62,6 +62,7 @@
6262
* @author Dave Syer
6363
* @author Mahmoud Ben Hassine
6464
*/
65+
@NullUnmarked // FIXME to remove once default constructors are removed
6566
public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, InitializingBean {
6667

6768
protected static final Log logger = LogFactory.getLog(AbstractJob.class);
@@ -200,7 +201,7 @@ public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIn
200201
}
201202

202203
@Override
203-
public @Nullable JobParametersIncrementer getJobParametersIncrementer() {
204+
public JobParametersIncrementer getJobParametersIncrementer() {
204205
return this.jobParametersIncrementer;
205206
}
206207

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public String generateKey(JobParameters source) {
5252
Collections.sort(keys);
5353
for (String key : keys) {
5454
JobParameter<?> jobParameter = props.get(key);
55-
if (jobParameter.isIdentifying()) {
55+
if (jobParameter != null && jobParameter.isIdentifying()) {
5656
String value = jobParameter.toString();
5757
stringBuffer.append(key).append("=").append(value).append(";");
5858
}

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@
2626
import java.util.Set;
2727
import java.util.concurrent.CopyOnWriteArrayList;
2828

29-
import org.springframework.batch.core.*;
29+
import org.jspecify.annotations.Nullable;
30+
31+
import org.springframework.batch.core.BatchStatus;
32+
import org.springframework.batch.core.Entity;
33+
import org.springframework.batch.core.ExitStatus;
3034
import org.springframework.batch.core.job.parameters.JobParameters;
3135
import org.springframework.batch.core.step.StepExecution;
3236
import org.springframework.batch.item.ExecutionContext;
33-
import org.springframework.lang.Nullable;
3437

3538
/**
3639
* Batch domain object representing the execution of a job.
@@ -54,11 +57,11 @@ public class JobExecution extends Entity {
5457

5558
private LocalDateTime createTime = LocalDateTime.now();
5659

57-
private LocalDateTime startTime = null;
60+
private @Nullable LocalDateTime startTime = null;
5861

59-
private LocalDateTime endTime = null;
62+
private @Nullable LocalDateTime endTime = null;
6063

61-
private LocalDateTime lastUpdated = null;
64+
private @Nullable LocalDateTime lastUpdated = null;
6265

6366
private ExitStatus exitStatus = ExitStatus.UNKNOWN;
6467

@@ -92,8 +95,7 @@ public JobParameters getJobParameters() {
9295
/**
9396
* @return The current end time.
9497
*/
95-
@Nullable
96-
public LocalDateTime getEndTime() {
98+
@Nullable public LocalDateTime getEndTime() {
9799
return endTime;
98100
}
99101

@@ -116,8 +118,7 @@ public void setEndTime(LocalDateTime endTime) {
116118
/**
117119
* @return The current start time.
118120
*/
119-
@Nullable
120-
public LocalDateTime getStartTime() {
121+
@Nullable public LocalDateTime getStartTime() {
121122
return startTime;
122123
}
123124

@@ -265,8 +266,7 @@ public void addStepExecutions(List<StepExecution> stepExecutions) {
265266
* @return a {@link LocalDateTime} object representing the last time this
266267
* {@code JobExecution} was updated.
267268
*/
268-
@Nullable
269-
public LocalDateTime getLastUpdated() {
269+
@Nullable public LocalDateTime getLastUpdated() {
270270
return lastUpdated;
271271
}
272272

0 commit comments

Comments
 (0)