From 059df0ece211419fc8fc801d82c66f37bf150609 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Wed, 2 Jul 2025 15:54:16 -0400 Subject: [PATCH 1/5] Add JSpecify Nullability to the xml package * Tests were updated * Test XML files updated to handle non nullable attributes and parameters * In some cases I reformatted the whole xml file vs the changed section. If this is a problem I'll undo. * In many circumstances the chances of having null, should not happen, so `Objects.requireNonNull` was used. But wonder if we should use Assert.state and have a message. Thoughts? --- .../config/xml/CassandraParserUtils.java | 3 +- .../config/annotation/package-info.java | 1 + .../xml/AbstractChannelAdapterParser.java | 4 +- .../config/xml/AbstractChannelParser.java | 7 ++- .../xml/AbstractConsumerEndpointParser.java | 18 +++--- ...stractCorrelatingMessageHandlerParser.java | 3 +- ...tractDelegatingConsumerEndpointParser.java | 19 +++--- .../AbstractIntegrationNamespaceHandler.java | 3 +- .../AbstractOutboundChannelAdapterParser.java | 3 +- ...actPollingInboundChannelAdapterParser.java | 4 +- .../config/xml/AnnotationConfigParser.java | 7 ++- .../integration/config/xml/ChainParser.java | 10 ++-- .../config/xml/ChannelInterceptorParser.java | 5 +- .../config/xml/ConverterParser.java | 3 +- .../DefaultInboundChannelAdapterParser.java | 15 +++-- .../DefaultOutboundChannelAdapterParser.java | 2 +- .../integration/config/xml/GatewayParser.java | 22 +++---- .../xml/GlobalChannelInterceptorParser.java | 8 ++- .../config/xml/GlobalWireTapParser.java | 4 +- .../xml/HeaderEnricherParserSupport.java | 11 ++-- .../config/xml/IntegrationNamespaceUtils.java | 49 ++++++++------- .../config/xml/MessageHistoryParser.java | 4 +- .../config/xml/PointToPointChannelParser.java | 3 +- .../config/xml/ScatterGatherParser.java | 20 ++++--- .../xml/SpelPropertyAccessorsParser.java | 6 +- ...ansactionSynchronizationFactoryParser.java | 5 +- .../integration/config/xml/package-info.java | 1 + .../ResequencerIntegrationTests-context.xml | 8 ++- .../PartialSequencesWithGapsTests-context.xml | 8 ++- .../config/ChainParserTests-context.xml | 2 +- .../config/ResequencerParserTests-context.xml | 59 +++++++++++-------- ...cerWithMessageStoreParserTests-context.xml | 9 ++- .../xml/EndpointRoleParserTests-context.xml | 33 ++++++----- .../xml/OrderedHandlersTests-context.xml | 15 +++-- 34 files changed, 225 insertions(+), 149 deletions(-) diff --git a/spring-integration-cassandra/src/main/java/org/springframework/integration/cassandra/config/xml/CassandraParserUtils.java b/spring-integration-cassandra/src/main/java/org/springframework/integration/cassandra/config/xml/CassandraParserUtils.java index dcd315a8938..a5598e4fdc4 100644 --- a/spring-integration-cassandra/src/main/java/org/springframework/integration/cassandra/config/xml/CassandraParserUtils.java +++ b/spring-integration-cassandra/src/main/java/org/springframework/integration/cassandra/config/xml/CassandraParserUtils.java @@ -18,6 +18,7 @@ import java.util.List; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -91,7 +92,7 @@ public static void processOutboundTypeAttributes(Element element, ParserContext } - public static boolean areMutuallyExclusive(String query, BeanDefinition statementExpressionDef, + public static boolean areMutuallyExclusive(@Nullable String query, @Nullable BeanDefinition statementExpressionDef, String ingestQuery) { return !StringUtils.hasText(query) && statementExpressionDef == null && !StringUtils.hasText(ingestQuery) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/package-info.java index 34352df4f2e..9ec4b71e05f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting annotation-based configuration. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.config.annotation; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractChannelAdapterParser.java index 706d05ac0f2..3f29cf1f6e9 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractChannelAdapterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractChannelAdapterParser.java @@ -16,6 +16,7 @@ package org.springframework.integration.config.xml; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.MutablePropertyValues; @@ -62,6 +63,7 @@ else if (!StringUtils.hasText(id)) { } @Override + @SuppressWarnings("NullAway") protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { String channelName = element.getAttribute("channel"); if (!StringUtils.hasText(channelName)) { @@ -88,7 +90,7 @@ protected final AbstractBeanDefinition parseInternal(Element element, ParserCont return beanDefinition; } - private String createDirectChannel(Element element, ParserContext parserContext) { + private @Nullable String createDirectChannel(Element element, ParserContext parserContext) { if (parserContext.isNested()) { return null; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractChannelParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractChannelParser.java index 0c15e1ed2e9..2faa6b09140 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractChannelParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractChannelParser.java @@ -16,6 +16,9 @@ package org.springframework.integration.config.xml; +import java.util.Objects; + +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.aop.scope.ScopedProxyUtils; @@ -44,7 +47,7 @@ public abstract class AbstractChannelParser extends AbstractBeanDefinitionParser @Override protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = this.buildBeanDefinition(element, parserContext); - AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); + AbstractBeanDefinition beanDefinition = Objects.requireNonNull(builder).getBeanDefinition(); Element interceptorsElement = DomUtils.getChildElementByTagName(element, "interceptors"); String datatypeAttr = element.getAttribute("datatype"); String messageConverter = element.getAttribute("message-converter"); @@ -107,6 +110,6 @@ protected void registerBeanDefinition(BeanDefinitionHolder definition, BeanDefin * @param parserContext The parser context. * @return The bean definition builder. */ - protected abstract BeanDefinitionBuilder buildBeanDefinition(Element element, ParserContext parserContext); + protected abstract @Nullable BeanDefinitionBuilder buildBeanDefinition(Element element, ParserContext parserContext); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java index 84951138f88..b254a45cb66 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java @@ -18,7 +18,9 @@ import java.util.Collection; import java.util.List; +import java.util.Objects; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.factory.BeanDefinitionStoreException; @@ -78,16 +80,16 @@ protected String resolveId(Element element, AbstractBeanDefinition definition, P * @param parserContext The parser context. * @return The bean definition builder. */ - protected abstract BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext); + protected abstract @Nullable BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext); protected String getInputChannelAttributeName() { return "input-channel"; } @Override - protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + protected final @Nullable AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilder handlerBuilder = parseHandler(element, parserContext); - IntegrationNamespaceUtils.setValueIfAttributeDefined(handlerBuilder, element, "output-channel", + IntegrationNamespaceUtils.setValueIfAttributeDefined(Objects.requireNonNull(handlerBuilder), element, "output-channel", "outputChannelName"); IntegrationNamespaceUtils.setValueIfAttributeDefined(handlerBuilder, element, "order"); @@ -140,9 +142,9 @@ protected final AbstractBeanDefinition parseInternal(Element element, ParserCont String handlerBeanName = BeanDefinitionReaderUtils.generateBeanName(handlerBeanDefinition, parserContext.getRegistry()); - String[] handlerAlias = IntegrationNamespaceUtils.generateAlias(element); parserContext.registerBeanComponent( - new BeanComponentDefinition(handlerBeanDefinition, handlerBeanName, handlerAlias)); + new BeanComponentDefinition(handlerBeanDefinition, handlerBeanName, + IntegrationNamespaceUtils.generateAlias(element))); builder.addPropertyReference("handler", handlerBeanName); @@ -194,13 +196,11 @@ private void registerChannelForCreation(ParserContext parserContext, String inpu if (vh == null) { //although it should never happen if it does we can fix it caValues.addIndexedArgumentValue(0, new ManagedSet()); } - @SuppressWarnings("unchecked") Collection channelCandidateNames = - (Collection) caValues.getArgumentValue(0, Collection.class) + (Collection) Objects.requireNonNull(caValues.getArgumentValue(0, Collection.class)) .getValue(); // NOSONAR see comment above - channelCandidateNames.add(inputChannelName); // NOSONAR - + Objects.requireNonNull(channelCandidateNames).add(inputChannelName); // NOSONAR consumerEndpointBuilder.addDependsOn(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME); } else { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractCorrelatingMessageHandlerParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractCorrelatingMessageHandlerParser.java index 999c58daec4..13daeb27e9c 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractCorrelatingMessageHandlerParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractCorrelatingMessageHandlerParser.java @@ -16,6 +16,7 @@ package org.springframework.integration.config.xml; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.BeanMetadataElement; @@ -65,7 +66,7 @@ public abstract class AbstractCorrelatingMessageHandlerParser extends AbstractCo private static final String RELEASE_LOCK = "release-lock-before-send"; - protected void doParse(BeanDefinitionBuilder builder, Element element, BeanMetadataElement processor, + protected void doParse(BeanDefinitionBuilder builder, Element element, @Nullable BeanMetadataElement processor, ParserContext parserContext) { IntegrationNamespaceUtils.injectPropertyWithAdapter(CORRELATION_STRATEGY_REF_ATTRIBUTE, CORRELATION_STRATEGY_METHOD_ATTRIBUTE, diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractDelegatingConsumerEndpointParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractDelegatingConsumerEndpointParser.java index ab4c36557fa..85d9334fe6a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractDelegatingConsumerEndpointParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractDelegatingConsumerEndpointParser.java @@ -16,6 +16,7 @@ package org.springframework.integration.config.xml; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -39,7 +40,7 @@ abstract class AbstractDelegatingConsumerEndpointParser extends AbstractConsumerEndpointParser { @Override - protected final BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { + protected final @Nullable BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getFactoryBeanClassName()); BeanComponentDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, @@ -87,9 +88,9 @@ else if (!this.hasDefaultOption()) { return builder; } - private void innerDefinition(Element element, ParserContext parserContext, Object source, + private void innerDefinition(Element element, ParserContext parserContext, @Nullable Object source, BeanDefinitionBuilder builder, BeanComponentDefinition innerDefinition, boolean hasRef, - boolean hasExpression, Element expressionElement) { + boolean hasExpression, @Nullable Element expressionElement) { if (hasRef || hasExpression || expressionElement != null) { parserContext.getReaderContext().error( "Neither 'ref' nor 'expression' are permitted when an inner bean () is configured on element " + @@ -98,9 +99,9 @@ private void innerDefinition(Element element, ParserContext parserContext, Objec builder.addPropertyValue("targetObject", innerDefinition); } - private void scriptElement(Element element, ParserContext parserContext, Object source, + private void scriptElement(Element element, ParserContext parserContext, @Nullable Object source, BeanDefinitionBuilder builder, boolean hasRef, boolean hasExpression, Element scriptElement, - Element expressionElement) { + @Nullable Element expressionElement) { if (hasRef || hasExpression || expressionElement != null) { parserContext.getReaderContext().error( "Neither 'ref' nor 'expression' are permitted when an inner script element is configured on element " + @@ -110,7 +111,7 @@ private void scriptElement(Element element, ParserContext parserContext, Object builder.addPropertyValue("targetObject", scriptBeanDefinition); } - private void expressionElement(Element element, ParserContext parserContext, Object source, + private void expressionElement(Element element, ParserContext parserContext, @Nullable Object source, BeanDefinitionBuilder builder, boolean hasRef, boolean hasExpression, Element expressionElement) { if (hasRef || hasExpression) { parserContext.getReaderContext().error( @@ -126,9 +127,9 @@ private void expressionElement(Element element, ParserContext parserContext, Obj builder.addPropertyValue("expression", dynamicExpressionBuilder.getBeanDefinition()); } - private void methodAttribute(Element element, ParserContext parserContext, Object source, - BeanDefinitionBuilder builder, BeanComponentDefinition innerDefinition, boolean hasRef, - boolean hasExpression, Element expressionElement) { + private void methodAttribute(Element element, ParserContext parserContext, @Nullable Object source, + BeanDefinitionBuilder builder, @Nullable BeanComponentDefinition innerDefinition, boolean hasRef, + boolean hasExpression, @Nullable Element expressionElement) { String method = element.getAttribute(METHOD_ATTRIBUTE); if (StringUtils.hasText(method)) { if (hasExpression || expressionElement != null) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractIntegrationNamespaceHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractIntegrationNamespaceHandler.java index e3f11a8b140..83b7f2c520f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractIntegrationNamespaceHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractIntegrationNamespaceHandler.java @@ -18,6 +18,7 @@ import java.util.concurrent.atomic.AtomicBoolean; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -47,7 +48,7 @@ public abstract class AbstractIntegrationNamespaceHandler extends NamespaceHandl private final AtomicBoolean initialized = new AtomicBoolean(); @Override - public final BeanDefinition parse(Element element, ParserContext parserContext) { + public final @Nullable BeanDefinition parse(Element element, ParserContext parserContext) { if (!this.initialized.getAndSet(true)) { BeanDefinitionRegistry registry = parserContext.getRegistry(); new IntegrationRegistrar().registerBeanDefinitions(null, registry); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java index 096a887c5df..c02d5006260 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java @@ -16,6 +16,7 @@ package org.springframework.integration.config.xml; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -82,7 +83,7 @@ protected AbstractBeanDefinition doParse(Element element, ParserContext parserCo } private void configureRequestHandlerAdviceChain(Element element, ParserContext parserContext, - BeanDefinition handlerBeanDefinition, BeanDefinitionBuilder consumerBuilder) { + BeanDefinition handlerBeanDefinition, @Nullable BeanDefinitionBuilder consumerBuilder) { Element txElement = DomUtils.getChildElementByTagName(element, "transactional"); Element adviceChainElement = DomUtils.getChildElementByTagName(element, IntegrationNamespaceUtils.REQUEST_HANDLER_ADVICE_CHAIN); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractPollingInboundChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractPollingInboundChannelAdapterParser.java index 9e5346662d3..d38ff9b7fa5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractPollingInboundChannelAdapterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractPollingInboundChannelAdapterParser.java @@ -16,6 +16,7 @@ package org.springframework.integration.config.xml; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.BeanMetadataElement; @@ -59,6 +60,7 @@ else if (source instanceof RuntimeBeanReference runtimeBeanReference) { } else { parserContext.getReaderContext().error("Wrong 'source' type: must be 'BeanDefinition' or 'RuntimeBeanReference'", source); + throw new IllegalStateException("sourceBeanName must not be null"); } adapterBuilder.addPropertyReference("source", sourceBeanName); @@ -79,6 +81,6 @@ else if (source instanceof RuntimeBeanReference runtimeBeanReference) { * @param parserContext The parser context. * @return The bean metadata element. */ - protected abstract BeanMetadataElement parseSource(Element element, ParserContext parserContext); + protected abstract @Nullable BeanMetadataElement parseSource(Element element, ParserContext parserContext); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AnnotationConfigParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AnnotationConfigParser.java index acb88f5b670..3bd882b2b73 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AnnotationConfigParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AnnotationConfigParser.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Set; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -46,7 +47,7 @@ public class AnnotationConfigParser implements BeanDefinitionParser { @Override - public BeanDefinition parse(Element element, ParserContext parserContext) { + public @Nullable BeanDefinition parse(Element element, ParserContext parserContext) { ExtendedAnnotationMetadata importingClassMetadata = new ExtendedAnnotationMetadata(element); BeanDefinitionRegistry registry = parserContext.getRegistry(); new IntegrationRegistrar() @@ -67,11 +68,11 @@ private static final class ExtendedAnnotationMetadata extends AnnotationMetadata } @Override - public Map getAnnotationAttributes(String annotationType) { + public @Nullable Map getAnnotationAttributes(String annotationType) { if (EnablePublisher.class.getName().equals(annotationType)) { Element enablePublisherElement = DomUtils.getChildElementByTagName(this.element, "enable-publisher"); if (enablePublisherElement != null) { - Map attributes = new HashMap<>(); + Map attributes = new HashMap<>(); attributes.put("defaultChannel", enablePublisherElement.getAttribute("default-publisher-channel")); attributes.put("proxyTargetClass", enablePublisherElement.getAttribute("proxy-target-class")); attributes.put("order", enablePublisherElement.getAttribute("order")); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ChainParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ChainParser.java index 2e1f4d45611..e2c831768f2 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ChainParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ChainParser.java @@ -18,10 +18,12 @@ import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -65,7 +67,7 @@ public class ChainParser extends AbstractConsumerEndpointParser { private final Log logger = LogFactory.getLog(this.getClass()); @Override - protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { + protected @Nullable BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MessageHandlerChain.class); if (!StringUtils.hasText(element.getAttribute(ID_ATTRIBUTE))) { @@ -100,7 +102,7 @@ protected BeanDefinitionBuilder parseHandler(Element element, ParserContext pars handlerList.add(gwBuilder.getBeanDefinition()); } else { - handlerList.add(childBeanMetadata); + handlerList.add(Objects.requireNonNull(childBeanMetadata)); } } } @@ -123,7 +125,7 @@ protected String resolveId(Element element, AbstractBeanDefinition definition, P return id; } - private BeanMetadataElement parseChild(String chainHandlerId, Element element, int order, ParserContext parserContext, + private @Nullable BeanMetadataElement parseChild(String chainHandlerId, Element element, int order, ParserContext parserContext, BeanDefinition parentDefinition) { BeanDefinitionHolder holder = null; @@ -149,7 +151,7 @@ private BeanMetadataElement parseChild(String chainHandlerId, Element element, i } } - holder.getBeanDefinition().getPropertyValues().add("componentName", handlerComponentName); // NOSONAR never null + Objects.requireNonNull(holder).getBeanDefinition().getPropertyValues().add("componentName", handlerComponentName); // NOSONAR never null if (hasId) { BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ChannelInterceptorParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ChannelInterceptorParser.java index 41809508a03..fa55fb80293 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ChannelInterceptorParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ChannelInterceptorParser.java @@ -18,6 +18,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Objects; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -29,6 +30,7 @@ import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.Assert; /** * A helper class for parsing the sub-elements of a channel's @@ -60,7 +62,7 @@ public ManagedList parseInterceptors(Element element, ParserContext parserContex if ("bean".equals(localName)) { BeanDefinitionParserDelegate delegate = parserContext.getDelegate(); BeanDefinitionHolder holder = delegate.parseBeanDefinitionElement(childElement); - holder = delegate.decorateBeanDefinitionIfRequired(childElement, holder); // NOSONAR never null + holder = delegate.decorateBeanDefinitionIfRequired(childElement, Objects.requireNonNull(holder)); parserContext.registerBeanComponent(new BeanComponentDefinition(holder)); interceptors.add(new RuntimeBeanReference(holder.getBeanName())); } @@ -74,6 +76,7 @@ else if ("ref".equals(localName)) { parserContext.getReaderContext().error( "unsupported interceptor element '" + localName + "'", childElement); } + Assert.state(parser != null, "no parser registered for '" + localName + "'"); String interceptorBeanName = parser.parse(childElement, parserContext); interceptors.add(new RuntimeBeanReference(interceptorBeanName)); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ConverterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ConverterParser.java index bd4ca8b4919..71c76aa9206 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ConverterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ConverterParser.java @@ -16,6 +16,7 @@ package org.springframework.integration.config.xml; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.BeanMetadataElement; @@ -41,7 +42,7 @@ public class ConverterParser extends AbstractBeanDefinitionParser { @Override - protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + protected @Nullable AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionRegistry registry = parserContext.getRegistry(); BeanComponentDefinition converterDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultInboundChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultInboundChannelAdapterParser.java index 0b5fa05c649..bf8402384d6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultInboundChannelAdapterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultInboundChannelAdapterParser.java @@ -17,7 +17,9 @@ package org.springframework.integration.config.xml; import java.util.List; +import java.util.Objects; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.BeanMetadataElement; @@ -33,6 +35,7 @@ import org.springframework.integration.endpoint.ExpressionEvaluatingMessageSource; import org.springframework.integration.endpoint.MethodInvokingMessageSource; import org.springframework.integration.expression.DynamicExpression; +import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; @@ -46,8 +49,8 @@ */ public class DefaultInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser { - @Override // NOSONAR complexity - protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) { // NOSONAR + @Override + protected @Nullable BeanMetadataElement parseSource(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); BeanMetadataElement result = null; BeanComponentDefinition innerBeanDef = @@ -65,7 +68,7 @@ protected BeanMetadataElement parseSource(Element element, ParserContext parserC boolean hasExpressionElement = expressionElement != null; boolean hasMethod = StringUtils.hasText(methodName); - if (!hasInnerDef && !hasRef && !hasExpression && !hasScriptElement && !hasExpressionElement) { // NOSONAR + if (!hasInnerDef && !hasRef && !hasExpression && !hasScriptElement && !hasExpressionElement) { parserContext.getReaderContext().error( "Exactly one of the 'ref', 'expression', inner bean,