diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java index 642a0b06183..f29eeab604e 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java @@ -47,6 +47,7 @@ * * * @author Artem Bilan + * @author Glenn Renfro * * @since 5.2 */ @@ -84,6 +85,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { @Override public Object processMessageGroup(MessageGroup group) { Object result = this.delegate.processMessageGroup(group); + Assert.state(result != null, "The delegate must return a non-null for the group"); if (!(result instanceof Message) && !(result instanceof AbstractIntegrationMessageBuilder)) { result = getMessageBuilderFactory() .withPayload(result) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java b/spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java index bd956408672..7380e6cdfb5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java @@ -180,7 +180,7 @@ protected Object doTransform(Message message) { catch (IOException e) { throw new UncheckedIOException(e); } - + Assert.state(result != null, "Payload result must not be null"); if (removeHeaders) { return getMessageBuilderFactory() .withPayload(result) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java b/spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java index 47950e35004..dfeccd73dca 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java @@ -22,6 +22,8 @@ import java.io.UncheckedIOException; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.support.json.JsonObjectMapper; import org.springframework.integration.support.json.JsonObjectMapperProvider; import org.springframework.integration.transformer.AbstractTransformer; @@ -114,7 +116,7 @@ public String getComponentType() { @Override protected Object doTransform(Message message) { Object payload = buildJsonPayload(message.getPayload()); - + Assert.state(payload != null, "Payload result must not be null"); Map headers = new LinkedCaseInsensitiveMap<>(); headers.putAll(message.getHeaders()); @@ -136,7 +138,7 @@ else if (StringUtils.hasLength(this.contentType)) { .build(); } - private Object buildJsonPayload(Object payload) { + private @Nullable Object buildJsonPayload(Object payload) { try { switch (this.resultType) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/leader/event/AbstractLeaderEvent.java b/spring-integration-core/src/main/java/org/springframework/integration/leader/event/AbstractLeaderEvent.java index 487c16b2283..901e8f4f0ea 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/leader/event/AbstractLeaderEvent.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/leader/event/AbstractLeaderEvent.java @@ -16,8 +16,6 @@ package org.springframework.integration.leader.event; -import org.jspecify.annotations.Nullable; - import org.springframework.context.ApplicationEvent; import org.springframework.integration.leader.Context; @@ -32,18 +30,9 @@ @SuppressWarnings("serial") public abstract class AbstractLeaderEvent extends ApplicationEvent { - private final @Nullable Context context; - - private final @Nullable String role; + private final Context context; - /** - * Create a new ApplicationEvent. - * - * @param source the component that published the event (never {@code null}) - */ - public AbstractLeaderEvent(Object source) { - this(source, null, null); - } + private final String role; /** * Create a new ApplicationEvent. @@ -52,7 +41,7 @@ public AbstractLeaderEvent(Object source) { * @param context the context associated with this event * @param role the role of the leader */ - public AbstractLeaderEvent(Object source, @Nullable Context context, @Nullable String role) { + public AbstractLeaderEvent(Object source, Context context, String role) { super(source); this.context = context; this.role = role; @@ -63,7 +52,7 @@ public AbstractLeaderEvent(Object source, @Nullable Context context, @Nullable S * * @return the context */ - public @Nullable Context getContext() { + public Context getContext() { return this.context; } @@ -72,7 +61,7 @@ public AbstractLeaderEvent(Object source, @Nullable Context context, @Nullable S * * @return the role */ - public @Nullable String getRole() { + public String getRole() { return this.role; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/splitter/AbstractMessageSplitter.java b/spring-integration-core/src/main/java/org/springframework/integration/splitter/AbstractMessageSplitter.java index 3733cdeaaaa..6e8938aa1ef 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/splitter/AbstractMessageSplitter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/splitter/AbstractMessageSplitter.java @@ -234,7 +234,6 @@ else if (result instanceof Publisher publisher) { Map headers = messageHeaders; Object correlationId = message.getHeaders().getId(); AtomicInteger sequenceNumber = new AtomicInteger(1); - return object -> createBuilder(object, headers, correlationId, sequenceNumber.getAndIncrement(), sequenceSize); } @@ -282,6 +281,7 @@ private AbstractIntegrationMessageBuilder createBuilder(Object item, Map the target builder class type. * * @author Artem Bilan + * @author Glenn Renfro * * @since 6.4 * @@ -63,12 +63,11 @@ public abstract class BaseMessageBuilder> private final IntegrationMessageHeaderAccessor headerAccessor; - @Nullable - private final Message originalMessage; + private final @Nullable Message originalMessage; private volatile boolean modified; - private String[] readOnlyHeaders; + private String @Nullable [] readOnlyHeaders; protected BaseMessageBuilder(T payload, @Nullable Message originalMessage) { Assert.notNull(payload, "payload must not be null"); @@ -285,7 +284,7 @@ public B setPriority(Integer priority) { * @return the current {@link BaseMessageBuilder} * @see IntegrationMessageHeaderAccessor#isReadOnly(String) */ - public B readOnlyHeaders(@Nullable String... readOnlyHeaders) { + public B readOnlyHeaders(String @Nullable ... readOnlyHeaders) { this.readOnlyHeaders = readOnlyHeaders != null ? Arrays.copyOf(readOnlyHeaders, readOnlyHeaders.length) : null; if (readOnlyHeaders != null) { this.headerAccessor.setReadOnlyHeaders(readOnlyHeaders); @@ -317,7 +316,7 @@ public Message build() { } private boolean containsReadOnly(MessageHeaders headers) { - if (!ObjectUtils.isEmpty(this.readOnlyHeaders)) { + if (this.readOnlyHeaders != null) { for (String readOnly : this.readOnlyHeaders) { if (headers.containsKey(readOnly)) { return true; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java b/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java index 8c70bcc054c..3227865e193 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java @@ -25,13 +25,14 @@ /** * @author Gary Russell * @author Artem Bilan + * @author Glenn Renfro * * @since 4.0 * */ public class DefaultMessageBuilderFactory implements MessageBuilderFactory { - private String[] readOnlyHeaders; + private String @Nullable [] readOnlyHeaders; /** * Specify a list of headers which should be considered as a read only @@ -41,7 +42,7 @@ public class DefaultMessageBuilderFactory implements MessageBuilderFactory { * and {@link org.springframework.messaging.MessageHeaders#TIMESTAMP}. * @since 4.3.2 */ - public void setReadOnlyHeaders(@Nullable String... readOnlyHeaders) { + public void setReadOnlyHeaders(String @Nullable ... readOnlyHeaders) { this.readOnlyHeaders = readOnlyHeaders != null ? Arrays.copyOf(readOnlyHeaders, readOnlyHeaders.length) : null; } @@ -57,7 +58,7 @@ public void addReadOnlyHeaders(String... readOnlyHeaders) { } else { headers = Arrays.copyOf(headers, headers.length + readOnlyHeaders.length); - System.arraycopy(readOnlyHeaders, 0, headers, this.readOnlyHeaders.length, readOnlyHeaders.length); + System.arraycopy(readOnlyHeaders, 0, headers, (this.readOnlyHeaders != null) ? this.readOnlyHeaders.length : 0, readOnlyHeaders.length); } this.readOnlyHeaders = headers; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java b/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java index 7225451c14f..69c3afb76fe 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java @@ -45,6 +45,7 @@ * * @author Gary Russell * @author Artem Bilan + * @author Glenn Renfro * * @since 4.0 * @@ -80,9 +81,8 @@ public Map getHeaders() { } @SuppressWarnings("unchecked") - @Nullable @Override - public V getHeader(String key, Class type) { + public @Nullable V getHeader(String key, Class type) { Object value = this.headers.get(key); if (value == null) { return null; @@ -218,22 +218,22 @@ public AbstractIntegrationMessageBuilder copyHeadersIfAbsent(@Nullable Map> getSequenceDetails() { + protected @Nullable List> getSequenceDetails() { return (List>) this.headers.get(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS); } @Override - protected Object getCorrelationId() { + protected @Nullable Object getCorrelationId() { return this.headers.get(IntegrationMessageHeaderAccessor.CORRELATION_ID); } @Override - protected Object getSequenceNumber() { + protected @Nullable Object getSequenceNumber() { return this.headers.get(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER); } @Override - protected Object getSequenceSize() { + protected @Nullable Object getSequenceSize() { return this.headers.get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/NullAwarePayloadArgumentResolver.java b/spring-integration-core/src/main/java/org/springframework/integration/support/NullAwarePayloadArgumentResolver.java index a9504a0ce4d..89a88091c47 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/NullAwarePayloadArgumentResolver.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/NullAwarePayloadArgumentResolver.java @@ -16,6 +16,8 @@ package org.springframework.integration.support; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver; import org.springframework.validation.Validator; @@ -40,7 +42,8 @@ public NullAwarePayloadArgumentResolver(MessageConverter messageConverter, Valid } @Override - protected boolean isEmptyPayload(Object payload) { + @SuppressWarnings("NullAway") // Dataflow analysis limitation + protected boolean isEmptyPayload(@Nullable Object payload) { return super.isEmptyPayload(payload) || "KafkaNull".equals(payload.getClass().getSimpleName()); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/PartialSuccessException.java b/spring-integration-core/src/main/java/org/springframework/integration/support/PartialSuccessException.java index 464ccd73bbd..c5e102444cb 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/PartialSuccessException.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/PartialSuccessException.java @@ -28,6 +28,7 @@ * * @author Gary Russell * @author Artem Bilan + * @author Glenn Renfro * * @since 4.2 * @@ -97,7 +98,9 @@ public Collection getDerivedInput(Class clazz) { @Override public String toString() { - return "PartialSuccessException [" + getMessage() + ":" + getCause().getMessage() + Throwable cause = getCause(); + String causeMessage = (cause != null) ? cause.getMessage() : ""; + return "PartialSuccessException [" + getMessage() + ":" + causeMessage + ", partialResults=" + this.partialResults + ", derivedInput=" + this.derivedInput + ", failedMessage=" + getFailedMessage() + "]"; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/SmartLifecycleRoleController.java b/spring-integration-core/src/main/java/org/springframework/integration/support/SmartLifecycleRoleController.java index 66d724b9636..26a624a1b32 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/SmartLifecycleRoleController.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/SmartLifecycleRoleController.java @@ -56,6 +56,7 @@ * @author Artem Bilan * @author Christian Tzolov * @author Ngoc Nhan + * @author Glenn Renfro * * @since 4.2 * @@ -73,6 +74,7 @@ public class SmartLifecycleRoleController implements ApplicationListener lazyLifecycles = new LinkedMultiValueMap<>(); + @SuppressWarnings("NullAway.Init") private ApplicationContext applicationContext; /** diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java index 7df85179624..b9a865cf4d6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java @@ -28,6 +28,7 @@ import org.springframework.integration.support.MessageBuilderFactory; import org.springframework.integration.support.utils.IntegrationUtils; import org.springframework.messaging.Message; +import org.springframework.util.Assert; /** * Base {@link JsonInboundMessageMapper.JsonMessageParser} implementation for Jackson processors. @@ -44,10 +45,12 @@ abstract class AbstractJacksonJsonMessageParser

implements JsonInboundMessage private final JsonObjectMapper objectMapper; + @SuppressWarnings("NullAway.Init") private volatile JsonInboundMessageMapper messageMapper; private volatile MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory(); + @SuppressWarnings("NullAway.Init") private BeanFactory beanFactory; private volatile boolean messageBuilderFactorySet; @@ -82,6 +85,7 @@ public Message doInParser(JsonInboundMessageMapper messageMapperToUse, String if (messageMapperToUse.isMapToPayload()) { Object payload = readPayload(parser, jsonMessage); + Assert.state(payload != null, "No payload found in JSON message"); return getMessageBuilderFactory() .withPayload(payload) .copyHeaders(headers) @@ -92,7 +96,7 @@ public Message doInParser(JsonInboundMessageMapper messageMapperToUse, String } } - protected Object readPayload(P parser, String jsonMessage) { + protected @Nullable Object readPayload(P parser, String jsonMessage) { try { return this.objectMapper.fromJson(parser, this.messageMapper.getPayloadType()); } @@ -102,7 +106,7 @@ protected Object readPayload(P parser, String jsonMessage) { } } - protected Object readHeader(P parser, String headerName, String jsonMessage) { + protected @Nullable Object readHeader(P parser, String headerName, String jsonMessage) { Class headerType = this.messageMapper.getHeaderTypes().getOrDefault(headerName, Object.class); try { return this.objectMapper.fromJson(parser, (Type) headerType); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonObjectMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonObjectMapper.java index acb2d46b179..a75641fb023 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonObjectMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonObjectMapper.java @@ -26,6 +26,8 @@ import java.util.Collection; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.core.ResolvableType; import org.springframework.util.ClassUtils; @@ -38,6 +40,7 @@ * @param - The expected type of Java Type representation. * * @author Artem Bilan + * @author Glenn Renfro * * @since 3.0 */ @@ -46,14 +49,14 @@ public abstract class AbstractJacksonJsonObjectMapper implements JsonOb protected static final Collection> SUPPORTED_JSON_TYPES = Arrays.asList(String.class, byte[].class, File.class, URL.class, InputStream.class, Reader.class); - private volatile ClassLoader classLoader = ClassUtils.getDefaultClassLoader(); + private volatile @Nullable ClassLoader classLoader = ClassUtils.getDefaultClassLoader(); @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } - protected ClassLoader getClassLoader() { + protected @Nullable ClassLoader getClassLoader() { return this.classLoader; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJsonInboundMessageMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJsonInboundMessageMapper.java index 40eace01ebe..0dab53d97aa 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJsonInboundMessageMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJsonInboundMessageMapper.java @@ -20,6 +20,8 @@ import java.util.HashMap; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.mapping.InboundMessageMapper; import org.springframework.util.Assert; @@ -76,8 +78,8 @@ public boolean isMapToPayload() { return this.mapToPayload; } - protected abstract Object readPayload(P parser, String jsonMessage); + protected abstract @Nullable Object readPayload(P parser, String jsonMessage); - protected abstract Map readHeaders(P parser, String jsonMessage); + protected abstract @Nullable Map readHeaders(P parser, String jsonMessage); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonMessageParser.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonMessageParser.java index d206014e9b8..0ad468b459f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonMessageParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonMessageParser.java @@ -24,7 +24,6 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import org.jspecify.annotations.Nullable; import org.springframework.messaging.Message; import org.springframework.util.Assert; @@ -41,7 +40,7 @@ * @deprecated Since 7.0 in favor of {@link JacksonJsonMessageParser} for Jackson 3. */ @Deprecated(since = "7.0", forRemoval = true) -@SuppressWarnings("removal") +@SuppressWarnings({"removal", "NullAway"}) public class Jackson2JsonMessageParser extends AbstractJacksonJsonMessageParser { public Jackson2JsonMessageParser() { @@ -64,7 +63,7 @@ protected JsonParser createJsonParser(String jsonMessage) { @Override protected Message parseWithHeaders(JsonParser parser, String jsonMessage, - @Nullable Map headersToAdd) { + Map headersToAdd) { try { String error = AbstractJsonInboundMessageMapper.MESSAGE_FORMAT_ERROR + jsonMessage; @@ -87,7 +86,6 @@ protected Message parseWithHeaders(JsonParser parser, String jsonMessage, } } Assert.notNull(headers, error); - return getMessageBuilderFactory() .withPayload(payload) .copyHeaders(headers) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonObjectMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonObjectMapper.java index 9865b4e79d2..17990895452 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonObjectMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonObjectMapper.java @@ -63,6 +63,7 @@ * @deprecated Since 7.0 in favor of {@link JacksonJsonObjectMapper} for Jackson 3. */ @Deprecated(since = "7.0", forRemoval = true) +@SuppressWarnings("NullAway") public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper { private static final boolean JDK8_MODULE_PRESENT = @@ -161,7 +162,7 @@ else if (json instanceof Reader) { } else { throw new IllegalArgumentException("'json' argument must be an instance of: " + SUPPORTED_JSON_TYPES - + " , but gotten: " + json.getClass()); + + " , but gotten: " + ((json != null) ? json.getClass() : "null")); } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonMessageParser.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonMessageParser.java index aa67634f53d..0aa4ae22979 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonMessageParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonMessageParser.java @@ -79,7 +79,7 @@ protected Message parseWithHeaders(JsonParser parser, String jsonMessage, } } Assert.notNull(headers, error); - + Assert.notNull(payload, "Payload must not be null"); return getMessageBuilderFactory() .withPayload(payload) .copyHeaders(headers) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonUtils.java index 06d46bce933..9413283a377 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonUtils.java @@ -35,6 +35,7 @@ import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.module.SimpleModule; +import org.jspecify.annotations.Nullable; import org.springframework.integration.message.AdviceMessage; import org.springframework.integration.support.MutableMessage; @@ -130,9 +131,9 @@ private static final class AllowListTypeResolverBuilder extends ObjectMapper.Def @Serial private static final long serialVersionUID = 1L; - private final String[] trustedPackages; + private final String @Nullable [] trustedPackages; - AllowListTypeResolverBuilder(String... trustedPackages) { + AllowListTypeResolverBuilder(String @Nullable ... trustedPackages) { super(ObjectMapper.DefaultTyping.NON_FINAL, //we do explicit validation in the TypeIdResolver BasicPolymorphicTypeValidator.builder() @@ -172,7 +173,7 @@ private static final class AllowListTypeIdResolver implements TypeIdResolver { private final Set trustedPackages = new LinkedHashSet<>(DEFAULT_TRUSTED_PACKAGES); - AllowListTypeIdResolver(TypeIdResolver delegate, String... trustedPackages) { + AllowListTypeIdResolver(TypeIdResolver delegate, String @Nullable ... trustedPackages) { this.delegate = delegate; if (trustedPackages != null) { for (String trustedPackage : trustedPackages) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonInboundMessageMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonInboundMessageMapper.java index 77dc8718c6b..43b64828abf 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonInboundMessageMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonInboundMessageMapper.java @@ -67,13 +67,13 @@ public Message toMessage(String jsonMessage, @Nullable Map he } @Override - protected Map readHeaders(JsonMessageParser parser, String jsonMessage) { + protected @Nullable Map readHeaders(JsonMessageParser parser, String jsonMessage) { //No-op return null; } @Override - protected Object readPayload(JsonMessageParser parser, String jsonMessage) { + protected @Nullable Object readPayload(JsonMessageParser parser, String jsonMessage) { //No-op return null; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapper.java index b28c52445ff..0b8b1e609b6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapper.java @@ -22,6 +22,8 @@ import java.util.Collection; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.core.ResolvableType; import org.springframework.integration.mapping.support.JsonHeaders; @@ -32,12 +34,14 @@ * @param

- The expected type of JSON Parser. * * @author Artem Bilan + * @author Glenn Renfro * * @since 3.0 * */ public interface JsonObjectMapper { + @Nullable default String toJson(Object value) throws IOException { return null; } @@ -46,10 +50,12 @@ default void toJson(Object value, Writer writer) throws IOException { } + @Nullable default N toJsonNode(Object value) throws IOException { return null; } + @Nullable default T fromJson(Object json, Class valueType) throws IOException { return null; } @@ -63,14 +69,17 @@ default T fromJson(Object json, Class valueType) throws IOException { * @throws IOException a JSON parsing exception * @since 5.2 */ + @Nullable default T fromJson(Object json, ResolvableType valueType) throws IOException { return null; } + @Nullable default T fromJson(Object json, Map javaTypes) throws IOException { return null; } + @Nullable default T fromJson(P parser, Type valueType) throws IOException { return null; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonOutboundMessageMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonOutboundMessageMapper.java index 614dfae53e1..fd1e6908ec2 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonOutboundMessageMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonOutboundMessageMapper.java @@ -19,6 +19,8 @@ import java.io.IOException; import java.io.UncheckedIOException; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.mapping.OutboundMessageMapper; import org.springframework.messaging.Message; import org.springframework.util.Assert; @@ -56,7 +58,7 @@ public void setShouldExtractPayload(boolean shouldExtractPayload) { } @Override - public String fromMessage(Message message) { + public @Nullable String fromMessage(Message message) { try { return this.jsonObjectMapper.toJson(this.shouldExtractPayload ? message.getPayload() : message); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/package-info.java index b2e90eb8144..64bc490bafc 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting json. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.support.json; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/ControlBusCommandRegistry.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/ControlBusCommandRegistry.java index 0bf95c67fb9..e73829ba100 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/ControlBusCommandRegistry.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/ControlBusCommandRegistry.java @@ -55,6 +55,7 @@ * A global component to serve Control Bus command and respective SpEL expression relationships. * * @author Artem Bilan + * @author Glenn Renfro * * @since 6.4 * @@ -74,6 +75,7 @@ public class ControlBusCommandRegistry private boolean eagerInitialization; + @SuppressWarnings("NullAway.Init") private ApplicationContext applicationContext; private boolean initialized; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/metrics/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/metrics/package-info.java index 11cdf3e2dec..86ceb9656f4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/metrics/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/metrics/package-info.java @@ -1,4 +1,5 @@ /** * Provides interfaces related to 5.0 metrics. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.support.management.metrics; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptor.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptor.java index f69156a957c..12ed27264a9 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptor.java @@ -24,6 +24,7 @@ import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.ObjectProvider; import org.springframework.integration.support.management.metrics.CounterFacade; @@ -39,6 +40,7 @@ * * @author Gary Russell * @author Artem Bilan + * @author Glenn Renfro * * @since 5.0.4 * @@ -47,9 +49,9 @@ public class MicrometerMetricsCaptor implements MetricsCaptor { public static final String MICROMETER_CAPTOR_NAME = "integrationMicrometerMetricsCaptor"; - private MeterRegistry meterRegistry; + private @Nullable MeterRegistry meterRegistry; - private ObjectProvider meterRegistryProvider; + private @Nullable ObjectProvider meterRegistryProvider; public MicrometerMetricsCaptor(MeterRegistry meterRegistry) { Assert.notNull(meterRegistry, "meterRegistry cannot be null"); @@ -62,8 +64,11 @@ public MicrometerMetricsCaptor(MeterRegistry meterRegistry) { public MeterRegistry getMeterRegistry() { if (this.meterRegistry == null) { - this.meterRegistry = this.meterRegistryProvider.getIfUnique(); + if (this.meterRegistryProvider != null) { + this.meterRegistry = this.meterRegistryProvider.getIfUnique(); + } } + Assert.state(this.meterRegistry != null, "No MeterRegistry available"); return this.meterRegistry; } @@ -78,7 +83,7 @@ public CounterBuilder counterBuilder(String name) { } @Override - public GaugeBuilder gaugeBuilder(String name, Object obj, ToDoubleFunction f) { + public GaugeBuilder gaugeBuilder(String name, @Nullable Object obj, ToDoubleFunction f) { return new MicroGaugeBuilder(getMeterRegistry(), name, obj, f); } @@ -88,7 +93,7 @@ public SampleFacade start() { } @Override - public MeterFacade removeMeter(MeterFacade facade) { + public @Nullable MeterFacade removeMeter(MeterFacade facade) { return facade.remove(); } @@ -148,7 +153,7 @@ protected AbstractMeter(MeterRegistry meterRegistry) { @SuppressWarnings("unchecked") @Override - public T remove() { + public @Nullable T remove() { if (this.meterRegistry.remove(getMeter()) != null) { return (T) this; } @@ -263,7 +268,7 @@ protected static class MicroGaugeBuilder implements GaugeBuilder { private final Gauge.Builder builder; - protected MicroGaugeBuilder(MeterRegistry meterRegistry, String name, Object obj, ToDoubleFunction f) { + protected MicroGaugeBuilder(MeterRegistry meterRegistry, String name, @Nullable Object obj, ToDoubleFunction f) { this.meterRegistry = meterRegistry; this.builder = Gauge.builder(name, obj, f); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorConfiguration.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorConfiguration.java index fbce2ca07e9..312813aea21 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorConfiguration.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.integration.support.management.micrometer; import io.micrometer.core.instrument.MeterRegistry; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanDefinition; @@ -29,6 +30,7 @@ * A {@link Configuration} to add a {@link MicrometerMetricsCaptor}. * * @author Artem Bilan + * @author Glenn Renfro * * @since 5.2.9 */ @@ -45,7 +47,7 @@ public class MicrometerMetricsCaptorConfiguration { @Bean(name = MicrometerMetricsCaptor.MICROMETER_CAPTOR_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - public MicrometerMetricsCaptor micrometerMetricsCaptor(ObjectProvider meterRegistries) { + public @Nullable MicrometerMetricsCaptor micrometerMetricsCaptor(ObjectProvider meterRegistries) { if (meterRegistries.stream().findAny().isPresent()) { return new MicrometerMetricsCaptor(meterRegistries); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/package-info.java index 415da231894..462c0a542e8 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes to support the use of Micrometer for metrics. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.support.management.micrometer; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/observation/MessageSenderContext.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/observation/MessageSenderContext.java index 8ad95fa61ab..55b4f5857ad 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/observation/MessageSenderContext.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/observation/MessageSenderContext.java @@ -34,6 +34,7 @@ public class MessageSenderContext extends SenderContext> { private final String producerName; + @SuppressWarnings("NullAway") // Performance public MessageSenderContext(MutableMessage message, String producerName) { super((carrier, key, value) -> carrier.getHeaders().put(key, value)); this.message = message; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/observation/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/observation/package-info.java index e4db774be99..7c2ff3db599 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/observation/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/observation/package-info.java @@ -1,7 +1,5 @@ /** * Provides classes to support of Micrometer Observation API. */ - -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.integration.support.management.observation; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/support/package-info.java index 3cb065af442..faf58c684d3 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/package-info.java @@ -1,5 +1,5 @@ /** * Base core support package. */ -@org.springframework.lang.NonNullApi +@org.jspecify.annotations.NullMarked package org.springframework.integration.support; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ObjectToMapTransformer.java b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ObjectToMapTransformer.java index 7fbb6d1b156..8510412b967 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ObjectToMapTransformer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ObjectToMapTransformer.java @@ -105,11 +105,14 @@ public String getComponentType() { protected Map transformPayload(Object payload) { Map result; try { - result = this.jsonObjectMapper.fromJson(this.jsonObjectMapper.toJson(payload), Map.class); + var payloadValue = this.jsonObjectMapper.toJson(payload); + Assert.state(payloadValue != null, "'payload' must not be null"); + result = this.jsonObjectMapper.fromJson(payloadValue, Map.class); } catch (IOException e) { throw new UncheckedIOException(e); } + Assert.state(result != null, "The payload must not be null"); if (this.shouldFlattenKeys) { result = flattenMap(result); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java index dc58157b087..f8a438c649a 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java @@ -322,9 +322,11 @@ protected void onInit() { reply = sendAndReceiveMessage(message); } catch (MessageTimeoutException e) { + var errorMessage = e.getMessage(); + Assert.state(errorMessage != null, "MessageTimeoutException must have a message"); reply = getMessageBuilderFactory() - .withPayload(e.getMessage()) + .withPayload(errorMessage) .setHeader(HttpHeaders.STATUS_CODE, evaluateHttpStatus(httpEntity)) .build(); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/AbstractHttpRequestExecutingMessageHandler.java b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/AbstractHttpRequestExecutingMessageHandler.java index 8615912ecb5..a01c9d6174e 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/AbstractHttpRequestExecutingMessageHandler.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/AbstractHttpRequestExecutingMessageHandler.java @@ -335,6 +335,7 @@ protected Object handleRequestMessage(Message requestMessage) { protected abstract Object exchange(Object uri, HttpMethod httpMethod, HttpEntity httpRequest, Object expectedResponseType, Message requestMessage, Map uriVariables); + @SuppressWarnings("NullAway") protected Object getReply(ResponseEntity httpResponse) { HttpHeaders httpHeaders = httpResponse.getHeaders(); Map headers = this.headerMapper.toHeaders(httpHeaders); @@ -346,9 +347,9 @@ protected Object getReply(ResponseEntity httpResponse) { MessageBuilderFactory messageBuilderFactory = getMessageBuilderFactory(); if (httpResponse.hasBody() && this.extractResponseBody) { Object responseBody = httpResponse.getBody(); - replyBuilder = (responseBody instanceof Message) - ? messageBuilderFactory.fromMessage((Message) responseBody) - : messageBuilderFactory.withPayload(responseBody); // NOSONAR - hasBody() + replyBuilder = (responseBody instanceof Message messageResponseBody) + ? messageBuilderFactory.fromMessage(messageResponseBody) + : messageBuilderFactory.withPayload(responseBody); } else { replyBuilder = messageBuilderFactory.withPayload(httpResponse); diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/MapJsonSerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/MapJsonSerializer.java index 912761ceed8..f1c118f7965 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/MapJsonSerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/MapJsonSerializer.java @@ -91,7 +91,9 @@ public void setPacketSerializer(Serializer packetSerializer) { public Map deserialize(InputStream inputStream) throws IOException { byte[] bytes = this.packetDeserializer.deserialize(inputStream); try { - return this.jsonObjectMapper.fromJson(new InputStreamReader(new ByteArrayInputStream(bytes)), Map.class); + Map result = this.jsonObjectMapper.fromJson(new InputStreamReader(new ByteArrayInputStream(bytes)), Map.class); + Assert.state(result != null, "The deserialized Map must not be null"); + return result; } catch (Exception e) { throw new IOException(e); diff --git a/spring-integration-ws/src/main/java/org/springframework/integration/ws/MarshallingWebServiceInboundGateway.java b/spring-integration-ws/src/main/java/org/springframework/integration/ws/MarshallingWebServiceInboundGateway.java index b350d0a3d07..bce28784371 100644 --- a/spring-integration-ws/src/main/java/org/springframework/integration/ws/MarshallingWebServiceInboundGateway.java +++ b/spring-integration-ws/src/main/java/org/springframework/integration/ws/MarshallingWebServiceInboundGateway.java @@ -103,6 +103,7 @@ protected void doInvoke(MessageContext messageContext) throws IOException { WebServiceMessage request = messageContext.getRequest(); Assert.notNull(request, "Invalid message context: request was null."); Object requestObject = MarshallingUtils.unmarshal(this.unmarshaller, request); + Assert.state(requestObject != null, "Invalid message context: Request object was null"); AbstractIntegrationMessageBuilder builder = this.getMessageBuilderFactory().withPayload(requestObject); this.fromSoapHeaders(messageContext, builder); diff --git a/spring-integration-ws/src/main/java/org/springframework/integration/ws/SimpleWebServiceInboundGateway.java b/spring-integration-ws/src/main/java/org/springframework/integration/ws/SimpleWebServiceInboundGateway.java index c26f4ef2c3c..7caeb838dcf 100644 --- a/spring-integration-ws/src/main/java/org/springframework/integration/ws/SimpleWebServiceInboundGateway.java +++ b/spring-integration-ws/src/main/java/org/springframework/integration/ws/SimpleWebServiceInboundGateway.java @@ -49,6 +49,7 @@ public void setExtractPayload(boolean extractPayload) { } @Override + @SuppressWarnings("NullAway") // Dataflow analysis limitation protected void doInvoke(MessageContext messageContext) { WebServiceMessage request = messageContext.getRequest(); Assert.notNull(request, "Invalid message context: request was null.");