Skip to content

Commit b5cf9b3

Browse files
authored
GH-10083 Add Nullability to the mapping package
Related to: #10083 * `AbstractHeaderMapper` - Enhanced null safety by adding `@Nullable` annotations to fields and methods. * Updated method signatures to match those in `AbstractHeaderMapper` for the following classes: - `DefaultAmqpHeaderMapper` - `DefaultSoapHeaderMapper` - `DefaultXmppHeaderMapper` * `buildResolvableType` should accept a null `ClassLoader` * Move `@Contract` to `getClassForValue` *Remove redundant `Assert.state()`.
1 parent 36559ca commit b5cf9b3

File tree

7 files changed

+33
-28
lines changed

7 files changed

+33
-28
lines changed

spring-integration-amqp/src/main/java/org/springframework/integration/amqp/support/DefaultAmqpHeaderMapper.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
* @author Artem Bilan
5757
* @author Stephane Nicoll
5858
* @author Steve Singer
59+
* @author Glenn Renfro
5960
*
6061
* @since 2.1
6162
*/
@@ -107,8 +108,8 @@ protected DefaultAmqpHeaderMapper(String @Nullable [] requestHeaderNames, String
107108
* Extract "standard" headers from an AMQP MessageProperties instance.
108109
*/
109110
@Override
110-
protected Map<String, Object> extractStandardHeaders(MessageProperties amqpMessageProperties) {
111-
Map<String, Object> headers = new HashMap<>();
111+
protected Map<String, @Nullable Object> extractStandardHeaders(MessageProperties amqpMessageProperties) {
112+
Map<String, @Nullable Object> headers = new HashMap<>();
112113
try {
113114
JavaUtils.INSTANCE
114115
.acceptIfNotNull(AmqpHeaders.APP_ID, amqpMessageProperties.getAppId(), headers::put)
@@ -326,13 +327,13 @@ else if (contentType instanceof String) {
326327
}
327328

328329
@Override
329-
public Map<String, Object> toHeadersFromRequest(MessageProperties source) {
330-
Map<String, Object> headersFromRequest = super.toHeadersFromRequest(source);
330+
public Map<String, @Nullable Object> toHeadersFromRequest(MessageProperties source) {
331+
Map<String, @Nullable Object> headersFromRequest = super.toHeadersFromRequest(source);
331332
addConsumerMetadata(source, headersFromRequest);
332333
return headersFromRequest;
333334
}
334335

335-
private void addConsumerMetadata(MessageProperties messageProperties, Map<String, Object> headers) {
336+
private void addConsumerMetadata(MessageProperties messageProperties, Map<String, @Nullable Object> headers) {
336337
String consumerTag = messageProperties.getConsumerTag();
337338
if (consumerTag != null) {
338339
headers.put(AmqpHeaders.CONSUMER_TAG, consumerTag);

spring-integration-core/src/main/java/org/springframework/integration/mapping/AbstractHeaderMapper.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
* @author Stephane Nicoll
5252
* @author Gary Russell
5353
* @author Artem Bilan
54+
* @author Glenn Renfro
5455
*
5556
* @since 2.1
5657
*/
@@ -87,7 +88,7 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
8788

8889
private HeaderMatcher replyHeaderMatcher;
8990

90-
private ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
91+
private @Nullable ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
9192

9293
/**
9394
* Create a new instance.
@@ -113,7 +114,7 @@ public void setBeanClassLoader(ClassLoader classLoader) {
113114
this.classLoader = classLoader;
114115
}
115116

116-
protected ClassLoader getClassLoader() {
117+
protected @Nullable ClassLoader getClassLoader() {
117118
return this.classLoader;
118119
}
119120

@@ -204,12 +205,12 @@ public void fromHeadersToReply(MessageHeaders headers, T target) {
204205
}
205206

206207
@Override
207-
public Map<String, Object> toHeadersFromRequest(T source) {
208+
public Map<String, @Nullable Object> toHeadersFromRequest(T source) {
208209
return toHeaders(source, this.requestHeaderMatcher);
209210
}
210211

211212
@Override
212-
public Map<String, Object> toHeadersFromReply(T source) {
213+
public Map<String, @Nullable Object> toHeadersFromReply(T source) {
213214
return toHeaders(source, this.replyHeaderMatcher);
214215
}
215216

@@ -264,18 +265,19 @@ private boolean isMessageChannel(String headerName, Object headerValue) {
264265
* Map headers from a source instance to the {@link MessageHeaders} of
265266
* a {@link org.springframework.messaging.Message}.
266267
*/
267-
private Map<String, Object> toHeaders(T source, HeaderMatcher headerMatcher) {
268-
Map<String, Object> headers = new HashMap<>();
269-
Map<String, Object> standardHeaders = extractStandardHeaders(source);
268+
private Map<String, @Nullable Object> toHeaders(T source, HeaderMatcher headerMatcher) {
269+
Map<String, @Nullable Object> headers = new HashMap<>();
270+
Map<String, @Nullable Object> standardHeaders = extractStandardHeaders(source);
270271
copyHeaders(standardHeaders, headers, headerMatcher);
271-
Map<String, Object> userDefinedHeaders = extractUserDefinedHeaders(source);
272+
Map<String, @Nullable Object> userDefinedHeaders = extractUserDefinedHeaders(source);
272273
copyHeaders(userDefinedHeaders, headers, headerMatcher);
273274
return headers;
274275
}
275276

276-
private void copyHeaders(Map<String, Object> source, Map<String, Object> target, HeaderMatcher headerMatcher) {
277+
private void copyHeaders(Map<String, @Nullable Object> source, Map<String, @Nullable Object> target,
278+
HeaderMatcher headerMatcher) {
277279
if (!CollectionUtils.isEmpty(source)) {
278-
for (Map.Entry<String, Object> entry : source.entrySet()) {
280+
for (Map.Entry<String, @Nullable Object> entry : source.entrySet()) {
279281
try {
280282
String headerName = createTargetPropertyName(entry.getKey(), false);
281283
if (shouldMapHeader(headerName, headerMatcher)) {
@@ -322,8 +324,7 @@ private boolean shouldMapHeader(String headerName, HeaderMatcher headerMatcher)
322324
}
323325

324326
@SuppressWarnings("unchecked")
325-
@Nullable
326-
protected <V> V getHeaderIfAvailable(Map<String, Object> headers, String name, Class<V> type) {
327+
protected @Nullable <V> V getHeaderIfAvailable(Map<String, Object> headers, String name, Class<V> type) {
327328
Object value = headers.get(name);
328329
if (value == null) {
329330
return null;
@@ -365,7 +366,7 @@ protected Collection<String> getTransientHeaderNames() {
365366
* @param source the source object to extract standard headers.
366367
* @return the map of headers to be mapped.
367368
*/
368-
protected abstract Map<String, Object> extractStandardHeaders(T source);
369+
protected abstract Map<String, @Nullable Object> extractStandardHeaders(T source);
369370

370371
/**
371372
* Extract the user-defined headers from the specified source.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
22
* Provides classes related to mapping to/from message headers.
33
*/
4-
@org.springframework.lang.NonNullApi
4+
@org.jspecify.annotations.NullMarked
55
package org.springframework.integration.mapping;

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.springframework.core.ResolvableType;
2626
import org.springframework.core.convert.TypeDescriptor;
27+
import org.springframework.lang.Contract;
2728
import org.springframework.util.ClassUtils;
2829

2930
/**
@@ -32,6 +33,7 @@
3233
*
3334
* @author Artem Bilan
3435
* @author Gary Russell
36+
* @author Glenn Renfro
3537
*
3638
* @since 3.0
3739
*/
@@ -67,18 +69,17 @@ private JsonHeaders() {
6769
* @return the {@link ResolvableType} based on provided class components
6870
* @since 5.2.4
6971
*/
70-
public static ResolvableType buildResolvableType(ClassLoader classLoader, Object targetClassValue,
72+
public static ResolvableType buildResolvableType(@Nullable ClassLoader classLoader, Object targetClassValue,
7173
@Nullable Object contentClassValue, @Nullable Object keyClassValue) {
7274

7375
Class<?> targetClass = getClassForValue(classLoader, targetClassValue);
7476
Class<?> keyClass = getClassForValue(classLoader, keyClassValue);
7577
Class<?> contentClass = getClassForValue(classLoader, contentClassValue);
76-
7778
return buildResolvableType(targetClass, contentClass, keyClass);
7879
}
7980

80-
@Nullable
81-
private static Class<?> getClassForValue(ClassLoader classLoader, @Nullable Object classValue) {
81+
@Contract("_, null -> null; _, !null -> !null")
82+
private static @Nullable Class<?> getClassForValue(@Nullable ClassLoader classLoader, @Nullable Object classValue) {
8283
if (classValue instanceof Class<?>) {
8384
return (Class<?>) classValue;
8485
}
@@ -105,7 +106,6 @@ else if (classValue != null) {
105106
*/
106107
public static ResolvableType buildResolvableType(Class<?> targetClass, @Nullable Class<?> contentClass,
107108
@Nullable Class<?> keyClass) {
108-
109109
if (keyClass != null) {
110110
return TypeDescriptor
111111
.map(targetClass,
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/**
22
* Support classes for mapping.
33
*/
4+
@org.jspecify.annotations.NullMarked
45
package org.springframework.integration.mapping.support;

spring-integration-ws/src/main/java/org/springframework/integration/ws/DefaultSoapHeaderMapper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
* @author Artem Bilan
5757
* @author Gary Russell
5858
* @author Jooyoung Pyoung
59+
* @author Glenn Renfro
5960
*
6061
* @since 2.0
6162
*/
@@ -74,10 +75,10 @@ public DefaultSoapHeaderMapper() {
7475
}
7576

7677
@Override
77-
protected Map<String, Object> extractStandardHeaders(SoapMessage source) {
78+
protected Map<String, @Nullable Object> extractStandardHeaders(SoapMessage source) {
7879
final String soapAction = source.getSoapAction();
7980
if (StringUtils.hasText(soapAction)) {
80-
Map<String, Object> headers = new HashMap<>(1);
81+
Map<String, @Nullable Object> headers = new HashMap<>(1);
8182
headers.put(WebServiceHeaders.SOAP_ACTION, soapAction);
8283
return headers;
8384
}

spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/support/DefaultXmppHeaderMapper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
* @author Florian Schmaus
4242
* @author Stephane Nicoll
4343
* @author Artem Bilan
44+
* @author Glenn Renfro
4445
*
4546
* @since 2.1
4647
*/
@@ -61,8 +62,8 @@ public DefaultXmppHeaderMapper() {
6162
}
6263

6364
@Override
64-
protected Map<String, Object> extractStandardHeaders(MessageBuilder source) {
65-
Map<String, Object> headers = new HashMap<>();
65+
protected Map<String, @Nullable Object> extractStandardHeaders(MessageBuilder source) {
66+
Map<String, @Nullable Object> headers = new HashMap<>();
6667
Jid from = source.getFrom();
6768
if (from != null) {
6869
headers.put(XmppHeaders.FROM, from.toString());

0 commit comments

Comments
 (0)