Skip to content

Commit 448cee7

Browse files
authored
GH-10083: Add Nullability to core support package
Related to: #10083 * Add Nullability support to `support.management` package * Add Nullability support to `support.management.micrometer` package * Add Nullability support to `support.management.observation` * Add Nullability support to `support.json` * Removed nullable parameters from `fromJson` * Disabled null checks in Deprecated Jackson2 classes Remove Nullable from Jackson2 classes * Remove Nullable from `AbstractLeaderEvent` * Remove unnecessary `@SuppressWarnings` * Remove unnecessary if statements following review
1 parent 398715b commit 448cee7

File tree

36 files changed

+115
-73
lines changed

36 files changed

+115
-73
lines changed

spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
*
4848
*
4949
* @author Artem Bilan
50+
* @author Glenn Renfro
5051
*
5152
* @since 5.2
5253
*/
@@ -84,6 +85,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
8485
@Override
8586
public Object processMessageGroup(MessageGroup group) {
8687
Object result = this.delegate.processMessageGroup(group);
88+
Assert.state(result != null, "The delegate must return a non-null for the group");
8789
if (!(result instanceof Message<?>) && !(result instanceof AbstractIntegrationMessageBuilder)) {
8890
result = getMessageBuilderFactory()
8991
.withPayload(result)

spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ protected Object doTransform(Message<?> message) {
180180
catch (IOException e) {
181181
throw new UncheckedIOException(e);
182182
}
183-
183+
Assert.state(result != null, "Payload result must not be null");
184184
if (removeHeaders) {
185185
return getMessageBuilderFactory()
186186
.withPayload(result)

spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.io.UncheckedIOException;
2323
import java.util.Map;
2424

25+
import org.jspecify.annotations.Nullable;
26+
2527
import org.springframework.integration.support.json.JsonObjectMapper;
2628
import org.springframework.integration.support.json.JsonObjectMapperProvider;
2729
import org.springframework.integration.transformer.AbstractTransformer;
@@ -114,7 +116,7 @@ public String getComponentType() {
114116
@Override
115117
protected Object doTransform(Message<?> message) {
116118
Object payload = buildJsonPayload(message.getPayload());
117-
119+
Assert.state(payload != null, "Payload result must not be null");
118120
Map<String, Object> headers = new LinkedCaseInsensitiveMap<>();
119121
headers.putAll(message.getHeaders());
120122

@@ -136,7 +138,7 @@ else if (StringUtils.hasLength(this.contentType)) {
136138
.build();
137139
}
138140

139-
private Object buildJsonPayload(Object payload) {
141+
private @Nullable Object buildJsonPayload(Object payload) {
140142
try {
141143
switch (this.resultType) {
142144

spring-integration-core/src/main/java/org/springframework/integration/leader/event/AbstractLeaderEvent.java

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
package org.springframework.integration.leader.event;
1818

19-
import org.jspecify.annotations.Nullable;
20-
2119
import org.springframework.context.ApplicationEvent;
2220
import org.springframework.integration.leader.Context;
2321

@@ -32,18 +30,9 @@
3230
@SuppressWarnings("serial")
3331
public abstract class AbstractLeaderEvent extends ApplicationEvent {
3432

35-
private final @Nullable Context context;
36-
37-
private final @Nullable String role;
33+
private final Context context;
3834

39-
/**
40-
* Create a new ApplicationEvent.
41-
*
42-
* @param source the component that published the event (never {@code null})
43-
*/
44-
public AbstractLeaderEvent(Object source) {
45-
this(source, null, null);
46-
}
35+
private final String role;
4736

4837
/**
4938
* Create a new ApplicationEvent.
@@ -52,7 +41,7 @@ public AbstractLeaderEvent(Object source) {
5241
* @param context the context associated with this event
5342
* @param role the role of the leader
5443
*/
55-
public AbstractLeaderEvent(Object source, @Nullable Context context, @Nullable String role) {
44+
public AbstractLeaderEvent(Object source, Context context, String role) {
5645
super(source);
5746
this.context = context;
5847
this.role = role;
@@ -63,7 +52,7 @@ public AbstractLeaderEvent(Object source, @Nullable Context context, @Nullable S
6352
*
6453
* @return the context
6554
*/
66-
public @Nullable Context getContext() {
55+
public Context getContext() {
6756
return this.context;
6857
}
6958

@@ -72,7 +61,7 @@ public AbstractLeaderEvent(Object source, @Nullable Context context, @Nullable S
7261
*
7362
* @return the role
7463
*/
75-
public @Nullable String getRole() {
64+
public String getRole() {
7665
return this.role;
7766
}
7867

spring-integration-core/src/main/java/org/springframework/integration/splitter/AbstractMessageSplitter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ else if (result instanceof Publisher<?> publisher) {
234234
Map<String, Object> headers = messageHeaders;
235235
Object correlationId = message.getHeaders().getId();
236236
AtomicInteger sequenceNumber = new AtomicInteger(1);
237-
238237
return object -> createBuilder(object, headers, correlationId, sequenceNumber.getAndIncrement(), sequenceSize);
239238
}
240239

@@ -282,6 +281,7 @@ private AbstractIntegrationMessageBuilder<?> createBuilder(Object item, Map<Stri
282281
.cloneMessageHistoryIfAny();
283282

284283
if (this.applySequence) {
284+
Assert.state(correlationId != null, "Correlation ID must not be null.");
285285
builder.pushSequenceDetails(correlationId, sequenceNumber, sequenceSize);
286286
}
287287

spring-integration-core/src/main/java/org/springframework/integration/support/BaseMessageBuilder.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import org.springframework.messaging.support.ErrorMessage;
3333
import org.springframework.messaging.support.GenericMessage;
3434
import org.springframework.util.Assert;
35-
import org.springframework.util.ObjectUtils;
3635

3736
/**
3837
* The {@link AbstractIntegrationMessageBuilder} extension for the default logic to build message.
@@ -48,6 +47,7 @@
4847
* @param <B> the target builder class type.
4948
*
5049
* @author Artem Bilan
50+
* @author Glenn Renfro
5151
*
5252
* @since 6.4
5353
*
@@ -63,12 +63,11 @@ public abstract class BaseMessageBuilder<T, B extends BaseMessageBuilder<T, B>>
6363

6464
private final IntegrationMessageHeaderAccessor headerAccessor;
6565

66-
@Nullable
67-
private final Message<T> originalMessage;
66+
private final @Nullable Message<T> originalMessage;
6867

6968
private volatile boolean modified;
7069

71-
private String[] readOnlyHeaders;
70+
private String @Nullable [] readOnlyHeaders;
7271

7372
protected BaseMessageBuilder(T payload, @Nullable Message<T> originalMessage) {
7473
Assert.notNull(payload, "payload must not be null");
@@ -285,7 +284,7 @@ public B setPriority(Integer priority) {
285284
* @return the current {@link BaseMessageBuilder}
286285
* @see IntegrationMessageHeaderAccessor#isReadOnly(String)
287286
*/
288-
public B readOnlyHeaders(@Nullable String... readOnlyHeaders) {
287+
public B readOnlyHeaders(String @Nullable ... readOnlyHeaders) {
289288
this.readOnlyHeaders = readOnlyHeaders != null ? Arrays.copyOf(readOnlyHeaders, readOnlyHeaders.length) : null;
290289
if (readOnlyHeaders != null) {
291290
this.headerAccessor.setReadOnlyHeaders(readOnlyHeaders);
@@ -317,7 +316,7 @@ public Message<T> build() {
317316
}
318317

319318
private boolean containsReadOnly(MessageHeaders headers) {
320-
if (!ObjectUtils.isEmpty(this.readOnlyHeaders)) {
319+
if (this.readOnlyHeaders != null) {
321320
for (String readOnly : this.readOnlyHeaders) {
322321
if (headers.containsKey(readOnly)) {
323322
return true;

spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
/**
2626
* @author Gary Russell
2727
* @author Artem Bilan
28+
* @author Glenn Renfro
2829
*
2930
* @since 4.0
3031
*
3132
*/
3233
public class DefaultMessageBuilderFactory implements MessageBuilderFactory {
3334

34-
private String[] readOnlyHeaders;
35+
private String @Nullable [] readOnlyHeaders;
3536

3637
/**
3738
* Specify a list of headers which should be considered as a read only
@@ -41,7 +42,7 @@ public class DefaultMessageBuilderFactory implements MessageBuilderFactory {
4142
* and {@link org.springframework.messaging.MessageHeaders#TIMESTAMP}.
4243
* @since 4.3.2
4344
*/
44-
public void setReadOnlyHeaders(@Nullable String... readOnlyHeaders) {
45+
public void setReadOnlyHeaders(String @Nullable ... readOnlyHeaders) {
4546
this.readOnlyHeaders = readOnlyHeaders != null ? Arrays.copyOf(readOnlyHeaders, readOnlyHeaders.length) : null;
4647
}
4748

@@ -57,7 +58,7 @@ public void addReadOnlyHeaders(String... readOnlyHeaders) {
5758
}
5859
else {
5960
headers = Arrays.copyOf(headers, headers.length + readOnlyHeaders.length);
60-
System.arraycopy(readOnlyHeaders, 0, headers, this.readOnlyHeaders.length, readOnlyHeaders.length);
61+
System.arraycopy(readOnlyHeaders, 0, headers, (this.readOnlyHeaders != null) ? this.readOnlyHeaders.length : 0, readOnlyHeaders.length);
6162
}
6263
this.readOnlyHeaders = headers;
6364
}

spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
*
4646
* @author Gary Russell
4747
* @author Artem Bilan
48+
* @author Glenn Renfro
4849
*
4950
* @since 4.0
5051
*
@@ -80,9 +81,8 @@ public Map<String, Object> getHeaders() {
8081
}
8182

8283
@SuppressWarnings("unchecked")
83-
@Nullable
8484
@Override
85-
public <V> V getHeader(String key, Class<V> type) {
85+
public @Nullable <V> V getHeader(String key, Class<V> type) {
8686
Object value = this.headers.get(key);
8787
if (value == null) {
8888
return null;
@@ -218,22 +218,22 @@ public AbstractIntegrationMessageBuilder<T> copyHeadersIfAbsent(@Nullable Map<St
218218

219219
@SuppressWarnings("unchecked")
220220
@Override
221-
protected List<List<Object>> getSequenceDetails() {
221+
protected @Nullable List<List<Object>> getSequenceDetails() {
222222
return (List<List<Object>>) this.headers.get(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS);
223223
}
224224

225225
@Override
226-
protected Object getCorrelationId() {
226+
protected @Nullable Object getCorrelationId() {
227227
return this.headers.get(IntegrationMessageHeaderAccessor.CORRELATION_ID);
228228
}
229229

230230
@Override
231-
protected Object getSequenceNumber() {
231+
protected @Nullable Object getSequenceNumber() {
232232
return this.headers.get(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER);
233233
}
234234

235235
@Override
236-
protected Object getSequenceSize() {
236+
protected @Nullable Object getSequenceSize() {
237237
return this.headers.get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE);
238238
}
239239

spring-integration-core/src/main/java/org/springframework/integration/support/NullAwarePayloadArgumentResolver.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.integration.support;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
import org.springframework.messaging.converter.MessageConverter;
2022
import org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver;
2123
import org.springframework.validation.Validator;
@@ -40,7 +42,8 @@ public NullAwarePayloadArgumentResolver(MessageConverter messageConverter, Valid
4042
}
4143

4244
@Override
43-
protected boolean isEmptyPayload(Object payload) {
45+
@SuppressWarnings("NullAway") // Dataflow analysis limitation
46+
protected boolean isEmptyPayload(@Nullable Object payload) {
4447
return super.isEmptyPayload(payload) || "KafkaNull".equals(payload.getClass().getSimpleName());
4548
}
4649

spring-integration-core/src/main/java/org/springframework/integration/support/PartialSuccessException.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
*
2929
* @author Gary Russell
3030
* @author Artem Bilan
31+
* @author Glenn Renfro
3132
*
3233
* @since 4.2
3334
*
@@ -97,7 +98,9 @@ public <T> Collection<T> getDerivedInput(Class<T> clazz) {
9798

9899
@Override
99100
public String toString() {
100-
return "PartialSuccessException [" + getMessage() + ":" + getCause().getMessage()
101+
Throwable cause = getCause();
102+
String causeMessage = (cause != null) ? cause.getMessage() : "";
103+
return "PartialSuccessException [" + getMessage() + ":" + causeMessage
101104
+ ", partialResults=" + this.partialResults + ", derivedInput=" + this.derivedInput
102105
+ ", failedMessage=" + getFailedMessage() + "]";
103106
}

0 commit comments

Comments
 (0)