diff --git a/spring-ws-core/src/main/java/org/springframework/ws/FaultAwareWebServiceMessage.java b/spring-ws-core/src/main/java/org/springframework/ws/FaultAwareWebServiceMessage.java index bbea7534..0c909beb 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/FaultAwareWebServiceMessage.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/FaultAwareWebServiceMessage.java @@ -18,6 +18,8 @@ package org.springframework.ws; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + /** * Sub-interface of {@link WebServiceMessage} that can contain special Fault messages. * Fault messages (such as {@link org.springframework.ws.soap.SoapFault} SOAP Faults) @@ -39,7 +41,7 @@ public interface FaultAwareWebServiceMessage extends WebServiceMessage { /** * Returns the fault code, if any. */ - QName getFaultCode(); + @Nullable QName getFaultCode(); /** * Returns the fault reason message. @@ -47,6 +49,6 @@ public interface FaultAwareWebServiceMessage extends WebServiceMessage { * present. * @see #hasFault() */ - String getFaultReason(); + @Nullable String getFaultReason(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/WebServiceException.java b/spring-ws-core/src/main/java/org/springframework/ws/WebServiceException.java index 33d432db..c32f460f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/WebServiceException.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/WebServiceException.java @@ -16,6 +16,8 @@ package org.springframework.ws; +import org.jspecify.annotations.Nullable; + import org.springframework.core.NestedRuntimeException; /** @@ -31,7 +33,7 @@ public abstract class WebServiceException extends NestedRuntimeException { * Create a new instance of the {@code WebServiceException} class. * @param msg the detail message */ - public WebServiceException(String msg) { + public WebServiceException(@Nullable String msg) { super(msg); } @@ -40,7 +42,7 @@ public abstract class WebServiceException extends NestedRuntimeException { * @param msg the detail message * @param ex the root {@link Throwable exception} */ - public WebServiceException(String msg, Throwable ex) { + public WebServiceException(@Nullable String msg, Throwable ex) { super(msg, ex); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/WebServiceMessage.java b/spring-ws-core/src/main/java/org/springframework/ws/WebServiceMessage.java index c575ee52..f8985867 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/WebServiceMessage.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/WebServiceMessage.java @@ -22,6 +22,8 @@ import java.io.OutputStream; import javax.xml.transform.Result; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + /** * Represents a protocol-agnostic XML message. *

@@ -41,7 +43,7 @@ public interface WebServiceMessage { * single time. * @return the message contents */ - Source getPayloadSource(); + @Nullable Source getPayloadSource(); /** * Returns the contents of the message as a {@link Result}. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceClientException.java b/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceClientException.java index 39a77bf5..dca9ea87 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceClientException.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceClientException.java @@ -16,6 +16,8 @@ package org.springframework.ws.client; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceException; /** @@ -31,7 +33,7 @@ public abstract class WebServiceClientException extends WebServiceException { * Create a new instance of the {@code WebServiceClientException} class. * @param msg the detail message */ - public WebServiceClientException(String msg) { + public WebServiceClientException(@Nullable String msg) { super(msg); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceFaultException.java b/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceFaultException.java index dcd14ed8..b079d345 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceFaultException.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceFaultException.java @@ -16,6 +16,8 @@ package org.springframework.ws.client; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.FaultAwareWebServiceMessage; /** @@ -27,7 +29,7 @@ import org.springframework.ws.FaultAwareWebServiceMessage; @SuppressWarnings("serial") public class WebServiceFaultException extends WebServiceClientException { - private final FaultAwareWebServiceMessage faultMessage; + private final @Nullable FaultAwareWebServiceMessage faultMessage; /** Create a new instance of the {@code WebServiceFaultException} class. */ public WebServiceFaultException(String msg) { @@ -45,7 +47,7 @@ public class WebServiceFaultException extends WebServiceClientException { } /** Returns the fault message. */ - public FaultAwareWebServiceMessage getWebServiceMessage() { + public @Nullable FaultAwareWebServiceMessage getWebServiceMessage() { return this.faultMessage; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceIOException.java b/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceIOException.java index 5003d62e..eb29d66e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceIOException.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceIOException.java @@ -18,6 +18,8 @@ package org.springframework.ws.client; import java.io.IOException; +import org.jspecify.annotations.Nullable; + /** * Exception thrown whenever an I/O error occurs on the client-side. * @@ -31,7 +33,7 @@ public class WebServiceIOException extends WebServiceClientException { * Create a new instance of the {@code WebServiceIOException} class. * @param msg the detail message */ - public WebServiceIOException(String msg) { + public WebServiceIOException(@Nullable String msg) { super(msg); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceTransportException.java b/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceTransportException.java index 891d95de..297760aa 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceTransportException.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/WebServiceTransportException.java @@ -16,6 +16,8 @@ package org.springframework.ws.client; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.transport.TransportException; /** @@ -31,7 +33,7 @@ public class WebServiceTransportException extends WebServiceIOException { * Create a new instance of the {@code WebServiceTransportException} class. * @param msg the detail message */ - public WebServiceTransportException(String msg) { + public WebServiceTransportException(@Nullable String msg) { super(msg); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/core/SourceExtractor.java b/spring-ws-core/src/main/java/org/springframework/ws/client/core/SourceExtractor.java index 9a6f4cc3..0c18fa9b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/core/SourceExtractor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/core/SourceExtractor.java @@ -21,6 +21,8 @@ import java.io.IOException; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; +import org.jspecify.annotations.Nullable; + /** * Callback interface for extracting a result object from a * {@link javax.xml.transform.Source} instance. @@ -49,6 +51,6 @@ public interface SourceExtractor { * typically be stateful in the latter case) * @throws IOException in case of I/O errors */ - T extractData(Source source) throws IOException, TransformerException; + @Nullable T extractData(@Nullable Source source) throws IOException, TransformerException; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceMessageExtractor.java b/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceMessageExtractor.java index 2a70f452..1a7feee1 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceMessageExtractor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceMessageExtractor.java @@ -20,6 +20,8 @@ import java.io.IOException; import javax.xml.transform.TransformerException; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; /** @@ -50,6 +52,6 @@ public interface WebServiceMessageExtractor { * @throws IOException in case of I/O errors * @throws TransformerException in case of transformation errors */ - T extractData(WebServiceMessage message) throws IOException, TransformerException; + @Nullable T extractData(WebServiceMessage message) throws IOException, TransformerException; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceOperations.java b/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceOperations.java index bb51dcf2..946a16a3 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceOperations.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceOperations.java @@ -19,6 +19,8 @@ package org.springframework.ws.client.core; import javax.xml.transform.Result; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.oxm.XmlMappingException; import org.springframework.ws.client.WebServiceClientException; @@ -46,8 +48,8 @@ public interface WebServiceOperations { * @throws WebServiceClientException if there is a problem sending or receiving the * message */ - T sendAndReceive(WebServiceMessageCallback requestCallback, WebServiceMessageExtractor responseExtractor) - throws WebServiceClientException; + @Nullable T sendAndReceive(WebServiceMessageCallback requestCallback, + WebServiceMessageExtractor responseExtractor) throws WebServiceClientException; /** * Sends a web service message that can be manipulated with the given callback, @@ -61,7 +63,7 @@ public interface WebServiceOperations { * @throws WebServiceClientException if there is a problem sending or receiving the * message */ - T sendAndReceive(String uri, WebServiceMessageCallback requestCallback, + @Nullable T sendAndReceive(String uri, WebServiceMessageCallback requestCallback, WebServiceMessageExtractor responseExtractor) throws WebServiceClientException; /** @@ -112,7 +114,7 @@ public interface WebServiceOperations { * @see WebServiceTemplate#setMarshaller(org.springframework.oxm.Marshaller) * @see WebServiceTemplate#setUnmarshaller(org.springframework.oxm.Unmarshaller) */ - Object marshalSendAndReceive(Object requestPayload) throws XmlMappingException, WebServiceClientException; + @Nullable Object marshalSendAndReceive(Object requestPayload) throws XmlMappingException, WebServiceClientException; /** * Sends a web service message that contains the given payload, marshalled by the @@ -128,7 +130,7 @@ public interface WebServiceOperations { * @see WebServiceTemplate#setMarshaller(org.springframework.oxm.Marshaller) * @see WebServiceTemplate#setUnmarshaller(org.springframework.oxm.Unmarshaller) */ - Object marshalSendAndReceive(String uri, Object requestPayload) + @Nullable Object marshalSendAndReceive(String uri, Object requestPayload) throws XmlMappingException, WebServiceClientException; /** @@ -148,7 +150,7 @@ public interface WebServiceOperations { * @see WebServiceTemplate#setMarshaller(org.springframework.oxm.Marshaller) * @see WebServiceTemplate#setUnmarshaller(org.springframework.oxm.Unmarshaller) */ - Object marshalSendAndReceive(Object requestPayload, WebServiceMessageCallback requestCallback) + @Nullable Object marshalSendAndReceive(Object requestPayload, @Nullable WebServiceMessageCallback requestCallback) throws XmlMappingException, WebServiceClientException; /** @@ -167,8 +169,8 @@ public interface WebServiceOperations { * @see WebServiceTemplate#setMarshaller(org.springframework.oxm.Marshaller) * @see WebServiceTemplate#setUnmarshaller(org.springframework.oxm.Unmarshaller) */ - Object marshalSendAndReceive(String uri, Object requestPayload, WebServiceMessageCallback requestCallback) - throws XmlMappingException, WebServiceClientException; + @Nullable Object marshalSendAndReceive(String uri, @Nullable Object requestPayload, + @Nullable WebServiceMessageCallback requestCallback) throws XmlMappingException, WebServiceClientException; // ----------------------------------------------------------------------------------------------------------------- // Convenience methods for sending Sources @@ -185,7 +187,7 @@ public interface WebServiceOperations { * @throws WebServiceClientException if there is a problem sending or receiving the * message */ - T sendSourceAndReceive(Source requestPayload, SourceExtractor responseExtractor) + @Nullable T sendSourceAndReceive(Source requestPayload, SourceExtractor responseExtractor) throws WebServiceClientException; /** @@ -198,7 +200,7 @@ public interface WebServiceOperations { * @throws WebServiceClientException if there is a problem sending or receiving the * message */ - T sendSourceAndReceive(String uri, Source requestPayload, SourceExtractor responseExtractor) + @Nullable T sendSourceAndReceive(String uri, Source requestPayload, SourceExtractor responseExtractor) throws WebServiceClientException; /** @@ -216,7 +218,7 @@ public interface WebServiceOperations { * @throws WebServiceClientException if there is a problem sending or receiving the * message */ - T sendSourceAndReceive(Source requestPayload, WebServiceMessageCallback requestCallback, + @Nullable T sendSourceAndReceive(Source requestPayload, WebServiceMessageCallback requestCallback, SourceExtractor responseExtractor) throws WebServiceClientException; /** @@ -233,8 +235,9 @@ public interface WebServiceOperations { * @throws WebServiceClientException if there is a problem sending or receiving the * message */ - T sendSourceAndReceive(String uri, Source requestPayload, WebServiceMessageCallback requestCallback, - SourceExtractor responseExtractor) throws WebServiceClientException; + @Nullable T sendSourceAndReceive(String uri, Source requestPayload, + @Nullable WebServiceMessageCallback requestCallback, SourceExtractor responseExtractor) + throws WebServiceClientException; // ----------------------------------------------------------------------------------------------------------------- // Convenience methods for sending Sources and receiving to Results diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java b/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java index 29c0f996..cb4928c1 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java @@ -30,6 +30,7 @@ import javax.xml.transform.TransformerException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.oxm.Marshaller; @@ -133,19 +134,19 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService protected static final Log receivedMessageTracingLogger = LogFactory .getLog(WebServiceTemplate.MESSAGE_TRACING_LOG_CATEGORY + ".received"); - private Marshaller marshaller; + private @Nullable Marshaller marshaller; - private Unmarshaller unmarshaller; + private @Nullable Unmarshaller unmarshaller; - private FaultMessageResolver faultMessageResolver; + private @Nullable FaultMessageResolver faultMessageResolver; private boolean checkConnectionForError = true; private boolean checkConnectionForFault = true; - private ClientInterceptor[] interceptors; + private ClientInterceptor @Nullable [] interceptors; - private DestinationProvider destinationProvider; + private @Nullable DestinationProvider destinationProvider; /** Creates a new {@code WebServiceTemplate} using default settings. */ public WebServiceTemplate() { @@ -205,7 +206,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService /** * Returns the default URI to be used on operations that do not have a URI parameter. */ - public String getDefaultUri() { + public @Nullable String getDefaultUri() { if (this.destinationProvider != null) { URI uri = this.destinationProvider.getDestination(); return (uri != null) ? uri.toString() : null; @@ -241,7 +242,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * Returns the destination provider used on operations that do not have a URI * parameter. */ - public DestinationProvider getDestinationProvider() { + public @Nullable DestinationProvider getDestinationProvider() { return this.destinationProvider; } @@ -264,7 +265,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } /** Returns the marshaller for this template. */ - public Marshaller getMarshaller() { + public @Nullable Marshaller getMarshaller() { return this.marshaller; } @@ -274,7 +275,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } /** Returns the unmarshaller for this template. */ - public Unmarshaller getUnmarshaller() { + public @Nullable Unmarshaller getUnmarshaller() { return this.unmarshaller; } @@ -284,7 +285,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } /** Returns the fault message resolver for this template. */ - public FaultMessageResolver getFaultMessageResolver() { + public @Nullable FaultMessageResolver getFaultMessageResolver() { return this.faultMessageResolver; } @@ -346,7 +347,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * this template. * @return array of endpoint interceptors, or {@code null} if none */ - public ClientInterceptor[] getInterceptors() { + public ClientInterceptor @Nullable [] getInterceptors() { return this.interceptors; } @@ -402,23 +403,26 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService // @Override - public Object marshalSendAndReceive(final Object requestPayload) { + public @Nullable Object marshalSendAndReceive(final Object requestPayload) { return marshalSendAndReceive(requestPayload, null); } @Override - public Object marshalSendAndReceive(String uri, final Object requestPayload) { + public @Nullable Object marshalSendAndReceive(String uri, final Object requestPayload) { return marshalSendAndReceive(uri, requestPayload, null); } @Override - public Object marshalSendAndReceive(final Object requestPayload, final WebServiceMessageCallback requestCallback) { - return marshalSendAndReceive(getDefaultUri(), requestPayload, requestCallback); + public @Nullable Object marshalSendAndReceive(final Object requestPayload, + final @Nullable WebServiceMessageCallback requestCallback) { + String defaultUri = getDefaultUri(); + Assert.notNull(defaultUri, "'defaultUri' must not be null"); + return marshalSendAndReceive(defaultUri, requestPayload, requestCallback); } @Override - public Object marshalSendAndReceive(String uri, final Object requestPayload, - final WebServiceMessageCallback requestCallback) { + public @Nullable Object marshalSendAndReceive(String uri, final @Nullable Object requestPayload, + final @Nullable WebServiceMessageCallback requestCallback) { return sendAndReceive(uri, new WebServiceMessageCallback() { public void doWithMessage(WebServiceMessage request) throws IOException, TransformerException { @@ -436,7 +440,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } }, new WebServiceMessageExtractor<>() { - public Object extractData(WebServiceMessage response) throws IOException { + public @Nullable Object extractData(WebServiceMessage response) throws IOException { Unmarshaller unmarshaller = getUnmarshaller(); if (unmarshaller == null) { throw new IllegalStateException( @@ -462,20 +466,22 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } @Override - public boolean sendSourceAndReceiveToResult(Source requestPayload, WebServiceMessageCallback requestCallback, - final Result responseResult) { - return sendSourceAndReceiveToResult(getDefaultUri(), requestPayload, requestCallback, responseResult); + public boolean sendSourceAndReceiveToResult(Source requestPayload, + @Nullable WebServiceMessageCallback requestCallback, final Result responseResult) { + String defaultUri = getDefaultUri(); + Assert.notNull(defaultUri, "'defaultUri' must not be null"); + return sendSourceAndReceiveToResult(defaultUri, requestPayload, requestCallback, responseResult); } @Override public boolean sendSourceAndReceiveToResult(String uri, Source requestPayload, - WebServiceMessageCallback requestCallback, final Result responseResult) { + @Nullable WebServiceMessageCallback requestCallback, final Result responseResult) { try { final Transformer transformer = createTransformer(); Boolean retVal = doSendAndReceive(uri, transformer, requestPayload, requestCallback, new SourceExtractor<>() { - public Boolean extractData(Source source) throws IOException, TransformerException { + public Boolean extractData(@Nullable Source source) throws IOException, TransformerException { if (source != null) { transformer.transform(source, responseResult); } @@ -494,25 +500,28 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService // @Override - public T sendSourceAndReceive(final Source requestPayload, final SourceExtractor responseExtractor) { + public @Nullable T sendSourceAndReceive(final Source requestPayload, + final SourceExtractor responseExtractor) { return sendSourceAndReceive(requestPayload, null, responseExtractor); } @Override - public T sendSourceAndReceive(String uri, final Source requestPayload, + public @Nullable T sendSourceAndReceive(String uri, final Source requestPayload, final SourceExtractor responseExtractor) { return sendSourceAndReceive(uri, requestPayload, null, responseExtractor); } @Override - public T sendSourceAndReceive(final Source requestPayload, final WebServiceMessageCallback requestCallback, - final SourceExtractor responseExtractor) { - return sendSourceAndReceive(getDefaultUri(), requestPayload, requestCallback, responseExtractor); + public @Nullable T sendSourceAndReceive(final Source requestPayload, + final @Nullable WebServiceMessageCallback requestCallback, final SourceExtractor responseExtractor) { + String defaultUri = getDefaultUri(); + Assert.notNull(defaultUri, "'defaultUri' must not be null"); + return sendSourceAndReceive(defaultUri, requestPayload, requestCallback, responseExtractor); } @Override - public T sendSourceAndReceive(String uri, final Source requestPayload, - final WebServiceMessageCallback requestCallback, final SourceExtractor responseExtractor) { + public @Nullable T sendSourceAndReceive(String uri, final Source requestPayload, + final @Nullable WebServiceMessageCallback requestCallback, final SourceExtractor responseExtractor) { try { return doSendAndReceive(uri, createTransformer(), requestPayload, requestCallback, responseExtractor); @@ -522,8 +531,8 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } } - private T doSendAndReceive(String uri, final Transformer transformer, final Source requestPayload, - final WebServiceMessageCallback requestCallback, final SourceExtractor responseExtractor) { + private @Nullable T doSendAndReceive(String uri, final Transformer transformer, final Source requestPayload, + final @Nullable WebServiceMessageCallback requestCallback, final SourceExtractor responseExtractor) { Assert.notNull(responseExtractor, "responseExtractor must not be null"); return sendAndReceive(uri, new WebServiceMessageCallback() { public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException { @@ -542,7 +551,9 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService @Override public boolean sendAndReceive(WebServiceMessageCallback requestCallback, WebServiceMessageCallback responseCallback) { - return sendAndReceive(getDefaultUri(), requestCallback, responseCallback); + String defaultUri = getDefaultUri(); + Assert.notNull(defaultUri, "'defaultUri' must not be null"); + return sendAndReceive(defaultUri, requestCallback, responseCallback); } @Override @@ -555,13 +566,15 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } @Override - public T sendAndReceive(WebServiceMessageCallback requestCallback, + public @Nullable T sendAndReceive(WebServiceMessageCallback requestCallback, WebServiceMessageExtractor responseExtractor) { - return sendAndReceive(getDefaultUri(), requestCallback, responseExtractor); + String defaultUri = getDefaultUri(); + Assert.notNull(defaultUri, "'defaultUri' must not be null"); + return sendAndReceive(defaultUri, requestCallback, responseExtractor); } @Override - public T sendAndReceive(String uriString, WebServiceMessageCallback requestCallback, + public @Nullable T sendAndReceive(String uriString, WebServiceMessageCallback requestCallback, WebServiceMessageExtractor responseExtractor) { Assert.notNull(responseExtractor, "'responseExtractor' must not be null"); Assert.hasLength(uriString, "'uri' must not be empty"); @@ -581,7 +594,9 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService throw new WebServiceIOException("I/O error: " + ex.getMessage(), ex); } finally { - TransportUtils.closeConnection(connection); + if (connection != null) { + TransportUtils.closeConnection(connection); + } TransportContextHolder.setTransportContext(previousTransportContext); } } @@ -603,8 +618,8 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * @throws IOException in case of I/O errors */ @SuppressWarnings("unchecked") - protected T doSendAndReceive(MessageContext messageContext, WebServiceConnection connection, - WebServiceMessageCallback requestCallback, WebServiceMessageExtractor responseExtractor) + protected @Nullable T doSendAndReceive(MessageContext messageContext, WebServiceConnection connection, + @Nullable WebServiceMessageCallback requestCallback, WebServiceMessageExtractor responseExtractor) throws IOException { int interceptorIndex = -1; try { @@ -819,7 +834,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * @param ex exception thrown on handler execution, or {@code null} if none * @see ClientInterceptor#afterCompletion */ - private void triggerAfterCompletion(int interceptorIndex, MessageContext messageContext, Exception ex) + private void triggerAfterCompletion(int interceptorIndex, MessageContext messageContext, @Nullable Exception ex) throws WebServiceClientException { if (this.interceptors != null) { for (int i = interceptorIndex; i >= 0; i--) { @@ -843,7 +858,8 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * {@link #sendAndReceive(String,WebServiceMessageCallback, WebServiceMessageExtractor)}, * if any */ - protected Object handleFault(WebServiceConnection connection, MessageContext messageContext) throws IOException { + protected @Nullable Object handleFault(WebServiceConnection connection, MessageContext messageContext) + throws IOException { if (this.logger.isDebugEnabled()) { this.logger.debug("Received Fault message for request [" + messageContext.getRequest() + "]"); } @@ -887,7 +903,7 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } @Override - public T extractData(WebServiceMessage message) throws IOException, TransformerException { + public @Nullable T extractData(WebServiceMessage message) throws IOException, TransformerException { return this.sourceExtractor.extractData(message.getPayloadSource()); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/core/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/client/core/package-info.java index db6f8122..a44a049d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/core/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/core/package-info.java @@ -18,4 +18,7 @@ * Core package of the Spring-WS client-side support. Provides a WebServiceTemplate class * and various callback interfaces. */ +@NullMarked package org.springframework.ws.client.core; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java b/spring-ws-core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java index f8fa0a37..33e7ead7 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java @@ -18,6 +18,7 @@ package org.springframework.ws.client.core.support; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.InitializingBean; import org.springframework.oxm.Marshaller; @@ -90,7 +91,7 @@ public abstract class WebServiceGatewaySupport implements InitializingBean { } /** Returns the default URI used by the gateway. */ - public final String getDefaultUri() { + public final @Nullable String getDefaultUri() { return this.webServiceTemplate.getDefaultUri(); } @@ -100,7 +101,7 @@ public abstract class WebServiceGatewaySupport implements InitializingBean { } /** Returns the destination provider used by the gateway. */ - public final DestinationProvider getDestinationProvider() { + public final @Nullable DestinationProvider getDestinationProvider() { return this.webServiceTemplate.getDestinationProvider(); } @@ -145,7 +146,7 @@ public abstract class WebServiceGatewaySupport implements InitializingBean { } /** Returns the {@code Marshaller} used by the gateway. */ - public final Marshaller getMarshaller() { + public final @Nullable Marshaller getMarshaller() { return this.webServiceTemplate.getMarshaller(); } @@ -160,7 +161,7 @@ public abstract class WebServiceGatewaySupport implements InitializingBean { } /** Returns the {@code Unmarshaller} used by the gateway. */ - public final Unmarshaller getUnmarshaller() { + public final @Nullable Unmarshaller getUnmarshaller() { return this.webServiceTemplate.getUnmarshaller(); } @@ -175,7 +176,7 @@ public abstract class WebServiceGatewaySupport implements InitializingBean { } /** Returns the {@code ClientInterceptors} used by the template. */ - public final ClientInterceptor[] getInterceptors() { + public final ClientInterceptor @Nullable [] getInterceptors() { return this.webServiceTemplate.getInterceptors(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/core/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/client/core/support/package-info.java index 91451b8a..d8509d67 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/core/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/core/support/package-info.java @@ -18,4 +18,7 @@ * Convenient super class for application classes that need Web service access. Contains a * base class for WebServiceTemplate usage. */ +@NullMarked package org.springframework.ws.client.core.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/client/package-info.java index 71d7c5af..3bec2e36 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/package-info.java @@ -18,4 +18,7 @@ * Contains classes for client-side Spring-WS support, allowing for Spring-style Web * service access. */ +@NullMarked package org.springframework.ws.client; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/WebServiceAccessor.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/WebServiceAccessor.java index dc3883dd..0bf6327c 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/WebServiceAccessor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/WebServiceAccessor.java @@ -41,8 +41,10 @@ import org.springframework.xml.transform.TransformerObjectSupport; */ public abstract class WebServiceAccessor extends TransformerObjectSupport implements InitializingBean { + @SuppressWarnings("NullAway.Init") private WebServiceMessageFactory messageFactory; + @SuppressWarnings("NullAway.Init") private WebServiceMessageSender[] messageSenders; /** Returns the message factory used for creating messages. */ diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/AbstractCachingDestinationProvider.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/AbstractCachingDestinationProvider.java index 0de3d113..a034a28d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/AbstractCachingDestinationProvider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/AbstractCachingDestinationProvider.java @@ -20,6 +20,7 @@ import java.net.URI; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; /** * Abstract base class for {@link DestinationProvider} implementations that cache @@ -36,7 +37,7 @@ public abstract class AbstractCachingDestinationProvider implements DestinationP /** Logger available to subclasses. */ protected final Log logger = LogFactory.getLog(getClass()); - private URI cachedUri; + private @Nullable URI cachedUri; private boolean cache = true; @@ -50,7 +51,7 @@ public abstract class AbstractCachingDestinationProvider implements DestinationP } @Override - public final URI getDestination() { + public final @Nullable URI getDestination() { if (this.cache) { if (this.cachedUri == null) { this.cachedUri = lookupDestination(); @@ -69,6 +70,6 @@ public abstract class AbstractCachingDestinationProvider implements DestinationP * called once. * @return the destination URI */ - protected abstract URI lookupDestination(); + protected abstract @Nullable URI lookupDestination(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/DestinationProvider.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/DestinationProvider.java index dcb69dd0..a626fd50 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/DestinationProvider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/DestinationProvider.java @@ -18,6 +18,8 @@ package org.springframework.ws.client.support.destination; import java.net.URI; +import org.jspecify.annotations.Nullable; + /** * Strategy interface for providing a * {@link org.springframework.ws.client.core.WebServiceTemplate} destination URI at @@ -36,6 +38,6 @@ public interface DestinationProvider { * Return the destination URI. * @return the destination URI */ - URI getDestination(); + @Nullable URI getDestination(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/Wsdl11DestinationProvider.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/Wsdl11DestinationProvider.java index 4660cd4f..91486fe0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/Wsdl11DestinationProvider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/Wsdl11DestinationProvider.java @@ -26,6 +26,7 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.springframework.core.io.Resource; @@ -64,7 +65,7 @@ public class Wsdl11DestinationProvider extends AbstractCachingDestinationProvide private XPathExpression locationXPathExpression; - private Resource wsdlResource; + private @Nullable Resource wsdlResource; public Wsdl11DestinationProvider() { this.expressionNamespaces.put("wsdl", "http://schemas.xmlsoap.org/wsdl/"); @@ -120,7 +121,8 @@ public class Wsdl11DestinationProvider extends AbstractCachingDestinationProvide } @Override - protected URI lookupDestination() { + protected @Nullable URI lookupDestination() { + Assert.notNull(this.wsdlResource, "'wsdlResource' must not be null"); try { DOMResult result = new DOMResult(); Transformer transformer = transformerFactory.newTransformer(); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/package-info.java index 512eae58..7a521316 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/destination/package-info.java @@ -17,4 +17,7 @@ /** * Provides the {@code DestinationProvider} interface. */ +@NullMarked package org.springframework.ws.client.support.destination; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/AbstractValidatingInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/AbstractValidatingInterceptor.java index 60f71f29..36100744 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/AbstractValidatingInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/AbstractValidatingInterceptor.java @@ -20,6 +20,7 @@ import java.io.IOException; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; import org.xml.sax.SAXParseException; import org.springframework.beans.factory.InitializingBean; @@ -56,12 +57,14 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup private String schemaLanguage = XmlValidatorFactory.SCHEMA_W3C_XML; + @SuppressWarnings("NullAway.Init") private Resource[] schemas; private boolean validateRequest = true; private boolean validateResponse = false; + @SuppressWarnings("NullAway.Init") private XmlValidator validator; public String getSchemaLanguage() { @@ -275,7 +278,8 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup /** Does nothing by default. */ @Override - public void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException { + public void afterCompletion(MessageContext messageContext, @Nullable Exception ex) + throws WebServiceClientException { } /** @@ -285,7 +289,7 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup * @return the part of the message that is to validated, or {@code null} not to * validate anything */ - protected abstract Source getValidationRequestSource(WebServiceMessage request); + protected abstract @Nullable Source getValidationRequestSource(WebServiceMessage request); /** * Abstract template method that returns the part of the response message that is to @@ -294,6 +298,6 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup * @return the part of the message that is to validated, or {@code null} not to * validate anything */ - protected abstract Source getValidationResponseSource(WebServiceMessage response); + protected abstract @Nullable Source getValidationResponseSource(WebServiceMessage response); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/ClientInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/ClientInterceptor.java index 77648a64..4e1532b4 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/ClientInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/ClientInterceptor.java @@ -16,6 +16,8 @@ package org.springframework.ws.client.support.interceptor; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.client.WebServiceClientException; import org.springframework.ws.context.MessageContext; import org.springframework.ws.soap.SoapHeader; @@ -102,6 +104,6 @@ public interface ClientInterceptor { * @throws WebServiceClientException in case of errors * @since 2.2 */ - void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException; + void afterCompletion(MessageContext messageContext, @Nullable Exception ex) throws WebServiceClientException; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/ClientInterceptorAdapter.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/ClientInterceptorAdapter.java index 3ed06cf1..c0cb2a45 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/ClientInterceptorAdapter.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/ClientInterceptorAdapter.java @@ -18,6 +18,7 @@ package org.springframework.ws.client.support.interceptor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.ws.client.WebServiceClientException; import org.springframework.ws.context.MessageContext; @@ -55,7 +56,8 @@ public abstract class ClientInterceptorAdapter implements ClientInterceptor { * Does nothing by default. */ @Override - public void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException { + public void afterCompletion(MessageContext messageContext, @Nullable Exception ex) + throws WebServiceClientException { } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptor.java index f909c890..a96788c3 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptor.java @@ -18,6 +18,8 @@ package org.springframework.ws.client.support.interceptor; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; /** @@ -49,7 +51,7 @@ public class PayloadValidatingInterceptor extends AbstractValidatingInterceptor * validate anything */ @Override - protected Source getValidationRequestSource(WebServiceMessage request) { + protected @Nullable Source getValidationRequestSource(WebServiceMessage request) { return request.getPayloadSource(); } @@ -60,7 +62,7 @@ public class PayloadValidatingInterceptor extends AbstractValidatingInterceptor * validate anything */ @Override - protected Source getValidationResponseSource(WebServiceMessage response) { + protected @Nullable Source getValidationResponseSource(WebServiceMessage response) { return response.getPayloadSource(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/package-info.java index 4e41ed0d..1f8c2c15 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/interceptor/package-info.java @@ -17,4 +17,7 @@ /** * Provides the {@code ClientInterceptor} interface, and validating interceptors. */ +@NullMarked package org.springframework.ws.client.support.interceptor; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/client/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/client/support/package-info.java index b3e998ad..c61c19f1 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/client/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/client/support/package-info.java @@ -18,4 +18,7 @@ * Classes supporting the org.springframework.ws.client.core package. Contains a base * class for WebServiceTemplate usage. */ +@NullMarked package org.springframework.ws.client.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/config/AnnotationDrivenBeanDefinitionParser.java b/spring-ws-core/src/main/java/org/springframework/ws/config/AnnotationDrivenBeanDefinitionParser.java index 4e51b716..efbeb98b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/config/AnnotationDrivenBeanDefinitionParser.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/config/AnnotationDrivenBeanDefinitionParser.java @@ -16,6 +16,7 @@ package org.springframework.ws.config; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.BeanMetadataElement; @@ -74,24 +75,24 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { AnnotationDrivenBeanDefinitionParser.class.getClassLoader()); @Override - public BeanDefinition parse(Element element, ParserContext parserContext) { + public @Nullable BeanDefinition parse(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source); parserContext.pushContainingComponent(compDefinition); - registerEndpointMappings(source, parserContext); + registerEndpointMappings(parserContext, source); - registerEndpointAdapters(element, source, parserContext); + registerEndpointAdapters(parserContext, element, source); - registerEndpointExceptionResolvers(source, parserContext); + registerEndpointExceptionResolvers(parserContext, source); parserContext.popAndRegisterContainingComponent(); return null; } - private void registerEndpointMappings(Object source, ParserContext parserContext) { + private void registerEndpointMappings(ParserContext parserContext, @Nullable Object source) { RootBeanDefinition payloadRootMappingDef = createBeanDefinition( PayloadRootAnnotationMethodEndpointMapping.class, source); payloadRootMappingDef.getPropertyValues().add("order", 0); @@ -107,7 +108,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { parserContext.getReaderContext().registerWithGeneratedName(annActionMappingDef); } - private void registerEndpointAdapters(Element element, Object source, ParserContext parserContext) { + private void registerEndpointAdapters(ParserContext parserContext, Element element, @Nullable Object source) { RootBeanDefinition adapterDef = createBeanDefinition(DefaultMethodEndpointAdapter.class, source); ManagedList argumentResolvers = new ManagedList<>(); @@ -121,35 +122,35 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { argumentResolvers.add(createBeanDefinition(SoapMethodArgumentResolver.class, source)); argumentResolvers.add(createBeanDefinition(SoapHeaderElementMethodArgumentResolver.class, source)); - RuntimeBeanReference domProcessor = createBeanReference(DomPayloadMethodProcessor.class, source, parserContext); + RuntimeBeanReference domProcessor = createBeanReference(parserContext, DomPayloadMethodProcessor.class, source); argumentResolvers.add(domProcessor); returnValueHandlers.add(domProcessor); - RuntimeBeanReference sourceProcessor = createBeanReference(SourcePayloadMethodProcessor.class, source, - parserContext); + RuntimeBeanReference sourceProcessor = createBeanReference(parserContext, SourcePayloadMethodProcessor.class, + source); argumentResolvers.add(sourceProcessor); returnValueHandlers.add(sourceProcessor); if (dom4jPresent) { - RuntimeBeanReference dom4jProcessor = createBeanReference(Dom4jPayloadMethodProcessor.class, source, - parserContext); + RuntimeBeanReference dom4jProcessor = createBeanReference(parserContext, Dom4jPayloadMethodProcessor.class, + source); argumentResolvers.add(dom4jProcessor); returnValueHandlers.add(dom4jProcessor); } if (jaxb2Present) { - RuntimeBeanReference xmlRootElementProcessor = createBeanReference( - XmlRootElementPayloadMethodProcessor.class, source, parserContext); + RuntimeBeanReference xmlRootElementProcessor = createBeanReference(parserContext, + XmlRootElementPayloadMethodProcessor.class, source); argumentResolvers.add(xmlRootElementProcessor); returnValueHandlers.add(xmlRootElementProcessor); - RuntimeBeanReference jaxbElementProcessor = createBeanReference(JaxbElementPayloadMethodProcessor.class, - source, parserContext); + RuntimeBeanReference jaxbElementProcessor = createBeanReference(parserContext, + JaxbElementPayloadMethodProcessor.class, source); argumentResolvers.add(jaxbElementProcessor); returnValueHandlers.add(jaxbElementProcessor); } if (jdomPresent) { - RuntimeBeanReference jdomProcessor = createBeanReference(JDomPayloadMethodProcessor.class, source, - parserContext); + RuntimeBeanReference jdomProcessor = createBeanReference(parserContext, JDomPayloadMethodProcessor.class, + source); argumentResolvers.add(jdomProcessor); returnValueHandlers.add(jdomProcessor); } @@ -157,8 +158,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { argumentResolvers.add(createBeanDefinition(StaxPayloadMethodArgumentResolver.class, source)); } if (xomPresent) { - RuntimeBeanReference xomProcessor = createBeanReference(XomPayloadMethodProcessor.class, source, - parserContext); + RuntimeBeanReference xomProcessor = createBeanReference(parserContext, XomPayloadMethodProcessor.class, + source); argumentResolvers.add(xomProcessor); returnValueHandlers.add(xomProcessor); } @@ -186,7 +187,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { parserContext.getReaderContext().registerWithGeneratedName(adapterDef); } - private void registerEndpointExceptionResolvers(Object source, ParserContext parserContext) { + private void registerEndpointExceptionResolvers(ParserContext parserContext, @Nullable Object source) { RootBeanDefinition annotationResolverDef = createBeanDefinition(SoapFaultAnnotationExceptionResolver.class, source); annotationResolverDef.getPropertyValues().add("order", 0); @@ -197,14 +198,15 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { parserContext.getReaderContext().registerWithGeneratedName(simpleResolverDef); } - private RuntimeBeanReference createBeanReference(Class beanClass, Object source, ParserContext parserContext) { + private RuntimeBeanReference createBeanReference(ParserContext parserContext, Class beanClass, + @Nullable Object source) { RootBeanDefinition beanDefinition = createBeanDefinition(beanClass, source); String beanName = parserContext.getReaderContext().registerWithGeneratedName(beanDefinition); parserContext.registerComponent(new BeanComponentDefinition(beanDefinition, beanName)); return new RuntimeBeanReference(beanName); } - private RootBeanDefinition createBeanDefinition(Class beanClass, Object source) { + private RootBeanDefinition createBeanDefinition(Class beanClass, @Nullable Object source) { RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass); beanDefinition.setSource(source); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/config/DynamicWsdlBeanDefinitionParser.java b/spring-ws-core/src/main/java/org/springframework/ws/config/DynamicWsdlBeanDefinitionParser.java index 769dcd7e..fde19019 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/config/DynamicWsdlBeanDefinitionParser.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/config/DynamicWsdlBeanDefinitionParser.java @@ -18,6 +18,7 @@ package org.springframework.ws.config; import java.util.List; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -98,7 +99,7 @@ class DynamicWsdlBeanDefinitionParser extends AbstractBeanDefinitionParser { } } - private RootBeanDefinition createBeanDefinition(Class beanClass, Object source) { + private RootBeanDefinition createBeanDefinition(Class beanClass, @Nullable Object source) { RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass); beanDefinition.setSource(source); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/config/InterceptorsBeanDefinitionParser.java b/spring-ws-core/src/main/java/org/springframework/ws/config/InterceptorsBeanDefinitionParser.java index 0f34c7a8..21d107ce 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/config/InterceptorsBeanDefinitionParser.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/config/InterceptorsBeanDefinitionParser.java @@ -18,6 +18,7 @@ package org.springframework.ws.config; import java.util.List; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -29,6 +30,7 @@ import org.springframework.beans.factory.parsing.CompositeComponentDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.springframework.ws.server.SmartEndpointInterceptor; @@ -45,7 +47,7 @@ import org.springframework.ws.soap.server.endpoint.interceptor.SoapActionSmartEn class InterceptorsBeanDefinitionParser implements BeanDefinitionParser { @Override - public BeanDefinition parse(Element element, ParserContext parserContext) { + public @Nullable BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compDefinition); @@ -149,11 +151,12 @@ class InterceptorsBeanDefinitionParser implements BeanDefinitionParser { private BeanDefinitionHolder createInterceptorDefinition(ParserContext parserContext, Element element) { BeanDefinitionHolder interceptorDef = parserContext.getDelegate().parseBeanDefinitionElement(element); + Assert.notNull(interceptorDef, "No interceptor definition found for element [" + element + "]"); interceptorDef = parserContext.getDelegate().decorateBeanDefinitionIfRequired(element, interceptorDef); return interceptorDef; } - private BeanReference createInterceptorReference(ParserContext parserContext, Element element) { + private @Nullable BeanReference createInterceptorReference(ParserContext parserContext, Element element) { // A generic reference to any name of any bean. String refName = element.getAttribute("bean"); if (!StringUtils.hasLength(refName)) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/config/annotation/WsConfigurationSupport.java b/spring-ws-core/src/main/java/org/springframework/ws/config/annotation/WsConfigurationSupport.java index 3861b800..97fd686b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/config/annotation/WsConfigurationSupport.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/config/annotation/WsConfigurationSupport.java @@ -20,6 +20,8 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; @@ -79,7 +81,7 @@ import org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationM */ public class WsConfigurationSupport { - private List interceptors; + private @Nullable List interceptors; /** * Returns a {@link PayloadRootAnnotationMethodEndpointMapping} ordered at 0 for diff --git a/spring-ws-core/src/main/java/org/springframework/ws/config/annotation/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/config/annotation/package-info.java index 45416085..5d39ed9a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/config/annotation/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/config/annotation/package-info.java @@ -17,4 +17,7 @@ /** * Annotations and supporting classes for declarative configuration. */ +@NullMarked package org.springframework.ws.config.annotation; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/config/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/config/package-info.java index 41d8c3da..d0a544c5 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/config/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/config/package-info.java @@ -17,4 +17,7 @@ /** * Provide a namespace handler for the Spring Web Services namespace. */ +@NullMarked package org.springframework.ws.config; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/context/AbstractMessageContext.java b/spring-ws-core/src/main/java/org/springframework/ws/context/AbstractMessageContext.java index 704c4c25..70ee0ab8 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/context/AbstractMessageContext.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/context/AbstractMessageContext.java @@ -19,6 +19,8 @@ package org.springframework.ws.context; import java.util.HashMap; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.util.StringUtils; /** @@ -33,7 +35,7 @@ public abstract class AbstractMessageContext implements MessageContext { * Keys are {@code Strings}, values are {@code Objects}. Lazily initialized by * {@code getProperties()}. */ - private Map properties; + private @Nullable Map properties; @Override public boolean containsProperty(String name) { @@ -41,7 +43,7 @@ public abstract class AbstractMessageContext implements MessageContext { } @Override - public Object getProperty(String name) { + public @Nullable Object getProperty(String name) { return getProperties().get(name); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/context/DefaultMessageContext.java b/spring-ws-core/src/main/java/org/springframework/ws/context/DefaultMessageContext.java index 3c3dfab5..3b27e187 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/context/DefaultMessageContext.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/context/DefaultMessageContext.java @@ -19,6 +19,8 @@ package org.springframework.ws.context; import java.io.IOException; import java.io.InputStream; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.WebServiceMessageFactory; @@ -35,7 +37,7 @@ public class DefaultMessageContext extends AbstractMessageContext { private final WebServiceMessage request; - private WebServiceMessage response; + private @Nullable WebServiceMessage response; /** * Construct a new, empty instance of the {@code DefaultMessageContext} with the given @@ -75,7 +77,7 @@ public class DefaultMessageContext extends AbstractMessageContext { } @Override - public void setResponse(WebServiceMessage response) { + public void setResponse(@Nullable WebServiceMessage response) { checkForResponse(); this.response = response; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/context/MessageContext.java b/spring-ws-core/src/main/java/org/springframework/ws/context/MessageContext.java index ce506a30..505a72bc 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/context/MessageContext.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/context/MessageContext.java @@ -19,6 +19,8 @@ package org.springframework.ws.context; import java.io.IOException; import java.io.InputStream; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; import org.springframework.ws.server.EndpointInterceptor; @@ -61,7 +63,7 @@ public interface MessageContext { * @throws IllegalStateException if a response has already been created * @since 1.5.0 */ - void setResponse(WebServiceMessage response); + void setResponse(@Nullable WebServiceMessage response); /** * Removes the response message, if any. @@ -91,7 +93,7 @@ public interface MessageContext { * @param name name of the property whose value is to be retrieved * @return value of the property */ - Object getProperty(String name); + @Nullable Object getProperty(String name); /** * Removes a property from the {@code MessageContext}. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/context/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/context/package-info.java index 12e0f138..84534d27 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/context/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/context/package-info.java @@ -17,4 +17,7 @@ /** * Contains the {@code MessageContext} interface and implementations thereof. */ +@NullMarked package org.springframework.ws.context; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/mime/AbstractMimeMessage.java b/spring-ws-core/src/main/java/org/springframework/ws/mime/AbstractMimeMessage.java index b9a10204..1e257059 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/mime/AbstractMimeMessage.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/mime/AbstractMimeMessage.java @@ -93,7 +93,7 @@ public abstract class AbstractMimeMessage implements MimeMessage { @Override public String getName() { - if (this.inputStreamSource instanceof Resource resource) { + if (this.inputStreamSource instanceof Resource resource && resource.getFilename() != null) { return resource.getFilename(); } else { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/mime/MimeMessage.java b/spring-ws-core/src/main/java/org/springframework/ws/mime/MimeMessage.java index f3df5c26..1aad3f8c 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/mime/MimeMessage.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/mime/MimeMessage.java @@ -20,6 +20,7 @@ import java.io.File; import java.util.Iterator; import jakarta.activation.DataHandler; +import org.jspecify.annotations.Nullable; import org.springframework.core.io.InputStreamSource; import org.springframework.ws.WebServiceMessage; @@ -58,7 +59,7 @@ public interface MimeMessage extends WebServiceMessage { * be found * @throws AttachmentException in case of errors */ - Attachment getAttachment(String contentId) throws AttachmentException; + @Nullable Attachment getAttachment(String contentId) throws AttachmentException; /** * Returns an {@code Iterator} over all {@link Attachment} objects that are part of diff --git a/spring-ws-core/src/main/java/org/springframework/ws/mime/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/mime/package-info.java index df27a310..a1e7679f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/mime/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/mime/package-info.java @@ -18,4 +18,7 @@ * Provides MIME functionality for use the Spring Web Services framework. Contains the * Attachment and MimeMessage and related interfaces. */ +@NullMarked package org.springframework.ws.mime; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/package-info.java index 5b922498..5b5e2a91 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/package-info.java @@ -17,4 +17,7 @@ /** * Provides the core functionality of the Spring Web Services framework. */ +@NullMarked package org.springframework.ws; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/pox/dom/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/pox/dom/package-info.java index 9e84ff02..f830e639 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/pox/dom/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/pox/dom/package-info.java @@ -17,4 +17,7 @@ /** * Contains an implementation of the POX interfaces that is based on DOM. */ +@NullMarked package org.springframework.ws.pox.dom; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/pox/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/pox/package-info.java index 05ed69fd..ac967299 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/pox/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/pox/package-info.java @@ -18,4 +18,7 @@ * Provides the Plain Old XML (POX) functionality of the Spring Web Services framework. * Contains the PoxMessage and related interfaces. */ +@NullMarked package org.springframework.ws.pox; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointExceptionResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointExceptionResolver.java index a63879b6..9363279a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointExceptionResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointExceptionResolver.java @@ -16,6 +16,8 @@ package org.springframework.ws.server; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.context.MessageContext; /** @@ -35,6 +37,6 @@ public interface EndpointExceptionResolver { * @param ex the exception that got thrown during endpoint execution * @return {@code true} if resolved; {@code false} otherwise */ - boolean resolveException(MessageContext messageContext, Object endpoint, Exception ex); + boolean resolveException(MessageContext messageContext, @Nullable Object endpoint, Exception ex); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointInterceptor.java index 380dcaf4..c5894451 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointInterceptor.java @@ -16,6 +16,8 @@ package org.springframework.ws.server; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.context.MessageContext; /** @@ -125,6 +127,6 @@ public interface EndpointInterceptor { * @throws Exception in case of errors * @since 2.0.2 */ - void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception; + void afterCompletion(MessageContext messageContext, Object endpoint, @Nullable Exception ex) throws Exception; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointInvocationChain.java b/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointInvocationChain.java index 71db24bd..95709219 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointInvocationChain.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointInvocationChain.java @@ -16,6 +16,8 @@ package org.springframework.ws.server; +import org.jspecify.annotations.Nullable; + /** * Endpoint invocation chain, consisting of an endpoint object and any preprocessing * interceptors. @@ -28,7 +30,7 @@ public class EndpointInvocationChain { private final Object endpoint; - private EndpointInterceptor[] interceptors; + private EndpointInterceptor @Nullable [] interceptors; /** * Create new {@code EndpointInvocationChain}. @@ -43,7 +45,7 @@ public class EndpointInvocationChain { * @param endpoint the endpoint object to invoke * @param interceptors the array of interceptors to apply */ - public EndpointInvocationChain(Object endpoint, EndpointInterceptor[] interceptors) { + public EndpointInvocationChain(Object endpoint, EndpointInterceptor @Nullable [] interceptors) { this.endpoint = endpoint; this.interceptors = interceptors; } @@ -60,7 +62,7 @@ public class EndpointInvocationChain { * Returns the array of interceptors to apply before the handler executes. * @return the array of interceptors */ - public EndpointInterceptor[] getInterceptors() { + public EndpointInterceptor @Nullable [] getInterceptors() { return this.interceptors; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointMapping.java index 1aa66949..03dd716a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/EndpointMapping.java @@ -16,6 +16,8 @@ package org.springframework.ws.server; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.context.MessageContext; /** @@ -57,6 +59,6 @@ public interface EndpointMapping { * interceptors, or {@code null} if no mapping is found * @throws Exception if there is an internal error */ - EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception; + @Nullable EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/MessageDispatcher.java b/spring-ws-core/src/main/java/org/springframework/ws/server/MessageDispatcher.java index 1e2e34c2..4e900d1b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/MessageDispatcher.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/MessageDispatcher.java @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; @@ -103,15 +104,19 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa private final DefaultStrategiesHelper defaultStrategiesHelper; /** The registered bean name for this dispatcher. */ + @SuppressWarnings("NullAway.Init") private String beanName; /** List of EndpointAdapters used in this dispatcher. */ + @SuppressWarnings("NullAway.Init") private List endpointAdapters; /** List of EndpointExceptionResolvers used in this dispatcher. */ + @SuppressWarnings("NullAway.Init") private List endpointExceptionResolvers; /** List of EndpointMappings used in this dispatcher. */ + @SuppressWarnings("NullAway.Init") private List endpointMappings; /** Initializes a new instance of the {@code MessageDispatcher}. */ @@ -231,8 +236,8 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i]; interceptorIndex = i; if (!interceptor.handleRequest(messageContext, mappedEndpoint.getEndpoint())) { - triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext); - triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, null); + triggerHandleResponse(messageContext, mappedEndpoint, interceptorIndex); + triggerAfterCompletion(messageContext, mappedEndpoint, interceptorIndex, null); return; } } @@ -242,7 +247,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa endpointAdapter.invoke(messageContext, mappedEndpoint.getEndpoint()); // Apply handleResponse methods of registered interceptors - triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext); + triggerHandleResponse(messageContext, mappedEndpoint, interceptorIndex); } catch (NoEndpointFoundException ex) { // No triggering of interceptors if no endpoint is found @@ -254,16 +259,16 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa catch (Exception ex) { Object endpoint = (mappedEndpoint != null) ? mappedEndpoint.getEndpoint() : null; processEndpointException(messageContext, endpoint, ex); - triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext); + triggerHandleResponse(messageContext, mappedEndpoint, interceptorIndex); } - triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, null); + triggerAfterCompletion(messageContext, mappedEndpoint, interceptorIndex, null); } catch (NoEndpointFoundException ex) { throw ex; } catch (Exception ex) { // Trigger after-completion for thrown exception. - triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, ex); + triggerAfterCompletion(messageContext, mappedEndpoint, interceptorIndex, ex); throw ex; } } @@ -273,7 +278,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa * @return the {@code EndpointInvocationChain}, or {@code null} if no endpoint could * be found. */ - protected EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception { + protected @Nullable EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception { for (EndpointMapping endpointMapping : getEndpointMappings()) { EndpointInvocationChain endpoint = endpointMapping.getEndpoint(messageContext); if (endpoint != null) { @@ -331,7 +336,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa * @param ex the exception that got thrown during handler execution * @throws Exception if no suitable resolver is found */ - protected void processEndpointException(MessageContext messageContext, Object endpoint, Exception ex) + protected void processEndpointException(MessageContext messageContext, @Nullable Object endpoint, Exception ex) throws Exception { if (!CollectionUtils.isEmpty(getEndpointExceptionResolvers())) { for (EndpointExceptionResolver resolver : getEndpointExceptionResolvers()) { @@ -351,14 +356,14 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa * Trigger handleResponse or handleFault on the mapped EndpointInterceptors. Will just * invoke said method on all interceptors whose handleRequest invocation returned * {@code true}, in addition to the last interceptor who returned {@code false}. + * @param messageContext the message context, whose request and response are filled * @param mappedEndpoint the mapped EndpointInvocationChain * @param interceptorIndex index of last interceptor that was called - * @param messageContext the message context, whose request and response are filled - * @see EndpointInterceptor#handleResponse(MessageContext,Object) + * @see EndpointInterceptor#handleResponse(MessageContext, Object) * @see EndpointInterceptor#handleFault(MessageContext, Object) */ - private void triggerHandleResponse(EndpointInvocationChain mappedEndpoint, int interceptorIndex, - MessageContext messageContext) throws Exception { + private void triggerHandleResponse(MessageContext messageContext, @Nullable EndpointInvocationChain mappedEndpoint, + int interceptorIndex) throws Exception { if (mappedEndpoint != null && messageContext.hasResponse() && !ObjectUtils.isEmpty(mappedEndpoint.getInterceptors())) { boolean hasFault = false; @@ -389,8 +394,8 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa * @param ex exception thrown on handler execution, or {@code null} if none * @see EndpointInterceptor#afterCompletion */ - private void triggerAfterCompletion(EndpointInvocationChain mappedEndpoint, int interceptorIndex, - MessageContext messageContext, Exception ex) throws Exception { + private void triggerAfterCompletion(MessageContext messageContext, @Nullable EndpointInvocationChain mappedEndpoint, + int interceptorIndex, @Nullable Exception ex) throws Exception { // Apply afterCompletion methods of registered interceptors. if (mappedEndpoint != null) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/AbstractEndpointExceptionResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/AbstractEndpointExceptionResolver.java index 13a197a2..e36d2f8e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/AbstractEndpointExceptionResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/AbstractEndpointExceptionResolver.java @@ -20,6 +20,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.core.Ordered; import org.springframework.ws.context.MessageContext; @@ -41,9 +42,9 @@ public abstract class AbstractEndpointExceptionResolver implements EndpointExcep private int order = Integer.MAX_VALUE; // default: same as non-Ordered - private Set mappedEndpoints; + private @Nullable Set mappedEndpoints; - private Log warnLogger; + private @Nullable Log warnLogger; /** * Specify the set of endpoints that this exception resolver should map. @@ -94,7 +95,7 @@ public abstract class AbstractEndpointExceptionResolver implements EndpointExcep * @see #resolveExceptionInternal(MessageContext, Object, Exception) */ @Override - public final boolean resolveException(MessageContext messageContext, Object endpoint, Exception ex) { + public final boolean resolveException(MessageContext messageContext, @Nullable Object endpoint, Exception ex) { Object mappedEndpoint = (endpoint instanceof MethodEndpoint methodEndpoint) ? methodEndpoint.getBean() : endpoint; if (this.mappedEndpoints != null && !this.mappedEndpoints.contains(mappedEndpoint)) { @@ -105,7 +106,7 @@ public abstract class AbstractEndpointExceptionResolver implements EndpointExcep } boolean resolved = resolveExceptionInternal(messageContext, endpoint, ex); if (resolved) { - logException(ex, messageContext); + logException(messageContext, ex); } return resolved; } @@ -116,39 +117,40 @@ public abstract class AbstractEndpointExceptionResolver implements EndpointExcep *

* Calls {@link #buildLogMessage} in order to determine the concrete message to log. * Always passes the full exception to the logger. - * @param ex the exception that got thrown during handler execution * @param messageContext current message context request + * @param ex the exception that got thrown during handler execution * @see #setWarnLogCategory * @see #buildLogMessage * @see org.apache.commons.logging.Log#warn(Object, Throwable) */ - protected void logException(Exception ex, MessageContext messageContext) { + protected void logException(MessageContext messageContext, Exception ex) { if (this.warnLogger != null && this.warnLogger.isWarnEnabled()) { - this.warnLogger.warn(buildLogMessage(ex, messageContext), ex); + this.warnLogger.warn(buildLogMessage(messageContext, ex), ex); } } /** * Build a log message for the given exception, occured during processing the given * message context. - * @param ex the exception that got thrown during handler execution * @param messageContext the message context + * @param ex the exception that got thrown during handler execution * @return the log message to use */ - protected String buildLogMessage(Exception ex, MessageContext messageContext) { + protected String buildLogMessage(MessageContext messageContext, Exception ex) { return "Endpoint execution resulted in exception"; } /** * Template method for resolving exceptions that is called by - * {@link #resolveException}. + * {@link EndpointExceptionResolver#resolveException}. * @param messageContext current message context * @param endpoint the executed endpoint, or {@code null} if none chosen at the time * of the exception * @param ex the exception that got thrown during endpoint execution * @return {@code true} if resolved; {@code false} otherwise - * @see #resolveException(MessageContext, Object, Exception) + * @see EndpointExceptionResolver#resolveException(MessageContext, Object, Exception) */ - protected abstract boolean resolveExceptionInternal(MessageContext messageContext, Object endpoint, Exception ex); + protected abstract boolean resolveExceptionInternal(MessageContext messageContext, @Nullable Object endpoint, + Exception ex); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/AbstractLoggingInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/AbstractLoggingInterceptor.java index 9913e7e5..849f1f8d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/AbstractLoggingInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/AbstractLoggingInterceptor.java @@ -27,6 +27,7 @@ import javax.xml.transform.stream.StreamResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.context.MessageContext; @@ -116,7 +117,7 @@ public abstract class AbstractLoggingInterceptor extends TransformerObjectSuppor * Does nothing by default. */ @Override - public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + public void afterCompletion(MessageContext messageContext, Object endpoint, @Nullable Exception ex) { } /** @@ -146,7 +147,7 @@ public abstract class AbstractLoggingInterceptor extends TransformerObjectSuppor * @param source the source to be logged * @throws TransformerException in case of errors */ - protected void logMessageSource(String logMessage, Source source) throws TransformerException { + protected void logMessageSource(String logMessage, @Nullable Source source) throws TransformerException { if (source != null) { Transformer transformer = createNonIndentingTransformer(); StringWriter writer = new StringWriter(); @@ -173,6 +174,6 @@ public abstract class AbstractLoggingInterceptor extends TransformerObjectSuppor * @param message the message * @return the source of the message */ - protected abstract Source getSource(WebServiceMessage message); + protected abstract @Nullable Source getSource(WebServiceMessage message); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/CompositeEndpointExceptionResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/CompositeEndpointExceptionResolver.java index 61048874..6371e3ae 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/CompositeEndpointExceptionResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/CompositeEndpointExceptionResolver.java @@ -16,6 +16,8 @@ package org.springframework.ws.server.endpoint; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointExceptionResolver; @@ -35,7 +37,7 @@ public class CompositeEndpointExceptionResolver implements EndpointExceptionReso } @Override - public final boolean resolveException(MessageContext messageContext, Object endpoint, Exception ex) { + public final boolean resolveException(MessageContext messageContext, @Nullable Object endpoint, Exception ex) { AbstractEndpointExceptionResolver currentResolver = null; for (AbstractEndpointExceptionResolver resolver : this.resolvers) { currentResolver = resolver; @@ -44,7 +46,7 @@ public class CompositeEndpointExceptionResolver implements EndpointExceptionReso } } if (currentResolver != null) { - currentResolver.logException(ex, messageContext); + currentResolver.logException(messageContext, ex); } return false; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java index c3620557..1b1fd62e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java @@ -19,6 +19,8 @@ package org.springframework.ws.server.endpoint; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.BeanFactory; import org.springframework.core.MethodParameter; import org.springframework.util.Assert; @@ -39,7 +41,7 @@ public final class MethodEndpoint { private final Method method; - private final BeanFactory beanFactory; + private final @Nullable BeanFactory beanFactory; /** * Constructs a new method endpoint with the given bean and method. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/PayloadEndpoint.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/PayloadEndpoint.java index 4def1d43..e8e69dee 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/PayloadEndpoint.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/PayloadEndpoint.java @@ -18,6 +18,8 @@ package org.springframework.ws.server.endpoint; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + /** * Defines the basic contract for Web Services interested in just the message payload. *

@@ -37,6 +39,6 @@ public interface PayloadEndpoint { * response * @throws Exception if an exception occurs */ - Source invoke(Source request) throws Exception; + @Nullable Source invoke(@Nullable Source request) throws Exception; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.java index 717b7b7c..d9c06ca1 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.java @@ -20,6 +20,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.InitializingBean; @@ -66,11 +68,13 @@ public class DefaultMethodEndpointAdapter extends AbstractMethodEndpointAdapter private static final String SOAP_HEADER_ELEMENT_ARGUMENT_RESOLVER_CLASS_NAME = "org.springframework.ws.soap.server.endpoint.adapter.method.SoapHeaderElementMethodArgumentResolver"; + @SuppressWarnings("NullAway.Init") private List methodArgumentResolvers; + @SuppressWarnings("NullAway.Init") private List methodReturnValueHandlers; - private ClassLoader classLoader; + private @Nullable ClassLoader classLoader; /** * Create a new instance with default method argument and return value resolvers. @@ -247,7 +251,7 @@ public class DefaultMethodEndpointAdapter extends AbstractMethodEndpointAdapter @Override protected final void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception { - Object[] args = getMethodArguments(messageContext, methodEndpoint); + @Nullable Object[] args = getMethodArguments(messageContext, methodEndpoint); if (this.logger.isTraceEnabled()) { this.logger.trace("Invoking [" + methodEndpoint + "] with arguments " + Arrays.asList(args)); @@ -276,10 +280,10 @@ public class DefaultMethodEndpointAdapter extends AbstractMethodEndpointAdapter * @return the arguments * @throws Exception in case of errors */ - protected Object[] getMethodArguments(MessageContext messageContext, MethodEndpoint methodEndpoint) + protected @Nullable Object[] getMethodArguments(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception { MethodParameter[] parameters = methodEndpoint.getMethodParameters(); - Object[] args = new Object[parameters.length]; + @Nullable Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { for (MethodArgumentResolver methodArgumentResolver : this.methodArgumentResolvers) { if (methodArgumentResolver.supportsParameter(parameters[i])) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadSourceMethodProcessor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadSourceMethodProcessor.java index 69b7e6a7..892effe8 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadSourceMethodProcessor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadSourceMethodProcessor.java @@ -18,6 +18,8 @@ package org.springframework.ws.server.endpoint.adapter.method; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.core.MethodParameter; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.context.MessageContext; @@ -35,15 +37,15 @@ public abstract class AbstractPayloadSourceMethodProcessor extends AbstractPaylo // MethodArgumentResolver @Override - public final Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception { + public final @Nullable Object resolveArgument(MessageContext messageContext, MethodParameter parameter) + throws Exception { Source requestPayload = getRequestPayload(messageContext); return (requestPayload != null) ? resolveRequestPayloadArgument(parameter, requestPayload) : null; } /** Returns the request payload as {@code Source}. */ - private Source getRequestPayload(MessageContext messageContext) { - WebServiceMessage request = messageContext.getRequest(); - return (request != null) ? request.getPayloadSource() : null; + private @Nullable Source getRequestPayload(MessageContext messageContext) { + return messageContext.getRequest().getPayloadSource(); } /** @@ -60,14 +62,12 @@ public abstract class AbstractPayloadSourceMethodProcessor extends AbstractPaylo // MethodReturnValueHandler @Override - public final void handleReturnValue(MessageContext messageContext, MethodParameter returnType, Object returnValue) - throws Exception { + public final void handleReturnValue(MessageContext messageContext, MethodParameter returnType, + @Nullable Object returnValue) throws Exception { if (returnValue != null) { Source responsePayload = createResponsePayload(returnType, returnValue); - if (responsePayload != null) { - WebServiceMessage response = messageContext.getResponse(); - transform(responsePayload, response.getPayloadResult()); - } + WebServiceMessage response = messageContext.getResponse(); + transform(responsePayload, response.getPayloadResult()); } } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessor.java index 267823e3..14eb8ad8 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessor.java @@ -16,6 +16,8 @@ package org.springframework.ws.server.endpoint.adapter.method; +import org.jspecify.annotations.Nullable; + import org.springframework.core.MethodParameter; import org.springframework.oxm.GenericMarshaller; import org.springframework.oxm.GenericUnmarshaller; @@ -35,9 +37,9 @@ import org.springframework.ws.support.MarshallingUtils; */ public class MarshallingPayloadMethodProcessor extends AbstractPayloadMethodProcessor { - private Marshaller marshaller; + private @Nullable Marshaller marshaller; - private Unmarshaller unmarshaller; + private @Nullable Unmarshaller unmarshaller; /** * Creates a new {@code MarshallingPayloadMethodProcessor}. The {@link Marshaller} and @@ -83,7 +85,7 @@ public class MarshallingPayloadMethodProcessor extends AbstractPayloadMethodProc /** * Returns the marshaller used for transforming objects into XML. */ - public Marshaller getMarshaller() { + public @Nullable Marshaller getMarshaller() { return this.marshaller; } @@ -97,7 +99,7 @@ public class MarshallingPayloadMethodProcessor extends AbstractPayloadMethodProc /** * Returns the unmarshaller used for transforming XML into objects. */ - public Unmarshaller getUnmarshaller() { + public @Nullable Unmarshaller getUnmarshaller() { return this.unmarshaller; } @@ -123,7 +125,7 @@ public class MarshallingPayloadMethodProcessor extends AbstractPayloadMethodProc } @Override - public Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception { + public @Nullable Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception { Unmarshaller unmarshaller = getUnmarshaller(); Assert.state(unmarshaller != null, "unmarshaller must not be null"); @@ -150,8 +152,8 @@ public class MarshallingPayloadMethodProcessor extends AbstractPayloadMethodProc } @Override - public void handleReturnValue(MessageContext messageContext, MethodParameter returnType, Object returnValue) - throws Exception { + public void handleReturnValue(MessageContext messageContext, MethodParameter returnType, + @Nullable Object returnValue) throws Exception { if (returnValue == null) { return; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MethodArgumentResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MethodArgumentResolver.java index f245b006..69372ea9 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MethodArgumentResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MethodArgumentResolver.java @@ -16,6 +16,8 @@ package org.springframework.ws.server.endpoint.adapter.method; +import org.jspecify.annotations.Nullable; + import org.springframework.core.MethodParameter; import org.springframework.ws.context.MessageContext; @@ -48,6 +50,6 @@ public interface MethodArgumentResolver { * @return the resolved argument. May be {@code null}. * @throws Exception in case of errors */ - Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception; + @Nullable Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MethodReturnValueHandler.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MethodReturnValueHandler.java index 3f108c8f..ace6af09 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MethodReturnValueHandler.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MethodReturnValueHandler.java @@ -16,6 +16,8 @@ package org.springframework.ws.server.endpoint.adapter.method; +import org.jspecify.annotations.Nullable; + import org.springframework.core.MethodParameter; import org.springframework.ws.context.MessageContext; @@ -47,7 +49,7 @@ public interface MethodReturnValueHandler { * @param returnValue the return value to handle * @throws Exception in case of errors */ - void handleReturnValue(MessageContext messageContext, MethodParameter returnType, Object returnValue) + void handleReturnValue(MessageContext messageContext, MethodParameter returnType, @Nullable Object returnValue) throws Exception; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessor.java index 23da7836..cc2ae019 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessor.java @@ -30,6 +30,7 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; @@ -166,7 +167,7 @@ public class SourcePayloadMethodProcessor extends AbstractPayloadSourceMethodPro return (parentLocation != null) ? parentLocation.getLineNumber() : -1; } - public String getPublicId() { + public @Nullable String getPublicId() { return (parentLocation != null) ? parentLocation.getPublicId() : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/StaxPayloadMethodArgumentResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/StaxPayloadMethodArgumentResolver.java index 7b6f31a8..5586183d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/StaxPayloadMethodArgumentResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/StaxPayloadMethodArgumentResolver.java @@ -27,6 +27,8 @@ import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.stream.StreamResult; +import org.jspecify.annotations.Nullable; + import org.springframework.core.MethodParameter; import org.springframework.util.xml.StaxUtils; import org.springframework.ws.context.MessageContext; @@ -57,7 +59,7 @@ public class StaxPayloadMethodArgumentResolver extends TransformerObjectSupport } @Override - public Object resolveArgument(MessageContext messageContext, MethodParameter parameter) + public @Nullable Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws TransformerException, XMLStreamException { Source source = messageContext.getRequest().getPayloadSource(); if (source == null) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/XPathParamMethodArgumentResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/XPathParamMethodArgumentResolver.java index 909430a2..1be1cfc4 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/XPathParamMethodArgumentResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/XPathParamMethodArgumentResolver.java @@ -16,6 +16,8 @@ package org.springframework.ws.server.endpoint.adapter.method; +import java.lang.reflect.Method; + import javax.xml.namespace.QName; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; @@ -25,6 +27,7 @@ import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -33,6 +36,7 @@ import org.w3c.dom.NodeList; import org.springframework.core.MethodParameter; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.util.Assert; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.endpoint.annotation.XPathParam; import org.springframework.ws.server.endpoint.support.NamespaceUtils; @@ -91,8 +95,10 @@ public class XPathParamMethodArgumentResolver implements MethodArgumentResolver } @Override - public Object resolveArgument(MessageContext messageContext, MethodParameter parameter) + public @Nullable Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws TransformerException, XPathExpressionException { + Method method = parameter.getMethod(); + Assert.notNull(method, "Method must not be null"); Class parameterType = parameter.getParameterType(); QName evaluationReturnType = getReturnType(parameterType); boolean useConversionService = false; @@ -100,17 +106,20 @@ public class XPathParamMethodArgumentResolver implements MethodArgumentResolver evaluationReturnType = XPathConstants.STRING; useConversionService = true; } - XPath xpath = createXPath(); - xpath.setNamespaceContext(NamespaceUtils.getNamespaceContext(parameter.getMethod())); + xpath.setNamespaceContext(NamespaceUtils.getNamespaceContext(method)); - Element rootElement = getRootElement(messageContext.getRequest().getPayloadSource()); - String expression = parameter.getParameterAnnotation(XPathParam.class).value(); + Source payloadSource = messageContext.getRequest().getPayloadSource(); + Assert.notNull(payloadSource, "No payload source available"); + Element rootElement = getRootElement(payloadSource); + XPathParam annotation = parameter.getParameterAnnotation(XPathParam.class); + Assert.state(annotation != null, "No @XPathParam annotation found"); + String expression = annotation.value(); Object result = xpath.evaluate(expression, rootElement, evaluationReturnType); return (useConversionService) ? this.conversionService.convert(result, parameterType) : result; } - private QName getReturnType(Class parameterType) { + private @Nullable QName getReturnType(Class parameterType) { if (Boolean.class.equals(parameterType) || Boolean.TYPE.equals(parameterType)) { return XPathConstants.BOOLEAN; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/dom/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/dom/package-info.java index 63fd94dd..ddc38b6d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/dom/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/dom/package-info.java @@ -18,4 +18,7 @@ * Provides DOM-based implementations of the {@code MethodArgumentResolver} and * {@code MethodReturnValueHandler} interfaces. */ +@NullMarked package org.springframework.ws.server.endpoint.adapter.method.dom; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/AbstractJaxb2PayloadMethodProcessor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/AbstractJaxb2PayloadMethodProcessor.java index b4e3211c..91d53ecc 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/AbstractJaxb2PayloadMethodProcessor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/AbstractJaxb2PayloadMethodProcessor.java @@ -44,6 +44,7 @@ import jakarta.xml.bind.JAXBIntrospector; import jakarta.xml.bind.Marshaller; import jakarta.xml.bind.Unmarshaller; import jakarta.xml.bind.UnmarshallerHandler; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Node; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; @@ -79,8 +80,8 @@ public abstract class AbstractJaxb2PayloadMethodProcessor extends AbstractPayloa private final ConcurrentMap, JAXBContext> jaxbContexts = new ConcurrentHashMap<>(); @Override - public final void handleReturnValue(MessageContext messageContext, MethodParameter returnType, Object returnValue) - throws Exception { + public final void handleReturnValue(MessageContext messageContext, MethodParameter returnType, + @Nullable Object returnValue) throws Exception { if (returnValue != null) { handleReturnValueInternal(messageContext, returnType, returnValue); } @@ -130,7 +131,7 @@ public abstract class AbstractJaxb2PayloadMethodProcessor extends AbstractPayloa * @return the unmarshalled object, or {@code null} if the request has no payload * @throws JAXBException in case of JAXB2 errors */ - protected final Object unmarshalFromRequestPayload(MessageContext messageContext, Class clazz) + protected final @Nullable Object unmarshalFromRequestPayload(MessageContext messageContext, Class clazz) throws JAXBException { Source requestPayload = getRequestPayload(messageContext); if (requestPayload == null) { @@ -156,8 +157,8 @@ public abstract class AbstractJaxb2PayloadMethodProcessor extends AbstractPayloa * @return the unmarshalled element, or {@code null} if the request has no payload * @throws JAXBException in case of JAXB2 errors */ - protected final JAXBElement unmarshalElementFromRequestPayload(MessageContext messageContext, Class clazz) - throws JAXBException { + protected final @Nullable JAXBElement unmarshalElementFromRequestPayload(MessageContext messageContext, + Class clazz) throws JAXBException { Source requestPayload = getRequestPayload(messageContext); if (requestPayload == null) { return null; @@ -175,9 +176,8 @@ public abstract class AbstractJaxb2PayloadMethodProcessor extends AbstractPayloa } } - private Source getRequestPayload(MessageContext messageContext) { - WebServiceMessage request = messageContext.getRequest(); - return (request != null) ? request.getPayloadSource() : null; + private @Nullable Source getRequestPayload(MessageContext messageContext) { + return messageContext.getRequest().getPayloadSource(); } private JAXBException convertToJaxbException(Exception ex) { @@ -237,7 +237,7 @@ public abstract class AbstractJaxb2PayloadMethodProcessor extends AbstractPayloa private final Unmarshaller unmarshaller; - private Object result; + private @Nullable Object result; Jaxb2SourceCallback(Class clazz) throws JAXBException { this.unmarshaller = createUnmarshaller(clazz); @@ -307,7 +307,7 @@ public abstract class AbstractJaxb2PayloadMethodProcessor extends AbstractPayloa private final Class declaredType; - private JAXBElement result; + private @Nullable JAXBElement result; JaxbElementSourceCallback(Class declaredType) throws JAXBException { this.unmarshaller = createUnmarshaller(declaredType); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/JaxbElementPayloadMethodProcessor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/JaxbElementPayloadMethodProcessor.java index 4ad127da..8af0f8ec 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/JaxbElementPayloadMethodProcessor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/JaxbElementPayloadMethodProcessor.java @@ -21,6 +21,7 @@ import java.lang.reflect.Type; import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.JAXBException; +import org.jspecify.annotations.Nullable; import org.springframework.core.MethodParameter; import org.springframework.ws.context.MessageContext; @@ -45,7 +46,7 @@ public class JaxbElementPayloadMethodProcessor extends AbstractJaxb2PayloadMetho } @Override - public JAXBElement resolveArgument(MessageContext messageContext, MethodParameter parameter) + public @Nullable JAXBElement resolveArgument(MessageContext messageContext, MethodParameter parameter) throws JAXBException { ParameterizedType parameterizedType = (ParameterizedType) parameter.getGenericParameterType(); Class clazz = (Class) parameterizedType.getActualTypeArguments()[0]; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/XmlRootElementPayloadMethodProcessor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/XmlRootElementPayloadMethodProcessor.java index 78f36ad2..dc816153 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/XmlRootElementPayloadMethodProcessor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/XmlRootElementPayloadMethodProcessor.java @@ -20,6 +20,7 @@ import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.XmlType; +import org.jspecify.annotations.Nullable; import org.springframework.core.MethodParameter; import org.springframework.ws.context.MessageContext; @@ -46,7 +47,8 @@ public class XmlRootElementPayloadMethodProcessor extends AbstractJaxb2PayloadMe } @Override - public Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws JAXBException { + public @Nullable Object resolveArgument(MessageContext messageContext, MethodParameter parameter) + throws JAXBException { Class parameterType = parameter.getParameterType(); if (parameterType.isAnnotationPresent(XmlRootElement.class)) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/package-info.java index ec70b2c0..55bc9e53 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/package-info.java @@ -18,4 +18,7 @@ * Provides JAXB2-based implementations of the {@code MethodArgumentResolver} and * {@code MethodReturnValueHandler} interfaces. */ +@NullMarked package org.springframework.ws.server.endpoint.adapter.method.jaxb; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/package-info.java index c5bfb586..c36641db 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/package-info.java @@ -18,4 +18,7 @@ * Provides the {@code MethodArgumentResolver} and {@code MethodReturnValueHandler} * abstractions, and various implementations thereof. */ +@NullMarked package org.springframework.ws.server.endpoint.adapter.method; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/package-info.java index a0959439..db1604e4 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/package-info.java @@ -17,4 +17,7 @@ /** * Provides miscellaneous {@code EndpointAdapter} implementations. */ +@NullMarked package org.springframework.ws.server.endpoint.adapter; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/annotation/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/annotation/package-info.java index 8ab9aff4..4dfeae60 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/annotation/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/annotation/package-info.java @@ -17,4 +17,7 @@ /** * JDK 1.5+ annotations for Spring-WS endpoints. */ +@NullMarked package org.springframework.ws.server.endpoint.annotation; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java index e397c30a..5205f098 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java @@ -21,6 +21,7 @@ import java.io.IOException; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; +import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; @@ -60,15 +61,16 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup private String schemaLanguage = XmlValidatorFactory.SCHEMA_W3C_XML; - private Resource[] schemas; + private Resource @Nullable [] schemas; private boolean validateRequest = true; private boolean validateResponse = false; + @SuppressWarnings("NullAway.Init") private XmlValidator validator; - private ValidationErrorHandler errorHandler; + private @Nullable ValidationErrorHandler errorHandler; public String getSchemaLanguage() { return this.schemaLanguage; @@ -87,7 +89,7 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup /** * Returns the schema resources to use for validation. */ - public Resource[] getSchemas() { + public Resource @Nullable [] getSchemas() { return this.schemas; } @@ -275,7 +277,7 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup /** Does nothing by default. */ @Override - public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + public void afterCompletion(MessageContext messageContext, Object endpoint, @Nullable Exception ex) { } /** @@ -285,7 +287,7 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup * @return the part of the message that is to validated, or {@code null} not to * validate anything */ - protected abstract Source getValidationRequestSource(WebServiceMessage request); + protected abstract @Nullable Source getValidationRequestSource(WebServiceMessage request); /** * Abstract template method that returns the part of the response message that is to @@ -294,6 +296,6 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup * @return the part of the message that is to validated, or {@code null} not to * validate anything */ - protected abstract Source getValidationResponseSource(WebServiceMessage response); + protected abstract @Nullable Source getValidationResponseSource(WebServiceMessage response); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/DelegatingSmartEndpointInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/DelegatingSmartEndpointInterceptor.java index e1de2499..a9805dc4 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/DelegatingSmartEndpointInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/DelegatingSmartEndpointInterceptor.java @@ -16,6 +16,8 @@ package org.springframework.ws.server.endpoint.interceptor; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.context.MessageContext; @@ -92,7 +94,8 @@ public class DelegatingSmartEndpointInterceptor implements SmartEndpointIntercep } @Override - public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception { + public void afterCompletion(MessageContext messageContext, Object endpoint, @Nullable Exception ex) + throws Exception { getDelegate().afterCompletion(messageContext, endpoint, ex); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/EndpointInterceptorAdapter.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/EndpointInterceptorAdapter.java index 5dfaa3c1..b1cd81c8 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/EndpointInterceptorAdapter.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/EndpointInterceptorAdapter.java @@ -18,6 +18,7 @@ package org.springframework.ws.server.endpoint.interceptor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Element; import org.springframework.ws.context.MessageContext; @@ -75,7 +76,8 @@ public class EndpointInterceptorAdapter implements EndpointInterceptor { * Does nothing by default. */ @Override - public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception { + public void afterCompletion(MessageContext messageContext, Object endpoint, @Nullable Exception ex) + throws Exception { } } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadLoggingInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadLoggingInterceptor.java index 15b0e851..ef074f09 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadLoggingInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadLoggingInterceptor.java @@ -18,6 +18,8 @@ package org.springframework.ws.server.endpoint.interceptor; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; import org.springframework.ws.server.endpoint.AbstractLoggingInterceptor; @@ -37,7 +39,7 @@ import org.springframework.ws.server.endpoint.AbstractLoggingInterceptor; public class PayloadLoggingInterceptor extends AbstractLoggingInterceptor { @Override - protected Source getSource(WebServiceMessage message) { + protected @Nullable Source getSource(WebServiceMessage message) { return message.getPayloadSource(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadTransformingInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadTransformingInterceptor.java index 80a805b7..26997f55 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadTransformingInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadTransformingInterceptor.java @@ -29,6 +29,7 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.xml.sax.XMLReader; import org.springframework.beans.factory.InitializingBean; @@ -61,13 +62,13 @@ public class PayloadTransformingInterceptor extends TransformerObjectSupport private static final Log logger = LogFactory.getLog(PayloadTransformingInterceptor.class); - private Resource requestXslt; + private @Nullable Resource requestXslt; - private Resource responseXslt; + private @Nullable Resource responseXslt; - private Templates requestTemplates; + private @Nullable Templates requestTemplates; - private Templates responseTemplates; + private @Nullable Templates responseTemplates; /** Sets the XSLT stylesheet to use for transforming incoming request. */ public void setRequestXslt(Resource requestXslt) { @@ -130,7 +131,7 @@ public class PayloadTransformingInterceptor extends TransformerObjectSupport /** Does nothing by default. */ @Override - public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + public void afterCompletion(MessageContext messageContext, Object endpoint, @Nullable Exception ex) { } @Override diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/package-info.java index 524c9869..147e51a8 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/interceptor/package-info.java @@ -17,4 +17,7 @@ /** * Provides miscellaneous endpoints {@code EndpointInterceptor} implementations. */ +@NullMarked package org.springframework.ws.server.endpoint.interceptor; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationMethodEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationMethodEndpointMapping.java index ab41e70f..96eaaafc 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationMethodEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationMethodEndpointMapping.java @@ -20,7 +20,9 @@ import java.lang.annotation.Annotation; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.util.Assert; import org.springframework.ws.server.endpoint.annotation.Endpoint; /** @@ -61,15 +63,17 @@ public abstract class AbstractAnnotationMethodEndpointMapping extends Abstrac @Override protected void initApplicationContext() throws BeansException { super.initApplicationContext(); + ApplicationContext applicationContext = getApplicationContext(); + Assert.notNull(applicationContext, "No ApplicationContext found"); if (this.logger.isDebugEnabled()) { - this.logger.debug("Looking for endpoints in application context: " + getApplicationContext()); + this.logger.debug("Looking for endpoints in application context: " + applicationContext); } String[] beanNames = (this.detectEndpointsInAncestorContexts - ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) - : getApplicationContext().getBeanNamesForType(Object.class)); + ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) + : applicationContext.getBeanNamesForType(Object.class)); for (String beanName : beanNames) { - Class endpointClass = getApplicationContext().getType(beanName); + Class endpointClass = applicationContext.getType(beanName); if (endpointClass != null && AnnotationUtils.findAnnotation(endpointClass, getEndpointAnnotationType()) != null) { registerMethods(beanName); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractEndpointMapping.java index ff005c88..302e0d11 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractEndpointMapping.java @@ -21,8 +21,11 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.context.ApplicationContext; import org.springframework.context.support.ApplicationObjectSupport; import org.springframework.core.Ordered; import org.springframework.ws.context.MessageContext; @@ -44,18 +47,18 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i private int order = Integer.MAX_VALUE; // default: same as non-Ordered - private Object defaultEndpoint; + private @Nullable Object defaultEndpoint; - private EndpointInterceptor[] interceptors; + private EndpointInterceptor @Nullable [] interceptors; - private SmartEndpointInterceptor[] smartInterceptors; + private SmartEndpointInterceptor @Nullable [] smartInterceptors; /** * Returns the endpoint interceptors to apply to all endpoints mapped by this endpoint * mapping. * @return array of endpoint interceptors, or {@code null} if none */ - public EndpointInterceptor[] getInterceptors() { + public EndpointInterceptor @Nullable [] getInterceptors() { return this.interceptors; } @@ -98,7 +101,7 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i */ protected void initInterceptors() { Map smartInterceptors = BeanFactoryUtils - .beansOfTypeIncludingAncestors(getApplicationContext(), SmartEndpointInterceptor.class, true, false); + .beansOfTypeIncludingAncestors(obtainApplicationContext(), SmartEndpointInterceptor.class, true, false); if (!smartInterceptors.isEmpty()) { this.smartInterceptors = smartInterceptors.values().toArray(new SmartEndpointInterceptor[0]); } @@ -111,7 +114,7 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i * @see #getEndpointInternal(org.springframework.ws.context.MessageContext) */ @Override - public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception { + public final @Nullable EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception { Object endpoint = resoleEndpoint(messageContext); if (endpoint == null) { return null; @@ -131,7 +134,7 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i interceptors.toArray(new EndpointInterceptor[0])); } - private Object resoleEndpoint(MessageContext messageContext) throws Exception { + private @Nullable Object resoleEndpoint(MessageContext messageContext) throws Exception { Object endpoint = getEndpointInternal(messageContext); if (endpoint == null) { endpoint = this.defaultEndpoint; @@ -141,9 +144,6 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i } if (endpoint instanceof String endpointName) { endpoint = resolveStringEndpoint(endpointName); - if (endpoint == null) { - return null; - } } return endpoint; } @@ -173,7 +173,7 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i * Returns the default endpoint for this endpoint mapping. * @return the default endpoint mapping, or null if none */ - protected final Object getDefaultEndpoint() { + protected final @Nullable Object getDefaultEndpoint() { return this.defaultEndpoint; } @@ -194,9 +194,10 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i * @param endpointName the endpoint name * @return the resolved endpoint, or {@code null} if the name could not be resolved */ - protected Object resolveStringEndpoint(String endpointName) { - if (getApplicationContext().containsBean(endpointName)) { - return getApplicationContext().getBean(endpointName); + protected @Nullable Object resolveStringEndpoint(String endpointName) { + ApplicationContext applicationContext = obtainApplicationContext(); + if (applicationContext.containsBean(endpointName)) { + return applicationContext.getBean(endpointName); } else { return null; @@ -214,6 +215,6 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i * @return the looked up endpoint instance, or null * @throws Exception if there is an error */ - protected abstract Object getEndpointInternal(MessageContext messageContext) throws Exception; + protected abstract @Nullable Object getEndpointInternal(MessageContext messageContext) throws Exception; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMapBasedEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMapBasedEndpointMapping.java index 0ffe89e5..2cc9012a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMapBasedEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMapBasedEndpointMapping.java @@ -20,8 +20,12 @@ import java.util.HashMap; import java.util.Map; import java.util.Properties; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextException; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; @@ -42,10 +46,12 @@ public abstract class AbstractMapBasedEndpointMapping extends AbstractEndpointMa private boolean registerBeanNames = false; + private boolean configured = false; + private final Map endpointMap = new HashMap<>(); // holds mappings set via setEndpointMap and setMappings - private Map temporaryEndpointMap = new HashMap<>(); + private final Map temporaryEndpointMap = new HashMap<>(); /** * Set whether to lazily initialize endpoints. Only applicable to singleton endpoints, @@ -77,6 +83,7 @@ public abstract class AbstractMapBasedEndpointMapping extends AbstractEndpointMa * @throws IllegalArgumentException if the endpoint is invalid */ public final void setEndpointMap(Map endpointMap) { + Assert.state(!this.configured, "Mappings have already been configured"); this.temporaryEndpointMap.putAll(endpointMap); } @@ -85,6 +92,7 @@ public abstract class AbstractMapBasedEndpointMapping extends AbstractEndpointMa * exact subclass used. They can be qualified names, for instance, or mime headers. */ public void setMappings(Properties mappings) { + Assert.state(!this.configured, "Mappings have already been configured"); for (Map.Entry entry : mappings.entrySet()) { if (entry.getKey() instanceof String) { this.temporaryEndpointMap.put((String) entry.getKey(), entry.getValue()); @@ -103,7 +111,7 @@ public abstract class AbstractMapBasedEndpointMapping extends AbstractEndpointMa * key cannot be found. * @return the registration key; or {@code null} */ - protected abstract String getLookupKeyForMessage(MessageContext messageContext) throws Exception; + protected abstract @Nullable String getLookupKeyForMessage(MessageContext messageContext) throws Exception; /** * Lookup an endpoint for the given message. The extraction of the endpoint key is @@ -111,7 +119,7 @@ public abstract class AbstractMapBasedEndpointMapping extends AbstractEndpointMa * @return the looked up endpoint, or {@code null} */ @Override - protected final Object getEndpointInternal(MessageContext messageContext) throws Exception { + protected final @Nullable Object getEndpointInternal(MessageContext messageContext) throws Exception { String key = getLookupKeyForMessage(messageContext); if (!StringUtils.hasLength(key)) { return null; @@ -127,7 +135,7 @@ public abstract class AbstractMapBasedEndpointMapping extends AbstractEndpointMa * @param key key the beans are mapped to * @return the associated endpoint instance, or {@code null} if not found */ - protected Object lookupEndpoint(String key) { + protected @Nullable Object lookupEndpoint(String key) { return this.endpointMap.get(key); } @@ -176,18 +184,19 @@ public abstract class AbstractMapBasedEndpointMapping extends AbstractEndpointMa } registerEndpoint(key, endpoint); } - this.temporaryEndpointMap = null; + this.temporaryEndpointMap.clear(); + this.configured = true; if (this.registerBeanNames) { + ApplicationContext applicationContext = obtainApplicationContext(); if (this.logger.isDebugEnabled()) { - this.logger - .debug("Looking for endpoint mappings in application context: [" + getApplicationContext() + "]"); + this.logger.debug("Looking for endpoint mappings in application context: [" + applicationContext + "]"); } - String[] beanNames = getApplicationContext().getBeanDefinitionNames(); + String[] beanNames = applicationContext.getBeanDefinitionNames(); for (String beanName : beanNames) { if (validateLookupKey(beanName)) { registerEndpoint(beanName, beanName); } - String[] aliases = getApplicationContext().getAliases(beanName); + String[] aliases = applicationContext.getAliases(beanName); for (String aliase : aliases) { if (validateLookupKey(aliase)) { registerEndpoint(aliase, beanName); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMethodEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMethodEndpointMapping.java index 1890b724..d21203bb 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMethodEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMethodEndpointMapping.java @@ -26,8 +26,11 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.jspecify.annotations.Nullable; + import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextException; import org.springframework.core.BridgeMethodResolver; import org.springframework.util.Assert; @@ -59,7 +62,7 @@ public abstract class AbstractMethodEndpointMapping extends AbstractEndpointM * @see #getLookupKeyForMessage(MessageContext) */ @Override - protected Object getEndpointInternal(MessageContext messageContext) throws Exception { + protected @Nullable Object getEndpointInternal(MessageContext messageContext) throws Exception { T key = getLookupKeyForMessage(messageContext); if (key == null) { return null; @@ -74,14 +77,14 @@ public abstract class AbstractMethodEndpointMapping extends AbstractEndpointM * Returns the endpoint keys for the given message context. * @return the registration keys */ - protected abstract T getLookupKeyForMessage(MessageContext messageContext) throws Exception; + protected abstract @Nullable T getLookupKeyForMessage(MessageContext messageContext) throws Exception; /** * Looks up an endpoint instance for the given keys. All keys are tried in order. * @param key key the beans are mapped to * @return the associated endpoint instance, or {@code null} if not found */ - protected MethodEndpoint lookupEndpoint(T key) { + protected @Nullable MethodEndpoint lookupEndpoint(T key) { return this.endpointMap.get(key); } @@ -91,7 +94,7 @@ public abstract class AbstractMethodEndpointMapping extends AbstractEndpointM * @param endpoint the method endpoint instance * @throws BeansException if the endpoint could not be registered */ - protected void registerEndpoint(T key, MethodEndpoint endpoint) throws BeansException { + protected void registerEndpoint(T key, @Nullable MethodEndpoint endpoint) throws BeansException { Object mappedEndpoint = this.endpointMap.get(key); if (mappedEndpoint != null) { throw new ApplicationContextException("Cannot map endpoint [" + endpoint + "] on registration key [" + key @@ -136,8 +139,11 @@ public abstract class AbstractMethodEndpointMapping extends AbstractEndpointM * @see #getLookupKeysForMethod(Method) */ protected void registerMethods(String beanName) { + ApplicationContext applicationContext = getApplicationContext(); + Assert.notNull(applicationContext, "'applicationContext' must not be null"); Assert.hasText(beanName, "'beanName' must not be empty"); - Class endpointType = getApplicationContext().getType(beanName); + Class endpointType = applicationContext.getType(beanName); + Assert.state(endpointType != null, "No type found for bean with name [" + beanName + "]"); endpointType = ClassUtils.getUserClass(endpointType); Set methods = findEndpointMethods(endpointType, new ReflectionUtils.MethodFilter() { @@ -149,7 +155,7 @@ public abstract class AbstractMethodEndpointMapping extends AbstractEndpointM for (Method method : methods) { List keys = getLookupKeysForMethod(method); for (T key : keys) { - registerEndpoint(key, new MethodEndpoint(beanName, getApplicationContext(), method)); + registerEndpoint(key, new MethodEndpoint(beanName, applicationContext, method)); } } @@ -188,7 +194,7 @@ public abstract class AbstractMethodEndpointMapping extends AbstractEndpointM * @return a registration key, or {@code null} if the method is not to be registered * @see #getLookupKeysForMethod(Method) */ - protected T getLookupKeyForMethod(Method method) { + protected @Nullable T getLookupKeyForMethod(Method method) { return null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractQNameEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractQNameEndpointMapping.java index f03f0837..a0f56425 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractQNameEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractQNameEndpointMapping.java @@ -18,6 +18,8 @@ package org.springframework.ws.server.endpoint.mapping; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.context.MessageContext; import org.springframework.xml.namespace.QNameUtils; @@ -31,7 +33,7 @@ import org.springframework.xml.namespace.QNameUtils; public abstract class AbstractQNameEndpointMapping extends AbstractMapBasedEndpointMapping { @Override - protected final String getLookupKeyForMessage(MessageContext messageContext) throws Exception { + protected final @Nullable String getLookupKeyForMessage(MessageContext messageContext) throws Exception { QName qName = resolveQName(messageContext); return (qName != null) ? qName.toString() : null; } @@ -40,7 +42,7 @@ public abstract class AbstractQNameEndpointMapping extends AbstractMapBasedEndpo * Template method that resolves the qualified names from the given SOAP message. * @return an array of qualified names that serve as registration keys */ - protected abstract QName resolveQName(MessageContext messageContext) throws Exception; + protected abstract @Nullable QName resolveQName(MessageContext messageContext) throws Exception; @Override protected boolean validateLookupKey(String key) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMapping.java index 20fb1eaf..c718d36a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMapping.java @@ -23,6 +23,8 @@ import java.util.List; import javax.xml.namespace.QName; import javax.xml.transform.TransformerFactory; +import org.jspecify.annotations.Nullable; + import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; @@ -54,11 +56,7 @@ import org.springframework.xml.transform.TransformerFactoryUtils; */ public class PayloadRootAnnotationMethodEndpointMapping extends AbstractAnnotationMethodEndpointMapping { - private static TransformerFactory transformerFactory; - - static { - setTransformerFactory(TransformerFactoryUtils.newInstance()); - } + private static TransformerFactory transformerFactory = TransformerFactoryUtils.newInstance(); /** * Override the default {@link TransformerFactory}. @@ -69,7 +67,7 @@ public class PayloadRootAnnotationMethodEndpointMapping extends AbstractAnnotati } @Override - protected QName getLookupKeyForMessage(MessageContext messageContext) throws Exception { + protected @Nullable QName getLookupKeyForMessage(MessageContext messageContext) throws Exception { return PayloadRootUtils.getPayloadRootQName(messageContext.getRequest().getPayloadSource(), transformerFactory); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameEndpointMapping.java index d69bff34..46f67878 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameEndpointMapping.java @@ -20,6 +20,8 @@ import javax.xml.namespace.QName; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.endpoint.support.PayloadRootUtils; import org.springframework.xml.transform.TransformerFactoryUtils; @@ -49,11 +51,7 @@ import org.springframework.xml.transform.TransformerFactoryUtils; */ public class PayloadRootQNameEndpointMapping extends AbstractQNameEndpointMapping { - private static TransformerFactory transformerFactory; - - static { - setTransformerFactory(TransformerFactoryUtils.newInstance()); - } + private static TransformerFactory transformerFactory = TransformerFactoryUtils.newInstance(); /** * Override the default {@link TransformerFactory}. @@ -64,7 +62,7 @@ public class PayloadRootQNameEndpointMapping extends AbstractQNameEndpointMappin } @Override - protected QName resolveQName(MessageContext messageContext) throws TransformerException { + protected @Nullable QName resolveQName(MessageContext messageContext) throws TransformerException { return PayloadRootUtils.getPayloadRootQName(messageContext.getRequest().getPayloadSource(), transformerFactory); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/SimpleMethodEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/SimpleMethodEndpointMapping.java index ca22934d..e0af54fe 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/SimpleMethodEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/SimpleMethodEndpointMapping.java @@ -22,6 +22,8 @@ import javax.xml.namespace.QName; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; @@ -42,7 +44,7 @@ import org.springframework.xml.transform.TransformerFactoryUtils; * * public Source handleMyMessage(Source source) { * ... - * } + * } * } * * @@ -61,15 +63,16 @@ public class SimpleMethodEndpointMapping extends AbstractMethodEndpointMapping namespaces; + private @Nullable Map namespaces; - private TransformerFactory transformerFactory; + private final TransformerFactory transformerFactory = TransformerFactoryUtils.newInstance(); /** Sets the XPath expression to be used. */ public void setExpression(String expression) { @@ -94,11 +97,10 @@ public class XPathPayloadEndpointMapping extends AbstractMapBasedEndpointMapping else { this.expression = XPathExpressionFactory.createXPathExpression(this.expressionString, this.namespaces); } - this.transformerFactory = TransformerFactoryUtils.newInstance(); } @Override - protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception { + protected @Nullable String getLookupKeyForMessage(MessageContext messageContext) throws Exception { Element payloadElement = getMessagePayloadElement(messageContext.getRequest()); return this.expression.evaluateAsString(payloadElement); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/jaxb/XmlRootElementEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/jaxb/XmlRootElementEndpointMapping.java index 4f1b0c8b..311b990c 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/jaxb/XmlRootElementEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/jaxb/XmlRootElementEndpointMapping.java @@ -25,6 +25,7 @@ import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.JAXBIntrospector; import jakarta.xml.bind.annotation.XmlRootElement; +import org.jspecify.annotations.Nullable; import org.springframework.core.MethodParameter; import org.springframework.ws.context.MessageContext; @@ -64,7 +65,7 @@ public class XmlRootElementEndpointMapping extends AbstractAnnotationMethodEndpo } @Override - protected QName getLookupKeyForMethod(Method method) { + protected @Nullable QName getLookupKeyForMethod(Method method) { Class[] parameterTypes = method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { MethodParameter methodParameter = new MethodParameter(method, i); @@ -80,7 +81,7 @@ public class XmlRootElementEndpointMapping extends AbstractAnnotationMethodEndpo return null; } - private QName handleRootElement(Class parameterType) { + private @Nullable QName handleRootElement(Class parameterType) { try { Object param = parameterType.getDeclaredConstructor().newInstance(); QName result = getElementName(parameterType, param); @@ -94,7 +95,7 @@ public class XmlRootElementEndpointMapping extends AbstractAnnotationMethodEndpo return null; } - private QName getElementName(Class parameterType, Object param) { + private @Nullable QName getElementName(Class parameterType, Object param) { try { JAXBContext context = JAXBContext.newInstance(parameterType); JAXBIntrospector introspector = context.createJAXBIntrospector(); @@ -106,7 +107,7 @@ public class XmlRootElementEndpointMapping extends AbstractAnnotationMethodEndpo } @Override - protected QName getLookupKeyForMessage(MessageContext messageContext) throws Exception { + protected @Nullable QName getLookupKeyForMessage(MessageContext messageContext) throws Exception { return PayloadRootUtils.getPayloadRootQName(messageContext.getRequest().getPayloadSource(), this.transformerHelper); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/jaxb/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/jaxb/package-info.java index f4d91caa..ecac9237 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/jaxb/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/jaxb/package-info.java @@ -17,4 +17,7 @@ /** * Provides JAXB2-based {@code EndpointMapping} implementations. */ +@NullMarked package org.springframework.ws.server.endpoint.mapping.jaxb; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/package-info.java index 363c9b60..6aad1919 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/mapping/package-info.java @@ -17,4 +17,7 @@ /** * Provides miscellaneous endpoints {@code EndpointMapping} implementations. */ +@NullMarked package org.springframework.ws.server.endpoint.mapping; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/package-info.java index dd6b6190..d8160c8d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/package-info.java @@ -17,4 +17,7 @@ /** * Provides standard endpoint, and {@code EndpointAdapter} implementations. */ +@NullMarked package org.springframework.ws.server.endpoint; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/support/PayloadRootUtils.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/support/PayloadRootUtils.java index de6dcc94..6b94060d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/support/PayloadRootUtils.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/support/PayloadRootUtils.java @@ -30,11 +30,13 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; +import org.springframework.lang.Contract; import org.springframework.xml.namespace.QNameUtils; import org.springframework.xml.transform.TransformerHelper; import org.springframework.xml.transform.TraxUtils; @@ -57,12 +59,13 @@ public abstract class PayloadRootUtils { * not a {@code DOMSource} * @return the root element, or {@code null} if {@code source} is {@code null} */ - public static QName getPayloadRootQName(Source source, TransformerFactory transformerFactory) + @Contract("!null, _ -> !null") + public static @Nullable QName getPayloadRootQName(@Nullable Source source, TransformerFactory transformerFactory) throws TransformerException { return getPayloadRootQName(source, new TransformerHelper(transformerFactory)); } - public static QName getPayloadRootQName(Source source, TransformerHelper transformerHelper) + public static @Nullable QName getPayloadRootQName(@Nullable Source source, TransformerHelper transformerHelper) throws TransformerException { if (source == null) { return null; @@ -91,7 +94,7 @@ public abstract class PayloadRootUtils { private static final class PayloadRootSourceCallback implements TraxUtils.SourceCallback { - private QName result; + private @Nullable QName result; @Override public void domSource(Node node) throws Exception { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/support/package-info.java index e5592a66..12857fb6 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/support/package-info.java @@ -18,4 +18,7 @@ * Provides helper classes for {@code EndpointAdapter}, {@code EndpointInterceptor}, and * {@code EndpointMapping} implementations. */ +@NullMarked package org.springframework.ws.server.endpoint.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/server/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/server/package-info.java index b0785994..d72acf02 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/server/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/server/package-info.java @@ -17,4 +17,7 @@ /** * Contains classes for server-side Spring-WS support. */ +@NullMarked package org.springframework.ws.server; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/AbstractSoapMessage.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/AbstractSoapMessage.java index 90160b67..c8032377 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/AbstractSoapMessage.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/AbstractSoapMessage.java @@ -20,6 +20,8 @@ import javax.xml.namespace.QName; import javax.xml.transform.Result; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.mime.AbstractMimeMessage; /** @@ -31,7 +33,7 @@ import org.springframework.ws.mime.AbstractMimeMessage; */ public abstract class AbstractSoapMessage extends AbstractMimeMessage implements SoapMessage { - private SoapVersion version; + private @Nullable SoapVersion version; /** Returns {@code getEnvelope().getBody()}. */ @Override @@ -41,13 +43,13 @@ public abstract class AbstractSoapMessage extends AbstractMimeMessage implements /** Returns {@code getEnvelope().getHeader()}. */ @Override - public final SoapHeader getSoapHeader() { + public final @Nullable SoapHeader getSoapHeader() { return getEnvelope().getHeader(); } /** Returns {@code getSoapBody().getPayloadSource()}. */ @Override - public final Source getPayloadSource() { + public final @Nullable Source getPayloadSource() { return getSoapBody().getPayloadSource(); } @@ -65,8 +67,8 @@ public abstract class AbstractSoapMessage extends AbstractMimeMessage implements /** Returns {@code getSoapBody().getFault().getFaultCode()}. */ @Override - public final QName getFaultCode() { - if (hasFault()) { + public final @Nullable QName getFaultCode() { + if (hasFault() && getSoapBody().getFault() != null) { return getSoapBody().getFault().getFaultCode(); } else { @@ -76,8 +78,8 @@ public abstract class AbstractSoapMessage extends AbstractMimeMessage implements /** Returns {@code getSoapBody().getFault().getFaultStringOrReason()}. */ @Override - public final String getFaultReason() { - if (hasFault()) { + public final @Nullable String getFaultReason() { + if (hasFault() && getSoapBody().getFault() != null) { return getSoapBody().getFault().getFaultStringOrReason(); } else { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapBody.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapBody.java index 22ee5ad4..0d71a7ce 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapBody.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapBody.java @@ -21,6 +21,8 @@ import java.util.Locale; import javax.xml.transform.Result; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; /** @@ -45,7 +47,7 @@ public interface SoapBody extends SoapElement { * @return the message contents * @see WebServiceMessage#getPayloadSource() */ - Source getPayloadSource(); + @Nullable Source getPayloadSource(); /** * Returns a {@code Result} that represents the contents of the body. @@ -112,6 +114,6 @@ public interface SoapBody extends SoapElement { * Returns the {@code SoapFault} of this body. * @return the {@code SoapFault}, or {@code null} if none is present */ - SoapFault getFault(); + @Nullable SoapFault getFault(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapEnvelope.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapEnvelope.java index b5e54062..f9e80f22 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapEnvelope.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapEnvelope.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap; +import org.jspecify.annotations.Nullable; + /** * Represents the {@code Envelope} element in a SOAP message. The header contains the * optional {@code SoapHeader} and {@code SoapBody}. @@ -30,7 +32,7 @@ public interface SoapEnvelope extends SoapElement { * @return the {@code SoapHeader}, or {@code null} * @throws SoapHeaderException if the header cannot be returned */ - SoapHeader getHeader() throws SoapHeaderException; + @Nullable SoapHeader getHeader() throws SoapHeaderException; /** * Returns the {@code SoapBody}. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapFault.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapFault.java index a8d1e396..ac8b4f4e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapFault.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapFault.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + /** * Represent the {@code Fault} element in the body of a SOAP message. *

@@ -42,7 +44,7 @@ public interface SoapFault extends SoapElement { * this returns the fault string. For SOAP 1.2, this returns the fault reason for the * default locale. */ - String getFaultStringOrReason(); + @Nullable String getFaultStringOrReason(); /** * Return the optional fault actor or role. For SOAP 1.1, this returns the URI of the @@ -50,7 +52,7 @@ public interface SoapFault extends SoapElement { * identifies the role in which the node was operating at the point the fault * occurred. */ - String getFaultActorOrRole(); + @Nullable String getFaultActorOrRole(); /** * Set the fault actor or role. For SOAP 1.1, this sets the actor. For SOAP 1.2, this @@ -62,7 +64,7 @@ public interface SoapFault extends SoapElement { * Return the optional {@linkplain SoapFaultDetail detail element} of this fault. * @return a fault detail */ - SoapFaultDetail getFaultDetail(); + @Nullable SoapFaultDetail getFaultDetail(); /** * Create a {@link SoapFaultDetail} and assign it to this fault. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapFaultDetailElement.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapFaultDetailElement.java index 6573dd3b..0a3af070 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapFaultDetailElement.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapFaultDetailElement.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap; import javax.xml.transform.Result; +import org.jspecify.annotations.Nullable; + /** * Represents the content for an individual SOAP detail entry in a SOAP Message. All * {@code SoapFaultDetailElement}s are contained in a {@code SoapDetail}. @@ -35,6 +37,6 @@ public interface SoapFaultDetailElement extends SoapElement { Result getResult(); /** Adds a new text node to this element. */ - void addText(String text); + void addText(@Nullable String text); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapMessage.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapMessage.java index a27140f4..f9f07757 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapMessage.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/SoapMessage.java @@ -16,6 +16,7 @@ package org.springframework.ws.soap; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.springframework.ws.FaultAwareWebServiceMessage; @@ -64,7 +65,7 @@ public interface SoapMessage extends MimeMessage, FaultAwareWebServiceMessage { * method for {@code getEnvelope().getHeader()}. * @see SoapEnvelope#getHeader() */ - SoapHeader getSoapHeader() throws SoapHeaderException; + @Nullable SoapHeader getSoapHeader() throws SoapHeaderException; /** * Returns the SOAP version of this message. This can be either SOAP 1.1 or SOAP 1.2. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/client/ActionCallback.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/client/ActionCallback.java index 338f74b4..8eb4bc9a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/client/ActionCallback.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/client/ActionCallback.java @@ -22,6 +22,8 @@ import java.net.URISyntaxException; import javax.xml.transform.TransformerException; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.client.core.WebServiceMessageCallback; @@ -58,17 +60,17 @@ public class ActionCallback implements WebServiceMessageCallback { private final URI action; - private final URI to; + private @Nullable final URI to; private boolean shouldInitializeTo; private MessageIdStrategy messageIdStrategy; - private EndpointReference from; + private @Nullable EndpointReference from; - private EndpointReference replyTo; + private @Nullable EndpointReference replyTo; - private EndpointReference faultTo; + private @Nullable EndpointReference faultTo; /** * Create a new {@code ActionCallback} with the given {@code Action}. @@ -118,7 +120,7 @@ public class ActionCallback implements WebServiceMessageCallback { * @param version the WS-Addressing version to use * @param to the value of the destination property */ - public ActionCallback(URI action, AddressingVersion version, URI to) { + public ActionCallback(URI action, AddressingVersion version, @Nullable URI to) { Assert.notNull(action, "'action' must not be null"); Assert.notNull(version, "'version' must not be null"); this.action = action; @@ -165,7 +167,7 @@ public class ActionCallback implements WebServiceMessageCallback { * Returns the {@code From}. * @see org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getFrom() */ - public EndpointReference getFrom() { + public @Nullable EndpointReference getFrom() { return this.from; } @@ -181,7 +183,7 @@ public class ActionCallback implements WebServiceMessageCallback { * Returns the {@code ReplyTo}. * @see org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getReplyTo() */ - public EndpointReference getReplyTo() { + public @Nullable EndpointReference getReplyTo() { return this.replyTo; } @@ -197,7 +199,7 @@ public class ActionCallback implements WebServiceMessageCallback { * Returns the {@code FaultTo}. * @see org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getFaultTo() */ - public EndpointReference getFaultTo() { + public @Nullable EndpointReference getFaultTo() { return this.faultTo; } @@ -216,7 +218,7 @@ public class ActionCallback implements WebServiceMessageCallback { * {@link org.springframework.ws.transport.WebServiceConnection#getUri() connection * URI} if no destination was set. */ - protected URI getTo() { + protected @Nullable URI getTo() { if (this.to == null && (isToHeaderRequired() || this.shouldInitializeTo)) { TransportContext transportContext = TransportContextHolder.getTransportContext(); if (transportContext != null && transportContext.getConnection() != null) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/client/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/client/package-info.java index ba24782d..3e3e7e59 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/client/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/client/package-info.java @@ -17,4 +17,7 @@ /** * Client-side WS-Addressing support. */ +@NullMarked package org.springframework.ws.soap.addressing.client; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/core/MessageAddressingProperties.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/core/MessageAddressingProperties.java index dbe801bd..60e44726 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/core/MessageAddressingProperties.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/core/MessageAddressingProperties.java @@ -22,6 +22,7 @@ import java.net.URI; import java.util.Collections; import java.util.List; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Node; /** @@ -41,19 +42,19 @@ public final class MessageAddressingProperties implements Serializable { @Serial private static final long serialVersionUID = -6980663311446506672L; - private final URI to; + private final @Nullable URI to; - private final EndpointReference from; + private final @Nullable EndpointReference from; - private final EndpointReference replyTo; + private final @Nullable EndpointReference replyTo; - private final EndpointReference faultTo; + private final @Nullable EndpointReference faultTo; - private final URI action; + private final @Nullable URI action; - private final URI messageId; + private final @Nullable URI messageId; - private final URI relatesTo; + private final @Nullable URI relatesTo; private final List referenceProperties; @@ -68,8 +69,9 @@ public final class MessageAddressingProperties implements Serializable { * @param action the value of the action property * @param messageId the value of the message id property */ - public MessageAddressingProperties(URI to, EndpointReference from, EndpointReference replyTo, - EndpointReference faultTo, URI action, URI messageId) { + public MessageAddressingProperties(@Nullable URI to, @Nullable EndpointReference from, + @Nullable EndpointReference replyTo, @Nullable EndpointReference faultTo, @Nullable URI action, + @Nullable URI messageId) { this.to = to; this.from = from; this.replyTo = replyTo; @@ -89,7 +91,8 @@ public final class MessageAddressingProperties implements Serializable { * @param messageId the value of the message id property * @param relatesTo the value of the relates to property */ - private MessageAddressingProperties(EndpointReference epr, URI action, URI messageId, URI relatesTo) { + private MessageAddressingProperties(EndpointReference epr, @Nullable URI action, URI messageId, + @Nullable URI relatesTo) { this.to = epr.getAddress(); this.action = action; this.messageId = messageId; @@ -102,37 +105,37 @@ public final class MessageAddressingProperties implements Serializable { } /** Returns the value of the destination property. */ - public URI getTo() { + public @Nullable URI getTo() { return this.to; } /** Returns the value of the source endpoint property. */ - public EndpointReference getFrom() { + public @Nullable EndpointReference getFrom() { return this.from; } /** Returns the value of the reply endpoint property. */ - public EndpointReference getReplyTo() { + public @Nullable EndpointReference getReplyTo() { return this.replyTo; } /** Returns the value of the fault endpoint property. */ - public EndpointReference getFaultTo() { + public @Nullable EndpointReference getFaultTo() { return this.faultTo; } /** Returns the value of the action property. */ - public URI getAction() { + public @Nullable URI getAction() { return this.action; } /** Returns the value of the message id property. */ - public URI getMessageId() { + public @Nullable URI getMessageId() { return this.messageId; } /** Returns the value of the relationship property. */ - public URI getRelatesTo() { + public @Nullable URI getRelatesTo() { return this.relatesTo; } @@ -156,7 +159,7 @@ public final class MessageAddressingProperties implements Serializable { * @param epr the endpoint reference to create a reply to * @param action the action */ - public MessageAddressingProperties getReplyProperties(EndpointReference epr, URI action, URI messageId) { + public MessageAddressingProperties getReplyProperties(EndpointReference epr, @Nullable URI action, URI messageId) { return new MessageAddressingProperties(epr, action, messageId, this.messageId); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/core/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/core/package-info.java index 6c6b6ea0..7463316f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/core/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/core/package-info.java @@ -18,4 +18,7 @@ * Core package for WS-Addressing support. Contains the {@code EndpointReference} and * {@code MessageAddressingProperties} classes. */ +@NullMarked package org.springframework.ws.soap.addressing.core; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdStrategy.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdStrategy.java index 585304b4..dd784ec2 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdStrategy.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdStrategy.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.addressing.messageid; import java.net.URI; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapMessage; /** @@ -34,7 +36,7 @@ public interface MessageIdStrategy { * @param messageId the message id * @return {@code true} if a duplicate; {@code false} otherwise */ - boolean isDuplicate(URI messageId); + boolean isDuplicate(@Nullable URI messageId); /** * Returns a new WS-Addressing {@code MessageID} for the given {@link SoapMessage}. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategy.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategy.java index 0ef9a09d..4d446262 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategy.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategy.java @@ -19,6 +19,8 @@ package org.springframework.ws.soap.addressing.messageid; import java.net.URI; import java.util.UUID; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapMessage; /** @@ -39,7 +41,7 @@ public class UuidMessageIdStrategy implements MessageIdStrategy { /** Returns {@code false}. */ @Override - public boolean isDuplicate(URI messageId) { + public boolean isDuplicate(@Nullable URI messageId) { return false; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/package-info.java index 6b7b2f81..09684a9b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/messageid/package-info.java @@ -17,4 +17,7 @@ /** * Contains various strategies for generating WS-Addressing MessageIDs. */ +@NullMarked package org.springframework.ws.soap.addressing.messageid; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/package-info.java index d5ae6d0a..64a7f85e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/package-info.java @@ -17,4 +17,7 @@ /** * Provides WS-Addressing implementation classes. */ +@NullMarked package org.springframework.ws.soap.addressing; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionEndpointMapping.java index 7e6042c4..b2b3bbae 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionEndpointMapping.java @@ -20,6 +20,8 @@ import java.net.URI; import java.util.HashMap; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.BeansException; import org.springframework.util.Assert; import org.springframework.ws.soap.addressing.core.MessageAddressingProperties; @@ -81,7 +83,7 @@ public abstract class AbstractActionEndpointMapping extends AbstractAddressingEn } @Override - protected final Object getEndpointInternal(MessageAddressingProperties map) { + protected final @Nullable Object getEndpointInternal(MessageAddressingProperties map) { URI action = map.getAction(); if (this.logger.isDebugEnabled()) { this.logger.debug("Looking up endpoint for action [" + action + "]"); @@ -103,14 +105,14 @@ public abstract class AbstractActionEndpointMapping extends AbstractAddressingEn * @param endpoint the endpoint to return the address for * @return the endpoint address; or {@code null} to ignore the destination property */ - protected abstract URI getEndpointAddress(Object endpoint); + protected abstract @Nullable URI getEndpointAddress(Object endpoint); /** * Looks up an endpoint instance for the given action. All keys are tried in order. * @param action the action URI * @return the associated endpoint instance, or {@code null} if not found */ - protected Object lookupEndpoint(URI action) { + protected @Nullable Object lookupEndpoint(@Nullable URI action) { return this.endpointMap.get(action); } @@ -149,7 +151,7 @@ public abstract class AbstractActionEndpointMapping extends AbstractAddressingEn } @Override - protected URI getResponseAction(Object endpoint, MessageAddressingProperties requestMap) { + protected @Nullable URI getResponseAction(Object endpoint, MessageAddressingProperties requestMap) { URI requestAction = requestMap.getAction(); if (requestAction != null) { return URI.create(requestAction + getOutputActionSuffix()); @@ -160,7 +162,7 @@ public abstract class AbstractActionEndpointMapping extends AbstractAddressingEn } @Override - protected URI getFaultAction(Object endpoint, MessageAddressingProperties requestMap) { + protected @Nullable URI getFaultAction(Object endpoint, MessageAddressingProperties requestMap) { URI requestAction = requestMap.getAction(); if (requestAction != null) { return URI.create(requestAction + getFaultActionSuffix()); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionMethodEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionMethodEndpointMapping.java index 6d6c9a9f..74149706 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionMethodEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionMethodEndpointMapping.java @@ -19,6 +19,8 @@ package org.springframework.ws.soap.addressing.server; import java.lang.reflect.Method; import java.net.URI; +import org.jspecify.annotations.Nullable; + import org.springframework.aop.support.AopUtils; import org.springframework.util.Assert; import org.springframework.ws.server.endpoint.MethodEndpoint; @@ -57,7 +59,7 @@ public abstract class AbstractActionMethodEndpointMapping extends AbstractAction } /** Returns the action value for the specified method. */ - protected abstract URI getActionForMethod(Method method); + protected abstract @Nullable URI getActionForMethod(Method method); /** * Return the class or interface to use for method reflection. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractAddressingEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractAddressingEndpointMapping.java index d55ea3e1..f980a352 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractAddressingEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractAddressingEndpointMapping.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.xml.transform.TransformerException; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.InitializingBean; @@ -84,7 +86,7 @@ import org.springframework.xml.transform.TransformerObjectSupport; public abstract class AbstractAddressingEndpointMapping extends TransformerObjectSupport implements SoapEndpointMapping, ApplicationContextAware, InitializingBean, Ordered { - private String[] actorsOrRoles; + private String @Nullable [] actorsOrRoles; private boolean isUltimateReceiver = true; @@ -100,22 +102,17 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec private SmartEndpointInterceptor[] smartInterceptors = new SmartEndpointInterceptor[0]; - private ApplicationContext applicationContext; + private @Nullable ApplicationContext applicationContext; private int order = Integer.MAX_VALUE; // default: same as non-Ordered - /** Protected constructor. Initializes the default settings. */ - protected AbstractAddressingEndpointMapping() { - initDefaultStrategies(); - } - /** - * Initializes the default implementation for this mapping's strategies: the + * Create a new instance with the default strategies, that is the * {@link org.springframework.ws.soap.addressing.version.Addressing200408} and * {@link org.springframework.ws.soap.addressing.version.Addressing10} versions of the * specification, and the {@link UuidMessageIdStrategy}. */ - protected void initDefaultStrategies() { + protected AbstractAddressingEndpointMapping() { this.versions = new AddressingVersion[] { new Addressing200408(), new Addressing10() }; this.messageIdStrategy = new UuidMessageIdStrategy(); } @@ -138,6 +135,7 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec } public ApplicationContext getApplicationContext() { + Assert.state(this.applicationContext != null, "No ApplicationContext set"); return this.applicationContext; } @@ -243,17 +241,16 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec if (this.logger.isInfoEnabled()) { this.logger.info("Supporting " + Arrays.asList(this.versions)); } - if (getApplicationContext() != null) { - Map smartInterceptors = BeanFactoryUtils - .beansOfTypeIncludingAncestors(getApplicationContext(), SmartEndpointInterceptor.class, true, false); - if (!smartInterceptors.isEmpty()) { - this.smartInterceptors = smartInterceptors.values().toArray(new SmartEndpointInterceptor[0]); - } + Map smartInterceptors = BeanFactoryUtils + .beansOfTypeIncludingAncestors(getApplicationContext(), SmartEndpointInterceptor.class, true, false); + if (!smartInterceptors.isEmpty()) { + this.smartInterceptors = smartInterceptors.values().toArray(new SmartEndpointInterceptor[0]); } } @Override - public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws TransformerException { + public final @Nullable EndpointInvocationChain getEndpoint(MessageContext messageContext) + throws TransformerException { Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest()); SoapMessage request = (SoapMessage) messageContext.getRequest(); for (AddressingVersion version : this.versions) { @@ -262,9 +259,6 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec this.logger.debug("Request [" + request + "] uses [" + version + "]"); } MessageAddressingProperties requestMap = version.getMessageAddressingProperties(request); - if (requestMap == null) { - return null; - } Object endpoint = getEndpointInternal(requestMap); if (endpoint == null) { return null; @@ -294,11 +288,9 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec interceptors.add(addressingInterceptor); interceptors.addAll(Arrays.asList(this.postInterceptors)); - if (this.smartInterceptors != null) { - for (SmartEndpointInterceptor smartInterceptor : this.smartInterceptors) { - if (smartInterceptor.shouldIntercept(messageContext, endpoint)) { - interceptors.add(smartInterceptor); - } + for (SmartEndpointInterceptor smartInterceptor : this.smartInterceptors) { + if (smartInterceptor.shouldIntercept(messageContext, endpoint)) { + interceptors.add(smartInterceptor); } } @@ -346,7 +338,7 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec * @param map the message addressing properties * @return the endpoint, or {@code null} */ - protected abstract Object getEndpointInternal(MessageAddressingProperties map); + protected abstract @Nullable Object getEndpointInternal(MessageAddressingProperties map); /** * Provides the WS-Addressing Action for response messages, given the endpoint, and @@ -355,7 +347,7 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec * @param requestMap the MAP for the request * @return the response Action */ - protected abstract URI getResponseAction(Object endpoint, MessageAddressingProperties requestMap); + protected abstract @Nullable URI getResponseAction(Object endpoint, MessageAddressingProperties requestMap); /** * Provides the WS-Addressing Action for response fault messages, given the endpoint, @@ -364,6 +356,6 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec * @param requestMap the MAP for the request * @return the response Action */ - protected abstract URI getFaultAction(Object endpoint, MessageAddressingProperties requestMap); + protected abstract @Nullable URI getFaultAction(Object endpoint, MessageAddressingProperties requestMap); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java index 1e479393..925d1504 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java @@ -21,7 +21,9 @@ import java.net.URI; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; +import org.springframework.lang.Contract; import org.springframework.util.Assert; import org.springframework.ws.context.MessageContext; import org.springframework.ws.soap.SoapHeaderElement; @@ -51,12 +53,12 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { private final WebServiceMessageSender[] messageSenders; - private final URI replyAction; + private final @Nullable URI replyAction; - private final URI faultAction; + private final @Nullable URI faultAction; AddressingEndpointInterceptor(AddressingVersion version, MessageIdStrategy messageIdStrategy, - WebServiceMessageSender[] messageSenders, URI replyAction, URI faultAction) { + WebServiceMessageSender[] messageSenders, @Nullable URI replyAction, @Nullable URI faultAction) { Assert.notNull(version, "version must not be null"); Assert.notNull(messageIdStrategy, "messageIdStrategy must not be null"); Assert.notNull(messageSenders, "'messageSenders' must not be null"); @@ -116,7 +118,8 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { } } - private boolean handleNoneAddress(MessageContext messageContext, EndpointReference replyEpr) { + @Contract("_, null -> true") + private boolean handleNoneAddress(MessageContext messageContext, @Nullable EndpointReference replyEpr) { if (replyEpr == null || this.version.hasNoneAddress(replyEpr)) { if (logger.isDebugEnabled()) { logger.debug("Request [" + messageContext.getRequest() + "] has [" + replyEpr @@ -173,7 +176,7 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { } @Override - public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + public void afterCompletion(MessageContext messageContext, Object endpoint, @Nullable Exception ex) { } @Override diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AnnotationActionEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AnnotationActionEndpointMapping.java index 5ef29a8f..b3fc6046 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AnnotationActionEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AnnotationActionEndpointMapping.java @@ -21,6 +21,8 @@ import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.StringUtils; @@ -72,7 +74,7 @@ public class AnnotationActionEndpointMapping extends AbstractActionMethodEndpoin * the {@link Action} annotation value. */ @Override - protected URI getActionForMethod(Method method) { + protected @Nullable URI getActionForMethod(Method method) { Action action = method.getAnnotation(Action.class); if (action != null && StringUtils.hasText(action.value())) { try { @@ -96,7 +98,7 @@ public class AnnotationActionEndpointMapping extends AbstractActionMethodEndpoin * @return the endpoint address; or {@code null} to ignore the destination property */ @Override - protected URI getEndpointAddress(Object endpoint) { + protected @Nullable URI getEndpointAddress(Object endpoint) { MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint; Class endpointClass = methodEndpoint.getMethod().getDeclaringClass(); Address address = AnnotationUtils.findAnnotation(endpointClass, Address.class); @@ -109,7 +111,7 @@ public class AnnotationActionEndpointMapping extends AbstractActionMethodEndpoin } @Override - protected URI getResponseAction(Object endpoint, MessageAddressingProperties map) { + protected @Nullable URI getResponseAction(Object endpoint, MessageAddressingProperties map) { MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint; Action action = methodEndpoint.getMethod().getAnnotation(Action.class); if (action != null && StringUtils.hasText(action.output())) { @@ -121,7 +123,7 @@ public class AnnotationActionEndpointMapping extends AbstractActionMethodEndpoin } @Override - protected URI getFaultAction(Object endpoint, MessageAddressingProperties map) { + protected @Nullable URI getFaultAction(Object endpoint, MessageAddressingProperties map) { MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint; Action action = methodEndpoint.getMethod().getAnnotation(Action.class); if (action != null && StringUtils.hasText(action.fault())) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/SimpleActionEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/SimpleActionEndpointMapping.java index fb65455f..a9f18745 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/SimpleActionEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/SimpleActionEndpointMapping.java @@ -22,6 +22,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Properties; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.BeansException; /** @@ -57,7 +59,7 @@ public class SimpleActionEndpointMapping extends AbstractActionEndpointMapping { // contents will be copied over to endpointMap private final Map actionMap = new HashMap<>(); - private URI address; + private @Nullable URI address; /** * Map action URIs to endpoint bean names. This is the typical way of configuring this @@ -132,7 +134,7 @@ public class SimpleActionEndpointMapping extends AbstractActionEndpointMapping { } @Override - protected URI getEndpointAddress(Object endpoint) { + protected @Nullable URI getEndpointAddress(Object endpoint) { return this.address; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/annotation/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/annotation/package-info.java index 81884c7b..9fed797f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/annotation/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/annotation/package-info.java @@ -17,4 +17,7 @@ /** * Annotations for server-side WS-Addressing support. */ +@NullMarked package org.springframework.ws.soap.addressing.server.annotation; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/package-info.java index ace69c89..6e039f44 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/package-info.java @@ -17,4 +17,7 @@ /** * Server-side WS-Addressing support, in the form of {@code EndpointMappings}. */ +@NullMarked package org.springframework.ws.soap.addressing.server; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/AbstractAddressingVersion.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/AbstractAddressingVersion.java index d895e46b..f07f1a1b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/AbstractAddressingVersion.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/AbstractAddressingVersion.java @@ -34,10 +34,12 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.ws.soap.SoapFault; import org.springframework.ws.soap.SoapHeader; @@ -80,9 +82,9 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport private final XPathExpression addressExpression; - private final XPathExpression referencePropertiesExpression; + private final @Nullable XPathExpression referencePropertiesExpression; - private final XPathExpression referenceParametersExpression; + private final @Nullable XPathExpression referenceParametersExpression; protected AbstractAddressingVersion() { Map namespaces = new HashMap<>(); @@ -144,7 +146,7 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport return new MessageAddressingProperties(to, from, replyTo, faultTo, action, messageId); } - private URI getUri(Node node, XPathExpression expression) { + private @Nullable URI getUri(Node node, XPathExpression expression) { String messageId = expression.evaluateAsString(node); if (!StringUtils.hasLength(messageId)) { return null; @@ -158,7 +160,9 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport } private Element getSoapHeaderElement(SoapMessage message) { - Source source = message.getSoapHeader().getSource(); + SoapHeader soapHeader = message.getSoapHeader(); + Assert.notNull(soapHeader, "'soapHeader' must not be null"); + Source source = soapHeader.getSource(); if (source instanceof DOMSource domSource) { if (domSource.getNode() != null && domSource.getNode().getNodeType() == Node.ELEMENT_NODE) { return (Element) domSource.getNode(); @@ -176,7 +180,7 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport } /** Given a ReplyTo, FaultTo, or From node, returns an endpoint reference. */ - private EndpointReference getEndpointReference(Node node) { + private @Nullable EndpointReference getEndpointReference(@Nullable Node node) { if (node == null) { return null; } @@ -193,7 +197,7 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport @Override public void addAddressingHeaders(SoapMessage message, MessageAddressingProperties map) { - SoapHeader header = message.getSoapHeader(); + SoapHeader header = getSoapHeader(message); header.addNamespaceDeclaration(getNamespacePrefix(), getNamespaceUri()); // To if (map.getTo() != null) { @@ -217,7 +221,9 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport } // Action SoapHeaderElement action = header.addHeaderElement(getActionName()); - action.setText(map.getAction().toString()); + if (map.getAction() != null) { + action.setText((map.getAction().toString())); + } // MessageID if (map.getMessageId() != null) { SoapHeaderElement messageId = header.addHeaderElement(getMessageIdName()); @@ -238,8 +244,8 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport } /** Adds ReplyTo, FaultTo, or From EPR to the given header Element. */ - protected void addEndpointReference(SoapHeaderElement headerElement, EndpointReference epr) { - if (epr == null || epr.getAddress() == null) { + protected void addEndpointReference(SoapHeaderElement headerElement, @Nullable EndpointReference epr) { + if (epr == null) { return; } try { @@ -282,18 +288,18 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport } @Override - public final SoapFault addInvalidAddressingHeaderFault(SoapMessage message) { + public final @Nullable SoapFault addInvalidAddressingHeaderFault(SoapMessage message) { return addAddressingFault(message, getInvalidAddressingHeaderFaultSubcode(), getInvalidAddressingHeaderFaultReason()); } @Override - public final SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message) { + public final @Nullable SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message) { return addAddressingFault(message, getMessageAddressingHeaderRequiredFaultSubcode(), getMessageAddressingHeaderRequiredFaultReason()); } - private SoapFault addAddressingFault(SoapMessage message, QName subcode, String reason) { + private @Nullable SoapFault addAddressingFault(SoapMessage message, QName subcode, String reason) { if (message.getSoapBody() instanceof Soap11Body soapBody) { return soapBody.addFault(subcode, reason, Locale.ENGLISH); } @@ -379,7 +385,7 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport * reference. Returns {@code null} when reference properties are not supported by this * version of the spec. */ - protected QName getReferencePropertiesName() { + protected @Nullable QName getReferencePropertiesName() { return new QName(getNamespaceUri(), "ReferenceProperties", getNamespacePrefix()); } @@ -388,7 +394,7 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport * reference. Returns {@code null} when reference parameters are not supported by this * version of the spec. */ - protected QName getReferenceParametersName() { + protected @Nullable QName getReferenceParametersName() { return new QName(getNamespaceUri(), "ReferenceParameters", getNamespacePrefix()); } @@ -402,23 +408,23 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport } /** Returns the default To URI. */ - protected abstract URI getDefaultTo(); + protected abstract @Nullable URI getDefaultTo(); /** * Returns the default ReplyTo EPR. Can be based on the From EPR, or the anonymous * URI. */ - protected abstract EndpointReference getDefaultReplyTo(EndpointReference from); + protected abstract @Nullable EndpointReference getDefaultReplyTo(@Nullable EndpointReference from); /* * Address URIs */ /** Returns the anonymous URI. */ - protected abstract URI getAnonymous(); + protected abstract @Nullable URI getAnonymous(); /** Returns the none URI, or {@code null} if the spec does not define it. */ - protected abstract URI getNone(); + protected abstract @Nullable URI getNone(); /* * Faults @@ -442,4 +448,10 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport /** Returns the reason of the fault that indicates that a header is invalid. */ protected abstract String getInvalidAddressingHeaderFaultReason(); + private static SoapHeader getSoapHeader(SoapMessage message) { + SoapHeader soapHeader = message.getSoapHeader(); + Assert.notNull(soapHeader, "'soapHeader' must not be null"); + return soapHeader; + } + } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java index bf6952c0..4e4c8050 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java @@ -20,6 +20,8 @@ import java.net.URI; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.addressing.core.EndpointReference; @@ -68,7 +70,7 @@ public class Addressing10 extends AbstractAddressingVersion { } @Override - protected QName getReferencePropertiesName() { + protected @Nullable QName getReferencePropertiesName() { return null; } @@ -78,7 +80,7 @@ public class Addressing10 extends AbstractAddressingVersion { } @Override - protected EndpointReference getDefaultReplyTo(EndpointReference from) { + protected EndpointReference getDefaultReplyTo(@Nullable EndpointReference from) { return new EndpointReference(getAnonymous()); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing200408.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing200408.java index b59830de..c7632217 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing200408.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing200408.java @@ -20,6 +20,8 @@ import java.net.URI; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.addressing.core.EndpointReference; @@ -97,17 +99,17 @@ public class Addressing200408 extends AbstractAddressingVersion { } @Override - protected URI getDefaultTo() { + protected @Nullable URI getDefaultTo() { return null; } @Override - protected final EndpointReference getDefaultReplyTo(EndpointReference from) { + protected final @Nullable EndpointReference getDefaultReplyTo(@Nullable EndpointReference from) { return from; } @Override - protected final URI getNone() { + protected final @Nullable URI getNone() { return null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/AddressingVersion.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/AddressingVersion.java index 57cbf0b2..fc52a278 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/AddressingVersion.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/AddressingVersion.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.addressing.version; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapFault; import org.springframework.ws.soap.SoapHeaderElement; import org.springframework.ws.soap.SoapMessage; @@ -99,13 +101,13 @@ public interface AddressingVersion { * @see Invalid * Addressing Header */ - SoapFault addInvalidAddressingHeaderFault(SoapMessage message); + @Nullable SoapFault addInvalidAddressingHeaderFault(SoapMessage message); /** * Adds a Message Addressing Header Required fault to the given message. * @see Message * Addressing Header Required */ - SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message); + @Nullable SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/package-info.java index 58abc6f8..b3693231 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/package-info.java @@ -17,4 +17,7 @@ /** * Contains abstractions over various versions of the WS-Addressing specification. */ +@NullMarked package org.springframework.ws.soap.addressing.version; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AbstractPayload.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AbstractPayload.java index 0834911a..180988e0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AbstractPayload.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AbstractPayload.java @@ -24,6 +24,7 @@ import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMException; import org.apache.axiom.soap.SOAPBody; import org.apache.axiom.soap.SOAPFactory; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.util.xml.StaxUtils; @@ -49,7 +50,7 @@ abstract class AbstractPayload extends Payload { } @Override - public final Source getSource() { + public final @Nullable Source getSource() { try { OMElement payloadElement = getPayloadElement(); if (payloadElement != null) { @@ -83,7 +84,7 @@ abstract class AbstractPayload extends Payload { return this.axiomBody; } - protected OMElement getPayloadElement() throws OMException { + protected @Nullable OMElement getPayloadElement() throws OMException { return getAxiomBody().getFirstElement(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Body.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Body.java index 11877674..af641309 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Body.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Body.java @@ -29,6 +29,7 @@ import org.apache.axiom.soap.SOAPFault; import org.apache.axiom.soap.SOAPFaultCode; import org.apache.axiom.soap.SOAPFaultReason; import org.apache.axiom.soap.SOAPProcessingException; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -123,7 +124,7 @@ class AxiomSoap11Body extends AxiomSoapBody implements Soap11Body { faultCode.setText(code); } - private SOAPFault addStandardFault(String localName, String faultString, Locale locale) { + private SOAPFault addStandardFault(String localName, String faultString, @Nullable Locale locale) { Assert.notNull(faultString, "No faultString given"); try { AxiomUtils.removeContents(getAxiomBody()); @@ -151,7 +152,7 @@ class AxiomSoap11Body extends AxiomSoapBody implements Soap11Body { } @Override - public Soap11Fault getFault() { + public @Nullable Soap11Fault getFault() { SOAPFault axiomFault = getAxiomBody().getFault(); return (axiomFault != null) ? new AxiomSoap11Fault(axiomFault, getAxiomFactory()) : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Fault.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Fault.java index 3fbd4bce..1db43a3c 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Fault.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Fault.java @@ -23,6 +23,7 @@ import javax.xml.namespace.QName; import org.apache.axiom.om.OMAttribute; import org.apache.axiom.soap.SOAPFactory; import org.apache.axiom.soap.SOAPFault; +import org.jspecify.annotations.Nullable; import org.springframework.ws.soap.axiom.support.AxiomUtils; import org.springframework.ws.soap.soap11.Soap11Fault; @@ -45,7 +46,7 @@ class AxiomSoap11Fault extends AxiomSoapFault implements Soap11Fault { } @Override - public String getFaultStringOrReason() { + public @Nullable String getFaultStringOrReason() { if (getAxiomFault().getReason() != null) { return getAxiomFault().getReason().getText(); } @@ -53,7 +54,7 @@ class AxiomSoap11Fault extends AxiomSoapFault implements Soap11Fault { } @Override - public Locale getFaultStringLocale() { + public @Nullable Locale getFaultStringLocale() { if (getAxiomFault().getReason() != null) { OMAttribute langAttribute = getAxiomFault().getReason() .getAttribute(new QName("http://www.w3.org/XML/1998/namespace", "lang")); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Header.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Header.java index 349b3d3a..e2495a06 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Header.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Header.java @@ -24,6 +24,7 @@ import org.apache.axiom.soap.RolePlayer; import org.apache.axiom.soap.SOAPFactory; import org.apache.axiom.soap.SOAPHeader; import org.apache.axiom.soap.SOAPHeaderBlock; +import org.jspecify.annotations.Nullable; import org.springframework.util.ObjectUtils; import org.springframework.ws.soap.SoapHeaderElement; @@ -43,7 +44,7 @@ class AxiomSoap11Header extends AxiomSoapHeader implements Soap11Header { @Override @SuppressWarnings("unchecked") - public Iterator examineHeaderElementsToProcess(final String[] actors) { + public Iterator examineHeaderElementsToProcess(final String @Nullable [] actors) { RolePlayer rolePlayer = null; if (!ObjectUtils.isEmpty(actors)) { rolePlayer = new RolePlayer() { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Body.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Body.java index 90e9824f..3e957085 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Body.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Body.java @@ -29,6 +29,7 @@ import org.apache.axiom.soap.SOAPFaultReason; import org.apache.axiom.soap.SOAPFaultText; import org.apache.axiom.soap.SOAPFaultValue; import org.apache.axiom.soap.SOAPProcessingException; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.ws.soap.axiom.support.AxiomUtils; @@ -82,7 +83,7 @@ class AxiomSoap12Body extends AxiomSoapBody implements Soap12Body { return new AxiomSoap12Fault(fault, getAxiomFactory()); } - private SOAPFault addStandardFault(String localName, String faultStringOrReason, Locale locale) { + private SOAPFault addStandardFault(String localName, String faultStringOrReason, @Nullable Locale locale) { Assert.notNull(faultStringOrReason, "No faultStringOrReason given"); try { AxiomUtils.removeContents(getAxiomBody()); @@ -104,7 +105,7 @@ class AxiomSoap12Body extends AxiomSoapBody implements Soap12Body { } @Override - public Soap12Fault getFault() { + public @Nullable Soap12Fault getFault() { SOAPFault axiomFault = getAxiomBody().getFault(); return (axiomFault != null) ? new AxiomSoap12Fault(axiomFault, getAxiomFactory()) : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Fault.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Fault.java index 0d12b808..06269ca0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Fault.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Fault.java @@ -33,6 +33,7 @@ import org.apache.axiom.soap.SOAPFaultSubCode; import org.apache.axiom.soap.SOAPFaultText; import org.apache.axiom.soap.SOAPFaultValue; import org.apache.axiom.soap.SOAPProcessingException; +import org.jspecify.annotations.Nullable; import org.springframework.util.StringUtils; import org.springframework.ws.soap.axiom.support.AxiomUtils; @@ -107,7 +108,7 @@ class AxiomSoap12Fault extends AxiomSoapFault implements Soap12Fault { } @Override - public String getFaultNode() { + public @Nullable String getFaultNode() { SOAPFaultNode faultNode = getAxiomFault().getNode(); if (faultNode == null) { return null; @@ -130,12 +131,12 @@ class AxiomSoap12Fault extends AxiomSoapFault implements Soap12Fault { } @Override - public String getFaultStringOrReason() { + public @Nullable String getFaultStringOrReason() { return getFaultReasonText(Locale.getDefault()); } @Override - public String getFaultReasonText(Locale locale) { + public @Nullable String getFaultReasonText(Locale locale) { SOAPFaultReason faultReason = getAxiomFault().getReason(); String language = AxiomUtils.toLanguage(locale); SOAPFaultText faultText = faultReason.getSOAPFaultText(language); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Header.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Header.java index 3cc97ac9..1fe442e7 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Header.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Header.java @@ -30,6 +30,7 @@ import org.apache.axiom.soap.SOAPFactory; import org.apache.axiom.soap.SOAPHeader; import org.apache.axiom.soap.SOAPHeaderBlock; import org.apache.axiom.soap.SOAPProcessingException; +import org.jspecify.annotations.Nullable; import org.springframework.util.ObjectUtils; import org.springframework.ws.soap.SoapHeaderElement; @@ -81,8 +82,7 @@ class AxiomSoap12Header extends AxiomSoapHeader implements Soap12Header { } @Override - @SuppressWarnings("unchecked") - public Iterator examineHeaderElementsToProcess(final String[] roles, + public Iterator examineHeaderElementsToProcess(final String @Nullable [] roles, final boolean isUltimateDestination) throws SoapHeaderException { RolePlayer rolePlayer = null; if (!ObjectUtils.isEmpty(roles)) { @@ -97,7 +97,7 @@ class AxiomSoap12Header extends AxiomSoapHeader implements Soap12Header { } }; } - Iterator result = (Iterator) getAxiomHeader().getHeadersToProcess(rolePlayer); + Iterator result = getAxiomHeader().getHeadersToProcess(rolePlayer); return new AxiomSoapHeaderElementIterator(result); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapBody.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapBody.java index 4e9f6b53..c9125954 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapBody.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapBody.java @@ -24,6 +24,7 @@ import org.apache.axiom.om.OMDataSource; import org.apache.axiom.om.OMElement; import org.apache.axiom.soap.SOAPBody; import org.apache.axiom.soap.SOAPFactory; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.ws.soap.SoapBody; @@ -51,7 +52,7 @@ abstract class AxiomSoapBody extends AxiomSoapElement implements SoapBody { } @Override - public Source getPayloadSource() { + public @Nullable Source getPayloadSource() { return this.payload.getSource(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapEnvelope.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapEnvelope.java index 22d8da6f..f5407d5b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapEnvelope.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapEnvelope.java @@ -23,6 +23,7 @@ import org.apache.axiom.soap.SOAPBody; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.soap.SOAPFactory; import org.apache.axiom.soap.SOAPHeader; +import org.jspecify.annotations.Nullable; import org.springframework.ws.soap.SoapBody; import org.springframework.ws.soap.SoapEnvelope; @@ -38,10 +39,10 @@ class AxiomSoapEnvelope extends AxiomSoapElement implements SoapEnvelope { boolean payloadCaching; - private AxiomSoapBody body; - private final boolean langAttributeOnSoap11FaultString; + private @Nullable AxiomSoapBody body; + AxiomSoapEnvelope(SOAPEnvelope axiomEnvelope, SOAPFactory axiomFactory, boolean payloadCaching, boolean langAttributeOnSoap11FaultString) { super(axiomEnvelope, axiomFactory); @@ -50,7 +51,7 @@ class AxiomSoapEnvelope extends AxiomSoapElement implements SoapEnvelope { } @Override - public SoapHeader getHeader() { + public @Nullable SoapHeader getHeader() { try { if (getAxiomEnvelope().getHeader() == null) { return null; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapFault.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapFault.java index 7a86d2d6..f405c133 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapFault.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapFault.java @@ -22,6 +22,7 @@ import org.apache.axiom.soap.SOAPFault; import org.apache.axiom.soap.SOAPFaultDetail; import org.apache.axiom.soap.SOAPFaultRole; import org.apache.axiom.soap.SOAPProcessingException; +import org.jspecify.annotations.Nullable; import org.springframework.ws.soap.SoapFault; import org.springframework.ws.soap.SoapFaultDetail; @@ -38,7 +39,7 @@ abstract class AxiomSoapFault extends AxiomSoapElement implements SoapFault { } @Override - public String getFaultActorOrRole() { + public @Nullable String getFaultActorOrRole() { SOAPFaultRole faultRole = getAxiomFault().getRole(); return (faultRole != null) ? faultRole.getRoleValue() : null; } @@ -56,7 +57,7 @@ abstract class AxiomSoapFault extends AxiomSoapElement implements SoapFault { } @Override - public SoapFaultDetail getFaultDetail() { + public @Nullable SoapFaultDetail getFaultDetail() { try { SOAPFaultDetail axiomFaultDetail = getAxiomFault().getDetail(); return (axiomFaultDetail != null) ? new AxiomSoapFaultDetail(axiomFaultDetail, getAxiomFactory()) : null; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapFaultDetailElement.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapFaultDetailElement.java index b24cac28..ad0de01b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapFaultDetailElement.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapFaultDetailElement.java @@ -21,6 +21,7 @@ import javax.xml.transform.Result; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMException; import org.apache.axiom.soap.SOAPFactory; +import org.jspecify.annotations.Nullable; import org.springframework.ws.soap.SoapFaultDetailElement; @@ -48,7 +49,7 @@ class AxiomSoapFaultDetailElement extends AxiomSoapElement implements SoapFaultD } @Override - public void addText(String text) { + public void addText(@Nullable String text) { try { getAxiomElement().setText(text); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java index 862d050f..66b4f001 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java @@ -40,6 +40,7 @@ import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.soap.SOAPFactory; import org.apache.axiom.soap.SOAPMessage; import org.apache.axiom.soap.SOAPProcessingException; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.springframework.util.Assert; @@ -76,13 +77,13 @@ public class AxiomSoapMessage extends AbstractSoapMessage implements StreamingWe private final boolean payloadCaching; - private AxiomSoapEnvelope envelope; + private @Nullable AxiomSoapEnvelope envelope; private String soapAction; private final boolean langAttributeOnSoap11FaultString; - private OMOutputFormat outputFormat; + private @Nullable OMOutputFormat outputFormat; /** * Create a new, empty {@code AxiomSoapMessage}. @@ -237,7 +238,7 @@ public class AxiomSoapMessage extends AbstractSoapMessage implements StreamingWe } @Override - public Attachment getAttachment(String contentId) { + public @Nullable Attachment getAttachment(String contentId) { Assert.hasLength(contentId, "contentId must not be empty"); if (contentId.startsWith("<") && contentId.endsWith(">")) { contentId = contentId.substring(1, contentId.length() - 1); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java index eb124884..28d81de5 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java @@ -37,6 +37,7 @@ import org.apache.axiom.soap.SOAPModelBuilder; import org.apache.axiom.soap.SOAPVersion; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; @@ -95,12 +96,13 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing private static final Log logger = LogFactory.getLog(AxiomSoapMessageFactory.class); - private XMLInputFactory inputFactory; + private @Nullable XMLInputFactory inputFactory; private boolean payloadCaching = true; private boolean attachmentCaching = false; + @SuppressWarnings("NullAway.Init") private File attachmentCacheDir; private int attachmentCacheThreshold = 4096; @@ -263,7 +265,8 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing } } - private String getHeaderValue(TransportInputStream transportInputStream, String header) throws IOException { + private @Nullable String getHeaderValue(TransportInputStream transportInputStream, String header) + throws IOException { String contentType = null; Iterator iterator = transportInputStream.getHeaders(header); if (iterator.hasNext()) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/NonCachingPayload.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/NonCachingPayload.java index 2573c50b..1c90cc95 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/NonCachingPayload.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/NonCachingPayload.java @@ -33,7 +33,9 @@ import org.apache.axiom.om.ds.BlobOMDataSource; import org.apache.axiom.om.util.StAXUtils; import org.apache.axiom.soap.SOAPBody; import org.apache.axiom.soap.SOAPFactory; +import org.jspecify.annotations.Nullable; +import org.springframework.util.Assert; import org.springframework.util.xml.StaxUtils; /** @@ -67,7 +69,7 @@ class NonCachingPayload extends AbstractPayload { private final XMLStreamWriter delegate; - private QName name; + private @Nullable QName name; private String encoding = "UTF-8"; @@ -138,6 +140,7 @@ class NonCachingPayload extends AbstractPayload { if (this.elementDepth <= 0 && !this.payloadAdded) { this.delegate.flush(); if (this.baos.size() > 0) { + Assert.notNull(this.name, "name is required"); byte[] buf = this.baos.toByteArray(); OMDataSource dataSource = new BlobOMDataSource(Blobs.createBlob(buf), this.encoding); OMNamespace namespace = getAxiomFactory().createOMNamespace(this.name.getNamespaceURI(), diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/Payload.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/Payload.java index 677b1f08..b8ad42b2 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/Payload.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/Payload.java @@ -19,6 +19,8 @@ package org.springframework.ws.soap.axiom; import javax.xml.transform.Result; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + /** * Defines the contract for payloads in Axiom. * @@ -31,7 +33,7 @@ abstract class Payload { * Returns the source of the payload. * @return the source of the payload */ - public abstract Source getSource(); + public abstract @Nullable Source getSource(); /** * Returns the result of the payload. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/package-info.java index a156b9cc..038e2b2d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/package-info.java @@ -17,4 +17,7 @@ /** * AXis Object Model (AXIOM) support for Spring-WS soap message infrastructure. */ +@NullMarked package org.springframework.ws.soap.axiom; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/support/AxiomUtils.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/support/AxiomUtils.java index 28bd3523..2c5c6412 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/support/AxiomUtils.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/support/AxiomUtils.java @@ -32,6 +32,7 @@ import org.apache.axiom.om.OMNamespace; import org.apache.axiom.om.OMOutputFormat; import org.apache.axiom.om.OMXMLBuilderFactory; import org.apache.axiom.soap.SOAPEnvelope; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -91,7 +92,7 @@ public abstract class AxiomUtils { * @param language the language string * @return the locale */ - public static Locale toLocale(String language) { + public static @Nullable Locale toLocale(String language) { language = language.replace('-', '_'); return StringUtils.parseLocaleString(language); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/support/package-info.java index e491c047..7be978c7 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/axiom/support/package-info.java @@ -17,4 +17,7 @@ /** * Support classes for working with the AXis Object Model (AXIOM). */ +@NullMarked package org.springframework.ws.soap.axiom.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/client/SoapFaultClientException.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/client/SoapFaultClientException.java index 238500b4..6025d2b2 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/client/SoapFaultClientException.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/client/SoapFaultClientException.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.client; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.client.WebServiceFaultException; import org.springframework.ws.soap.SoapBody; import org.springframework.ws.soap.SoapFault; @@ -32,7 +34,7 @@ import org.springframework.ws.soap.SoapMessage; @SuppressWarnings("serial") public class SoapFaultClientException extends WebServiceFaultException { - private final SoapFault soapFault; + private final @Nullable SoapFault soapFault; /** * Create a new instance of the {@code SoapFaultClientException} class. @@ -41,16 +43,16 @@ public class SoapFaultClientException extends WebServiceFaultException { public SoapFaultClientException(SoapMessage faultMessage) { super(faultMessage); SoapBody body = faultMessage.getSoapBody(); - this.soapFault = (body != null) ? body.getFault() : null; + this.soapFault = body.getFault(); } /** Returns the {@link SoapFault}. */ - public SoapFault getSoapFault() { + public @Nullable SoapFault getSoapFault() { return this.soapFault; } /** Returns the fault code. */ - public QName getFaultCode() { + public @Nullable QName getFaultCode() { return (this.soapFault != null) ? this.soapFault.getFaultCode() : null; } @@ -60,7 +62,7 @@ public class SoapFaultClientException extends WebServiceFaultException { *

* Note that this message returns the same as {@link #getMessage()}. */ - public String getFaultStringOrReason() { + public @Nullable String getFaultStringOrReason() { return (this.soapFault != null) ? this.soapFault.getFaultStringOrReason() : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/client/core/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/client/core/package-info.java index 885a7b6a..ed6d4451 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/client/core/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/client/core/package-info.java @@ -17,4 +17,7 @@ /** * Contains core classes for SOAP-specific client-side Spring-WS support. */ +@NullMarked package org.springframework.ws.soap.client.core; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/client/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/client/package-info.java index 2efa83a9..80df23f8 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/client/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/client/package-info.java @@ -17,4 +17,7 @@ /** * Contains classes for SOAP-specific client-side Spring-WS support. */ +@NullMarked package org.springframework.ws.soap.client; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/package-info.java index 841975f3..eb10aa3f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/package-info.java @@ -18,4 +18,7 @@ * Provides the SOAP functionality of the Spring Web Services framework. Contains the * SoapMessage and related interfaces. */ +@NullMarked package org.springframework.ws.soap; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Body.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Body.java index 53bd2c51..de60db28 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Body.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Body.java @@ -23,6 +23,7 @@ import javax.xml.namespace.QName; import jakarta.xml.soap.SOAPBody; import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPFault; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.ws.soap.SoapVersion; @@ -46,7 +47,7 @@ class SaajSoap11Body extends SaajSoapBody implements Soap11Body { } @Override - public Soap11Fault getFault() { + public @Nullable Soap11Fault getFault() { SOAPFault fault = getSaajBody().getFault(); return (fault != null) ? new SaajSoap11Fault(fault) : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Header.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Header.java index bb86f066..18a4ba5d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Header.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Header.java @@ -23,6 +23,7 @@ import java.util.List; import jakarta.xml.soap.SOAPConstants; import jakarta.xml.soap.SOAPHeader; import jakarta.xml.soap.SOAPHeaderElement; +import org.jspecify.annotations.Nullable; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -43,8 +44,7 @@ class SaajSoap11Header extends SaajSoapHeader implements Soap11Header { } @Override - @SuppressWarnings("unchecked") - public Iterator examineHeaderElementsToProcess(String[] actors) { + public Iterator examineHeaderElementsToProcess(String @Nullable [] actors) { List result = new ArrayList<>(); Iterator iterator = getSaajHeader().examineAllHeaderElements(); while (iterator.hasNext()) { @@ -57,7 +57,7 @@ class SaajSoap11Header extends SaajSoapHeader implements Soap11Header { return new SaajSoapHeaderElementIterator(result.iterator()); } - private boolean shouldProcess(String headerActor, String[] actors) { + private boolean shouldProcess(String headerActor, String @Nullable [] actors) { if (!StringUtils.hasLength(headerActor)) { return true; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Body.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Body.java index 8e4f5b27..cbdb1052 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Body.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Body.java @@ -23,6 +23,7 @@ import javax.xml.namespace.QName; import jakarta.xml.soap.SOAPBody; import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPFault; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.ws.soap.SoapVersion; @@ -43,7 +44,7 @@ class SaajSoap12Body extends SaajSoapBody implements Soap12Body { } @Override - public Soap12Fault getFault() { + public @Nullable Soap12Fault getFault() { SOAPFault fault = getSaajBody().getFault(); return (fault != null) ? new SaajSoap12Fault(fault) : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Header.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Header.java index 11a45535..c61921e3 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Header.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Header.java @@ -26,6 +26,7 @@ import jakarta.xml.soap.SOAPConstants; import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPHeader; import jakarta.xml.soap.SOAPHeaderElement; +import org.jspecify.annotations.Nullable; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -69,9 +70,8 @@ class SaajSoap12Header extends SaajSoapHeader implements Soap12Header { } @Override - @SuppressWarnings("unchecked") - public Iterator examineHeaderElementsToProcess(String[] roles, boolean isUltimateDestination) - throws SoapHeaderException { + public Iterator examineHeaderElementsToProcess(String @Nullable [] roles, + boolean isUltimateDestination) throws SoapHeaderException { List result = new ArrayList<>(); Iterator iterator = getSaajHeader().examineAllHeaderElements(); while (iterator.hasNext()) { @@ -85,7 +85,7 @@ class SaajSoap12Header extends SaajSoapHeader implements Soap12Header { } - private boolean shouldProcess(String headerRole, String[] roles, boolean isUltimateDestination) { + private boolean shouldProcess(String headerRole, String @Nullable [] roles, boolean isUltimateDestination) { if (!StringUtils.hasLength(headerRole)) { return true; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapBody.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapBody.java index 54f0b5a6..4563a6be 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapBody.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapBody.java @@ -23,6 +23,7 @@ import javax.xml.transform.dom.DOMSource; import jakarta.xml.soap.SOAPBody; import jakarta.xml.soap.SOAPElement; +import org.jspecify.annotations.Nullable; import org.springframework.ws.soap.SoapBody; import org.springframework.ws.soap.saaj.support.SaajUtils; @@ -41,7 +42,7 @@ abstract class SaajSoapBody extends SaajSoapElement implements SoapBod } @Override - public Source getPayloadSource() { + public @Nullable Source getPayloadSource() { SOAPElement bodyElement = SaajUtils.getFirstBodyElement(getSaajBody()); return (bodyElement != null) ? new DOMSource(bodyElement) : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapEnvelope.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapEnvelope.java index b09f9147..19f723c0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapEnvelope.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapEnvelope.java @@ -20,6 +20,7 @@ import jakarta.xml.soap.SOAPBody; import jakarta.xml.soap.SOAPEnvelope; import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPHeader; +import org.jspecify.annotations.Nullable; import org.springframework.ws.soap.SoapBody; import org.springframework.ws.soap.SoapEnvelope; @@ -35,9 +36,9 @@ import org.springframework.ws.soap.SoapVersion; */ class SaajSoapEnvelope extends SaajSoapElement implements SoapEnvelope { - private SaajSoapBody body; + private @Nullable SaajSoapBody body; - private SaajSoapHeader header; + private @Nullable SaajSoapHeader header; private final boolean langAttributeOnSoap11FaultString; @@ -71,7 +72,7 @@ class SaajSoapEnvelope extends SaajSoapElement implements SoapEnve } @Override - public SoapHeader getHeader() { + public @Nullable SoapHeader getHeader() { if (this.header == null) { try { SOAPHeader saajHeader = getSaajEnvelope().getHeader(); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFault.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFault.java index 02aea8b5..cfed35f2 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFault.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFault.java @@ -21,6 +21,7 @@ import javax.xml.namespace.QName; import jakarta.xml.soap.Detail; import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPFault; +import org.jspecify.annotations.Nullable; import org.springframework.ws.soap.SoapFault; import org.springframework.ws.soap.SoapFaultDetail; @@ -48,7 +49,7 @@ abstract class SaajSoapFault extends SaajSoapElement implements SoapF } @Override - public SoapFaultDetail getFaultDetail() { + public @Nullable SoapFaultDetail getFaultDetail() { Detail saajDetail = getSaajFault().getDetail(); return (saajDetail != null) ? new SaajSoapFaultDetail(saajDetail) : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetailElement.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetailElement.java index 73777f9d..36df57ab 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetailElement.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetailElement.java @@ -21,6 +21,7 @@ import javax.xml.transform.dom.DOMResult; import jakarta.xml.soap.DetailEntry; import jakarta.xml.soap.SOAPException; +import org.jspecify.annotations.Nullable; import org.springframework.ws.soap.SoapFaultDetailElement; @@ -43,7 +44,7 @@ class SaajSoapFaultDetailElement extends SaajSoapElement implements } @Override - public void addText(String text) { + public void addText(@Nullable String text) { try { getSaajDetailEntry().addTextNode(text); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java index 450b3cd3..c682c227 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java @@ -33,6 +33,7 @@ import jakarta.xml.soap.SOAPEnvelope; import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPMessage; import jakarta.xml.soap.SOAPPart; +import org.jspecify.annotations.Nullable; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.ls.DOMImplementationLS; @@ -65,11 +66,11 @@ public class SaajSoapMessage extends AbstractSoapMessage { private static final String CONTENT_TYPE_XOP = "application/xop+xml"; - private final MessageFactory messageFactory; + private final @Nullable MessageFactory messageFactory; private SOAPMessage saajMessage; - private SoapEnvelope envelope; + private @Nullable SoapEnvelope envelope; private final boolean langAttributeOnSoap11FaultString; @@ -108,7 +109,7 @@ public class SaajSoapMessage extends AbstractSoapMessage { * @param messageFactory the message factory */ public SaajSoapMessage(SOAPMessage soapMessage, boolean langAttributeOnSoap11FaultString, - MessageFactory messageFactory) { + @Nullable MessageFactory messageFactory) { Assert.notNull(soapMessage, "soapMessage must not be null"); this.saajMessage = soapMessage; this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString; @@ -311,15 +312,13 @@ public class SaajSoapMessage extends AbstractSoapMessage { } @Override - @SuppressWarnings("unchecked") public Iterator getAttachments() throws AttachmentException { Iterator iterator = getSaajMessage().getAttachments(); return new SaajAttachmentIterator(iterator); } @Override - @SuppressWarnings("unchecked") - public Attachment getAttachment(String contentId) { + public @Nullable Attachment getAttachment(String contentId) { Assert.hasLength(contentId, "contentId must not be empty"); MimeHeaders mimeHeaders = new MimeHeaders(); mimeHeaders.setHeader(TransportConstants.HEADER_CONTENT_ID, contentId); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java index d6b09163..fc70651b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java @@ -31,9 +31,11 @@ import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPMessage; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.xml.sax.SAXParseException; import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -67,13 +69,14 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB private static final Log logger = LogFactory.getLog(SaajSoapMessageFactory.class); - private MessageFactory messageFactory; + private @Nullable MessageFactory messageFactory; + @SuppressWarnings("NullAway.Init") private String messageFactoryProtocol; private boolean langAttributeOnSoap11FaultString = true; - private Map messageProperties; + private @Nullable Map messageProperties; /** Default, empty constructor. */ public SaajSoapMessageFactory() { @@ -86,6 +89,7 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB /** Returns the SAAJ {@code MessageFactory} used. */ public MessageFactory getMessageFactory() { + Assert.state(this.messageFactory != null, "'messageFactory' is required"); return this.messageFactory; } @@ -138,51 +142,55 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB @Override public void afterPropertiesSet() { if (this.messageFactory == null) { - try { - if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) { - if (!StringUtils.hasLength(this.messageFactoryProtocol)) { - this.messageFactoryProtocol = SOAPConstants.SOAP_1_1_PROTOCOL; - } - if (logger.isInfoEnabled()) { - logger.info("Creating SAAJ 1.3 MessageFactory with " + this.messageFactoryProtocol); - } - this.messageFactory = MessageFactory.newInstance(this.messageFactoryProtocol); - } - else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) { - logger.info("Creating SAAJ 1.2 MessageFactory"); - this.messageFactory = MessageFactory.newInstance(); - } - else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_11) { - logger.info("Creating SAAJ 1.1 MessageFactory"); - this.messageFactory = MessageFactory.newInstance(); - } - else { - throw new IllegalStateException( - "SaajSoapMessageFactory requires SAAJ 1.1, which was not found on the classpath"); - } - } - catch (NoSuchMethodError ex) { - throw new SoapMessageCreationException( - "Could not create SAAJ MessageFactory. Is the version of the SAAJ specification interfaces [" - + SaajUtils.getSaajVersionString() - + "] the same as the version supported by the application server?", - ex); - } - catch (SOAPException ex) { - throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + ex.getMessage(), ex); - } + this.messageFactory = initializeMessageFactory(); } if (logger.isDebugEnabled()) { logger.debug("Using MessageFactory class [" + this.messageFactory.getClass().getName() + "]"); } } + private MessageFactory initializeMessageFactory() { + try { + if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) { + if (!StringUtils.hasLength(this.messageFactoryProtocol)) { + this.messageFactoryProtocol = SOAPConstants.SOAP_1_1_PROTOCOL; + } + if (logger.isInfoEnabled()) { + logger.info("Creating SAAJ 1.3 MessageFactory with " + this.messageFactoryProtocol); + } + return MessageFactory.newInstance(this.messageFactoryProtocol); + } + else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) { + logger.info("Creating SAAJ 1.2 MessageFactory"); + return MessageFactory.newInstance(); + } + else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_11) { + logger.info("Creating SAAJ 1.1 MessageFactory"); + return MessageFactory.newInstance(); + } + else { + throw new IllegalStateException( + "SaajSoapMessageFactory requires SAAJ 1.1, which was not found on the classpath"); + } + } + catch (NoSuchMethodError ex) { + throw new SoapMessageCreationException( + "Could not create SAAJ MessageFactory. Is the version of the SAAJ specification interfaces [" + + SaajUtils.getSaajVersionString() + + "] the same as the version supported by the application server?", + ex); + } + catch (SOAPException ex) { + throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + ex.getMessage(), ex); + } + } + @Override public SaajSoapMessage createWebServiceMessage() { try { - SOAPMessage saajMessage = this.messageFactory.createMessage(); + SOAPMessage saajMessage = getMessageFactory().createMessage(); postProcess(saajMessage); - return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, this.messageFactory); + return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, getMessageFactory()); } catch (SOAPException ex) { throw new SoapMessageCreationException("Could not create empty message: " + ex.getMessage(), ex); @@ -194,7 +202,7 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB MimeHeaders mimeHeaders = parseMimeHeaders(inputStream); try { inputStream = checkForUtf8ByteOrderMark(inputStream); - SOAPMessage saajMessage = this.messageFactory.createMessage(mimeHeaders, inputStream); + SOAPMessage saajMessage = getMessageFactory().createMessage(mimeHeaders, inputStream); saajMessage.getSOAPPart().getEnvelope(); postProcess(saajMessage); return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, this.messageFactory); @@ -209,7 +217,7 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB contentType = contentType.replace("startinfo", "start-info"); mimeHeaders.setHeader(TransportConstants.HEADER_CONTENT_TYPE, contentType); try { - SOAPMessage saajMessage = this.messageFactory.createMessage(mimeHeaders, inputStream); + SOAPMessage saajMessage = getMessageFactory().createMessage(mimeHeaders, inputStream); postProcess(saajMessage); return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString); } @@ -228,7 +236,7 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB } } - private SAXParseException getSAXParseException(Throwable ex) { + private @Nullable SAXParseException getSAXParseException(Throwable ex) { if (ex instanceof SAXParseException) { return (SAXParseException) ex; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/package-info.java index 85eafc98..e8ab44d5 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/package-info.java @@ -18,4 +18,7 @@ * SOAP with Attachments API for Java (SAAJ) support for Spring-WS soap message * infrastructure. */ +@NullMarked package org.springframework.ws.soap.saaj; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/SaajContentHandler.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/SaajContentHandler.java index c1a3e336..c26876b0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/SaajContentHandler.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/SaajContentHandler.java @@ -23,6 +23,7 @@ import jakarta.xml.soap.Name; import jakarta.xml.soap.SOAPElement; import jakarta.xml.soap.SOAPEnvelope; import jakarta.xml.soap.SOAPException; +import org.jspecify.annotations.Nullable; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; @@ -59,7 +60,9 @@ public class SaajContentHandler implements ContentHandler { this.envelope = (SOAPEnvelope) element; } else { - this.envelope = SaajUtils.getEnvelope(element); + SOAPEnvelope elementEnvelope = SaajUtils.getEnvelope(element); + Assert.notNull(elementEnvelope, "Could not determine SOAP envelope from " + element); + this.envelope = elementEnvelope; } this.element = element; } @@ -163,7 +166,7 @@ public class SaajContentHandler implements ContentHandler { public void skippedEntity(String name) throws SAXException { } - private String getPrefix(String qName) { + private @Nullable String getPrefix(String qName) { int idx = qName.indexOf(':'); if (idx != -1) { return qName.substring(0, idx); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java index eddc499e..ca09899e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java @@ -30,6 +30,7 @@ import jakarta.xml.soap.SOAPElement; import jakarta.xml.soap.SOAPEnvelope; import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPMessage; +import org.jspecify.annotations.Nullable; import org.springframework.core.io.Resource; import org.springframework.util.Assert; @@ -136,6 +137,7 @@ public abstract class SaajUtils { public static Name toName(QName qName, SOAPElement resolveElement) throws SOAPException { String qNamePrefix = qName.getPrefix(); SOAPEnvelope envelope = getEnvelope(resolveElement); + Assert.notNull(envelope, "SOAPEnvelope must not be null"); if (StringUtils.hasLength(qName.getNamespaceURI()) && StringUtils.hasLength(qNamePrefix)) { return envelope.createName(qName.getLocalPart(), qNamePrefix, qName.getNamespaceURI()); } @@ -201,7 +203,7 @@ public abstract class SaajUtils { * @param element the element to return the envelope from * @return the envelope, or {@code null} if not found */ - public static SOAPEnvelope getEnvelope(SOAPElement element) { + public static @Nullable SOAPEnvelope getEnvelope(SOAPElement element) { Assert.notNull(element, "Element should not be null"); do { if (element instanceof SOAPEnvelope) { @@ -216,7 +218,7 @@ public abstract class SaajUtils { /** * Returns the first child element of the given body. */ - public static SOAPElement getFirstBodyElement(SOAPBody body) { + public static @Nullable SOAPElement getFirstBodyElement(SOAPBody body) { for (Iterator iterator = body.getChildElements(); iterator.hasNext();) { Object child = iterator.next(); if (child instanceof SOAPElement) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/package-info.java index 2fd98c10..cb1db780 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/saaj/support/package-info.java @@ -17,4 +17,7 @@ /** * Support classes for working with the SOAP with Attachments API for Java (SAAJ). */ +@NullMarked package org.springframework.ws.soap.saaj.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/SoapEndpointInvocationChain.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/SoapEndpointInvocationChain.java index 1625cb9b..c348eee9 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/SoapEndpointInvocationChain.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/SoapEndpointInvocationChain.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.server; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.server.EndpointInterceptor; import org.springframework.ws.server.EndpointInvocationChain; @@ -31,7 +33,7 @@ import org.springframework.ws.server.EndpointInvocationChain; */ public class SoapEndpointInvocationChain extends EndpointInvocationChain { - private String[] actorsOrRoles; + private String @Nullable [] actorsOrRoles; private boolean isUltimateReceiver = true; @@ -48,7 +50,7 @@ public class SoapEndpointInvocationChain extends EndpointInvocationChain { * @param endpoint the endpoint object to invoke * @param interceptors the array of interceptors to apply */ - public SoapEndpointInvocationChain(Object endpoint, EndpointInterceptor[] interceptors) { + public SoapEndpointInvocationChain(Object endpoint, EndpointInterceptor @Nullable [] interceptors) { super(endpoint, interceptors); } @@ -60,8 +62,8 @@ public class SoapEndpointInvocationChain extends EndpointInvocationChain { * @param isUltimateReceiver whether this chain fullfils the SOAP 1.2 Ultimate * receiver role */ - public SoapEndpointInvocationChain(Object endpoint, EndpointInterceptor[] interceptors, String[] actorsOrRoles, - boolean isUltimateReceiver) { + public SoapEndpointInvocationChain(Object endpoint, EndpointInterceptor @Nullable [] interceptors, + String @Nullable [] actorsOrRoles, boolean isUltimateReceiver) { super(endpoint, interceptors); this.actorsOrRoles = actorsOrRoles; this.isUltimateReceiver = isUltimateReceiver; @@ -72,7 +74,7 @@ public class SoapEndpointInvocationChain extends EndpointInvocationChain { * this chain and its contained interceptors and endpoint. * @return a string array of URIs for SOAP actors/roles */ - public String[] getActorsOrRoles() { + public String @Nullable [] getActorsOrRoles() { return this.actorsOrRoles; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/SoapMessageDispatcher.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/SoapMessageDispatcher.java index d45c2165..b784b1b8 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/SoapMessageDispatcher.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/SoapMessageDispatcher.java @@ -23,6 +23,8 @@ import java.util.Locale; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; @@ -100,7 +102,7 @@ public class SoapMessageDispatcher extends MessageDispatcher { } private boolean handleHeaders(EndpointInvocationChain mappedEndpoint, MessageContext messageContext, - String[] actorsOrRoles, boolean isUltimateReceiver) { + String @Nullable [] actorsOrRoles, boolean isUltimateReceiver) { SoapMessage soapRequest = (SoapMessage) messageContext.getRequest(); SoapHeader soapHeader = soapRequest.getSoapHeader(); if (soapHeader == null) { @@ -158,7 +160,7 @@ public class SoapMessageDispatcher extends MessageDispatcher { } private void createMustUnderstandFault(SoapMessage soapResponse, List notUnderstoodHeaderNames, - String[] actorsOrRoles) { + String @Nullable [] actorsOrRoles) { if (this.logger.isWarnEnabled()) { this.logger.warn("Could not handle mustUnderstand headers: " + StringUtils.collectionToCommaDelimitedString(notUnderstoodHeaderNames) + ". Returning fault"); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/AbstractSoapFaultDefinitionExceptionResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/AbstractSoapFaultDefinitionExceptionResolver.java index e23f63e4..aabe1d95 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/AbstractSoapFaultDefinitionExceptionResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/AbstractSoapFaultDefinitionExceptionResolver.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.server.endpoint; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; @@ -40,7 +42,7 @@ import org.springframework.ws.soap.soap12.Soap12Fault; */ public abstract class AbstractSoapFaultDefinitionExceptionResolver extends AbstractEndpointExceptionResolver { - private SoapFaultDefinition defaultFault; + private @Nullable SoapFaultDefinition defaultFault; /** * Set the default fault. This fault will be returned if no specific mapping was @@ -58,10 +60,11 @@ public abstract class AbstractSoapFaultDefinitionExceptionResolver extends Abstr * @param ex the exception to be handled * @return the definition mapped to the exception, or {@code null} if none is found. */ - protected abstract SoapFaultDefinition getFaultDefinition(Object endpoint, Exception ex); + protected abstract @Nullable SoapFaultDefinition getFaultDefinition(@Nullable Object endpoint, Exception ex); @Override - protected final boolean resolveExceptionInternal(MessageContext messageContext, Object endpoint, Exception ex) { + protected final boolean resolveExceptionInternal(MessageContext messageContext, @Nullable Object endpoint, + Exception ex) { Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse(), "AbstractSoapFaultDefinitionExceptionResolver requires a SoapMessage"); @@ -102,9 +105,7 @@ public abstract class AbstractSoapFaultDefinitionExceptionResolver extends Abstr throw new IllegalStateException("This class only supports SOAP 1.1 and SOAP 1.2."); } } - if (fault != null) { - customizeFault(endpoint, ex, fault); - } + customizeFault(endpoint, ex, fault); return true; } @@ -119,7 +120,7 @@ public abstract class AbstractSoapFaultDefinitionExceptionResolver extends Abstr * @param ex the exception to be handled * @param fault the created fault */ - protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) { + protected void customizeFault(@Nullable Object endpoint, Exception ex, SoapFault fault) { } } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SimpleSoapExceptionResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SimpleSoapExceptionResolver.java index 9c86990e..e11f25a1 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SimpleSoapExceptionResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SimpleSoapExceptionResolver.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.server.endpoint; import java.util.Locale; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; @@ -60,7 +62,8 @@ public class SimpleSoapExceptionResolver extends AbstractEndpointExceptionResolv } @Override - protected final boolean resolveExceptionInternal(MessageContext messageContext, Object endpoint, Exception ex) { + protected final boolean resolveExceptionInternal(MessageContext messageContext, @Nullable Object endpoint, + Exception ex) { Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse(), "SimpleSoapExceptionResolver requires a SoapMessage"); SoapMessage response = (SoapMessage) messageContext.getResponse(); @@ -74,14 +77,15 @@ public class SimpleSoapExceptionResolver extends AbstractEndpointExceptionResolv /** * Empty template method to allow subclasses an opportunity to customize the given * {@link SoapFault}. Called from - * {@link #resolveExceptionInternal(MessageContext,Object,Exception)}. + * {@link AbstractEndpointExceptionResolver#resolveExceptionInternal(MessageContext, Object, Exception)}. * @param messageContext current message context * @param endpoint the executed endpoint, or {@code null} if none chosen at the time * of the exception * @param ex the exception that got thrown during endpoint execution * @param fault the SOAP fault to be customized. */ - protected void customizeFault(MessageContext messageContext, Object endpoint, Exception ex, SoapFault fault) { + protected void customizeFault(MessageContext messageContext, @Nullable Object endpoint, Exception ex, + SoapFault fault) { } } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultAnnotationExceptionResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultAnnotationExceptionResolver.java index f1a60a94..651c9f13 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultAnnotationExceptionResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultAnnotationExceptionResolver.java @@ -16,8 +16,12 @@ package org.springframework.ws.soap.server.endpoint; +import java.util.Locale; + import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.util.StringUtils; import org.springframework.ws.soap.server.endpoint.annotation.FaultCode; import org.springframework.ws.soap.server.endpoint.annotation.SoapFault; @@ -32,7 +36,7 @@ import org.springframework.ws.soap.server.endpoint.annotation.SoapFault; public class SoapFaultAnnotationExceptionResolver extends AbstractSoapFaultDefinitionExceptionResolver { @Override - protected final SoapFaultDefinition getFaultDefinition(Object endpoint, Exception ex) { + protected final @Nullable SoapFaultDefinition getFaultDefinition(@Nullable Object endpoint, Exception ex) { SoapFault faultAnnotation = ex.getClass().getAnnotation(SoapFault.class); if (faultAnnotation != null) { SoapFaultDefinition definition = new SoapFaultDefinition(); @@ -43,7 +47,10 @@ public class SoapFaultAnnotationExceptionResolver extends AbstractSoapFaultDefin definition.setFaultCode(QName.valueOf(faultAnnotation.customFaultCode())); } definition.setFaultStringOrReason(faultAnnotation.faultStringOrReason()); - definition.setLocale(StringUtils.parseLocaleString(faultAnnotation.locale())); + Locale locale = StringUtils.parseLocaleString(faultAnnotation.locale()); + if (locale != null) { + definition.setLocale(locale); + } return definition; } else { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultDefinition.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultDefinition.java index 2a687d8c..4bb4f16b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultDefinition.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultDefinition.java @@ -20,6 +20,10 @@ import java.util.Locale; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + +import org.springframework.util.Assert; + /** * Defines properties for a SOAP Fault. Used by the {@code SoapFaultDefinitionEditor} and * the {@code SoapFaultMappingExceptionResolver}. @@ -34,39 +38,44 @@ public class SoapFaultDefinition { /** * Constant {@code QName} used to indicate that a {@code Client} fault must be * created. - * @see org.springframework.ws.soap.SoapBody#addClientOrSenderFault(String,java.util.Locale) + * @see org.springframework.ws.soap.SoapBody#addClientOrSenderFault(String, + * java.util.Locale) */ public static final QName CLIENT = new QName("CLIENT"); /** * Constant {@code QName} used to indicate that a {@code Receiver} fault must be * created. - * @see org.springframework.ws.soap.SoapBody#addServerOrReceiverFault(String,java.util.Locale) + * @see org.springframework.ws.soap.SoapBody#addServerOrReceiverFault(String, + * java.util.Locale) */ public static final QName RECEIVER = new QName("RECEIVER"); /** * Constant {@code QName} used to indicate that a {@code Sender} fault must be * created. - * @see org.springframework.ws.soap.SoapBody#addServerOrReceiverFault(String,java.util.Locale) + * @see org.springframework.ws.soap.SoapBody#addServerOrReceiverFault(String, + * java.util.Locale) */ public static final QName SENDER = new QName("SENDER"); /** * Constant {@code QName} used to indicate that a {@code Server} fault must be * created. - * @see org.springframework.ws.soap.SoapBody#addClientOrSenderFault(String,java.util.Locale) + * @see org.springframework.ws.soap.SoapBody#addClientOrSenderFault(String, + * java.util.Locale) */ public static final QName SERVER = new QName("SERVER"); - private QName faultCode; + private @Nullable QName faultCode; - private String faultStringOrReason; + private @Nullable String faultStringOrReason; private Locale locale = Locale.ENGLISH; /** Returns the fault code. */ public QName getFaultCode() { + Assert.state(this.faultCode != null, "'faultCode' is required"); return this.faultCode; } @@ -79,7 +88,7 @@ public class SoapFaultDefinition { * Returns the fault string or reason text. By default, it is set to the exception * message. */ - public String getFaultStringOrReason() { + public @Nullable String getFaultStringOrReason() { return this.faultStringOrReason; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultMappingExceptionResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultMappingExceptionResolver.java index 0e70363e..430ba61a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultMappingExceptionResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/SoapFaultMappingExceptionResolver.java @@ -20,6 +20,8 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; +import org.jspecify.annotations.Nullable; + import org.springframework.util.CollectionUtils; /** @@ -55,7 +57,7 @@ public class SoapFaultMappingExceptionResolver extends AbstractSoapFaultDefiniti } @Override - protected SoapFaultDefinition getFaultDefinition(Object endpoint, Exception ex) { + protected @Nullable SoapFaultDefinition getFaultDefinition(@Nullable Object endpoint, Exception ex) { if (!CollectionUtils.isEmpty(this.exceptionMappings)) { String definitionText = null; int deepest = Integer.MAX_VALUE; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapHeaderElementMethodArgumentResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapHeaderElementMethodArgumentResolver.java index 357e5388..3bc82115 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapHeaderElementMethodArgumentResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapHeaderElementMethodArgumentResolver.java @@ -24,6 +24,8 @@ import java.util.List; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.core.MethodParameter; import org.springframework.util.Assert; import org.springframework.ws.context.MessageContext; @@ -73,21 +75,21 @@ public class SoapHeaderElementMethodArgumentResolver implements MethodArgumentRe Type genericType = parameter.getGenericParameterType(); if (genericType instanceof ParameterizedType parameterizedType) { Type[] typeArguments = parameterizedType.getActualTypeArguments(); - if (typeArguments.length == 1 && SoapHeaderElement.class.equals(typeArguments[0])) { - return true; - } + return typeArguments.length == 1 && SoapHeaderElement.class.equals(typeArguments[0]); } } return false; } @Override - public Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception { + public @Nullable Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception { Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest()); SoapMessage request = (SoapMessage) messageContext.getRequest(); org.springframework.ws.soap.SoapHeader soapHeader = request.getSoapHeader(); - String paramValue = parameter.getParameterAnnotation(SoapHeader.class).value(); + SoapHeader parameterAnnotation = parameter.getParameterAnnotation(SoapHeader.class); + Assert.state(parameterAnnotation != null, "Cannot resolve parameter, @SoapHeader annotation is required"); + String paramValue = parameterAnnotation.value(); Assert.isTrue(QNameUtils.validateQName(paramValue), "Invalid header qualified name [" + paramValue + "]. " + "QName must be of the form '{namespace}localPart'."); @@ -96,17 +98,18 @@ public class SoapHeaderElementMethodArgumentResolver implements MethodArgumentRe Class parameterType = parameter.getParameterType(); - if (SoapHeaderElement.class.equals(parameterType)) { + if (SoapHeaderElement.class.equals(parameterType) && soapHeader != null) { return extractSoapHeader(qname, soapHeader); } - else if (List.class.equals(parameterType)) { + else if (List.class.equals(parameterType) && soapHeader != null) { return extractSoapHeaderList(qname, soapHeader); } // should not happen throw new UnsupportedOperationException(); } - private SoapHeaderElement extractSoapHeader(QName qname, org.springframework.ws.soap.SoapHeader soapHeader) { + private @Nullable SoapHeaderElement extractSoapHeader(QName qname, + org.springframework.ws.soap.SoapHeader soapHeader) { Iterator elements = soapHeader.examineAllHeaderElements(); while (elements.hasNext()) { SoapHeaderElement e = elements.next(); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapMethodArgumentResolver.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapMethodArgumentResolver.java index be811cf3..ccb79e5c 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapMethodArgumentResolver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapMethodArgumentResolver.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.server.endpoint.adapter.method; +import org.jspecify.annotations.Nullable; + import org.springframework.core.MethodParameter; import org.springframework.util.Assert; import org.springframework.ws.context.MessageContext; @@ -42,7 +44,7 @@ public class SoapMethodArgumentResolver implements MethodArgumentResolver { } @Override - public Object resolveArgument(MessageContext messageContext, MethodParameter parameter) { + public @Nullable Object resolveArgument(MessageContext messageContext, MethodParameter parameter) { Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest()); SoapMessage request = (SoapMessage) messageContext.getRequest(); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/package-info.java index 0e791c25..ac86e9c2 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/adapter/method/package-info.java @@ -17,4 +17,7 @@ /** * Method argument resolvers for SOAP headers. */ +@NullMarked package org.springframework.ws.soap.server.endpoint.adapter.method; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/package-info.java index 39d8821f..ba4885b0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/package-info.java @@ -17,4 +17,7 @@ /** * Annotations for Spring-WS SOAP endpoints. */ +@NullMarked package org.springframework.ws.soap.server.endpoint.annotation; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/PayloadValidatingInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/PayloadValidatingInterceptor.java index 16869dd2..cce91ae2 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/PayloadValidatingInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/PayloadValidatingInterceptor.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.server.endpoint.interceptor; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; /** @@ -44,13 +46,13 @@ public class PayloadValidatingInterceptor extends AbstractFaultCreatingValidatin /** Returns the payload source of the given message. */ @Override - protected Source getValidationRequestSource(WebServiceMessage request) { + protected @Nullable Source getValidationRequestSource(WebServiceMessage request) { return request.getPayloadSource(); } /** Returns the payload source of the given message. */ @Override - protected Source getValidationResponseSource(WebServiceMessage response) { + protected @Nullable Source getValidationResponseSource(WebServiceMessage response) { return response.getPayloadSource(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/SoapEnvelopeLoggingInterceptor.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/SoapEnvelopeLoggingInterceptor.java index 73f63f21..4b8165cc 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/SoapEnvelopeLoggingInterceptor.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/SoapEnvelopeLoggingInterceptor.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.server.endpoint.interceptor; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.endpoint.AbstractLoggingInterceptor; @@ -60,7 +62,7 @@ public class SoapEnvelopeLoggingInterceptor extends AbstractLoggingInterceptor i } @Override - protected Source getSource(WebServiceMessage message) { + protected @Nullable Source getSource(WebServiceMessage message) { if (message instanceof SoapMessage soapMessage) { return soapMessage.getEnvelope().getSource(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/package-info.java index ac0f2fe1..abb0f719 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/interceptor/package-info.java @@ -18,4 +18,7 @@ * Provides miscellaneous endpoints {@code EndpointInterceptor} implementations for SOAP * purposes. */ +@NullMarked package org.springframework.ws.soap.server.endpoint.interceptor; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/DelegatingSoapEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/DelegatingSoapEndpointMapping.java index a78f465a..2a6100ac 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/DelegatingSoapEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/DelegatingSoapEndpointMapping.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.server.endpoint.mapping; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.ws.context.MessageContext; @@ -44,9 +46,9 @@ import org.springframework.ws.soap.server.SoapEndpointMapping; */ public class DelegatingSoapEndpointMapping implements InitializingBean, SoapEndpointMapping { - private EndpointMapping delegate; + private @Nullable EndpointMapping delegate; - private String[] actorsOrRoles; + private String @Nullable [] actorsOrRoles; private boolean isUltimateReceiver = true; @@ -78,7 +80,8 @@ public class DelegatingSoapEndpointMapping implements InitializingBean, SoapEndp * @see #setActorsOrRoles(String[]) */ @Override - public EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception { + public @Nullable EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception { + Assert.notNull(this.delegate, "delegate must not be null"); EndpointInvocationChain delegateChain = this.delegate.getEndpoint(messageContext); if (delegateChain != null) { return new SoapEndpointInvocationChain(delegateChain.getEndpoint(), delegateChain.getInterceptors(), diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMapping.java index f26206e7..b7c532d9 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMapping.java @@ -20,6 +20,8 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -55,7 +57,7 @@ import org.springframework.ws.soap.server.endpoint.annotation.SoapActions; public class SoapActionAnnotationMethodEndpointMapping extends AbstractAnnotationMethodEndpointMapping implements SoapEndpointMapping { - private String[] actorsOrRoles; + private String @Nullable [] actorsOrRoles; private boolean isUltimateReceiver = true; @@ -92,7 +94,7 @@ public class SoapActionAnnotationMethodEndpointMapping extends AbstractAnnotatio } @Override - protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception { + protected @Nullable String getLookupKeyForMessage(MessageContext messageContext) throws Exception { if (messageContext.getRequest() instanceof SoapMessage request) { String soapAction = request.getSoapAction(); if (StringUtils.hasLength(soapAction) && soapAction.charAt(0) == '"' @@ -109,7 +111,7 @@ public class SoapActionAnnotationMethodEndpointMapping extends AbstractAnnotatio } @Override - protected String getLookupKeyForMethod(Method method) { + protected @Nullable String getLookupKeyForMethod(Method method) { SoapAction soapAction = AnnotationUtils.findAnnotation(method, SoapAction.class); return (soapAction != null) ? soapAction.value() : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionEndpointMapping.java index 0113dc81..c7527ebf 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionEndpointMapping.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.server.endpoint.mapping; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; @@ -54,7 +56,7 @@ import org.springframework.ws.soap.server.SoapEndpointMapping; */ public class SoapActionEndpointMapping extends AbstractMapBasedEndpointMapping implements SoapEndpointMapping { - private String[] actorsOrRoles; + private String @Nullable [] actorsOrRoles; private boolean isUltimateReceiver = true; @@ -91,7 +93,7 @@ public class SoapActionEndpointMapping extends AbstractMapBasedEndpointMapping i } @Override - protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception { + protected @Nullable String getLookupKeyForMessage(MessageContext messageContext) throws Exception { if (messageContext.getRequest() instanceof SoapMessage request) { String soapAction = request.getSoapAction(); if (StringUtils.hasLength(soapAction) && soapAction.charAt(0) == '"' diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/package-info.java index 7b4c3073..155e531e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/package-info.java @@ -18,4 +18,7 @@ * Provides miscellaneous endpoints {@code EndpointMapping} implementations for SOAP * purposes. */ +@NullMarked package org.springframework.ws.soap.server.endpoint.mapping; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/package-info.java index c67a437a..89add470 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/endpoint/package-info.java @@ -18,4 +18,7 @@ * Provides {@code EndpointAdapter}, {@code EndpointMapping}, and * {@code EndpointExceptionResolver} implementations for SOAP. */ +@NullMarked package org.springframework.ws.soap.server.endpoint; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/package-info.java index 41a9511f..e776c49e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/server/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/server/package-info.java @@ -17,4 +17,7 @@ /** * Contains classes for SOAP-specific server-side Spring-WS support. */ +@NullMarked package org.springframework.ws.soap.server; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Body.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Body.java index 063d6a5e..fb35f95a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Body.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Body.java @@ -20,6 +20,8 @@ import java.util.Locale; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapBody; import org.springframework.ws.soap.SoapFaultException; @@ -45,7 +47,7 @@ public interface Soap11Body extends SoapBody { Soap11Fault addFault(QName faultCode, String faultString, Locale faultStringLocale) throws SoapFaultException; @Override - Soap11Fault getFault(); + @Nullable Soap11Fault getFault(); @Override Soap11Fault addMustUnderstandFault(String faultStringOrReason, Locale locale) throws SoapFaultException; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Fault.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Fault.java index abdeefff..2d112950 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Fault.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Fault.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.soap11; import java.util.Locale; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapFault; /** @@ -30,6 +32,6 @@ import org.springframework.ws.soap.SoapFault; public interface Soap11Fault extends SoapFault { /** Returns the locale of the fault string. */ - Locale getFaultStringLocale(); + @Nullable Locale getFaultStringLocale(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Header.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Header.java index f52ec146..95e7ecfc 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Header.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/Soap11Header.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.soap11; import java.util.Iterator; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapHeader; import org.springframework.ws.soap.SoapHeaderElement; import org.springframework.ws.soap.SoapHeaderException; @@ -39,6 +41,6 @@ public interface Soap11Header extends SoapHeader { * @throws SoapHeaderException if the headers cannot be returned * @see SoapHeaderElement */ - Iterator examineHeaderElementsToProcess(String[] actors) throws SoapHeaderException; + Iterator examineHeaderElementsToProcess(String @Nullable [] actors) throws SoapHeaderException; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/package-info.java index 67172e11..2cdfd857 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap11/package-info.java @@ -17,4 +17,7 @@ /** * Contains interfaces specific to SOAP 1.1. */ +@NullMarked package org.springframework.ws.soap.soap11; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Body.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Body.java index 098a5d13..4a20c306 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Body.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Body.java @@ -20,6 +20,8 @@ import java.util.Locale; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapBody; import org.springframework.ws.soap.SoapFaultException; @@ -44,7 +46,7 @@ public interface Soap12Body extends SoapBody { Soap12Fault addDataEncodingUnknownFault(QName[] subcodes, String reason, Locale locale) throws SoapFaultException; @Override - Soap12Fault getFault(); + @Nullable Soap12Fault getFault(); @Override Soap12Fault addMustUnderstandFault(String faultStringOrReason, Locale locale) throws SoapFaultException; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Fault.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Fault.java index 528530f6..df400070 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Fault.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Fault.java @@ -21,6 +21,8 @@ import java.util.Locale; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapFault; /** @@ -46,7 +48,7 @@ public interface Soap12Fault extends SoapFault { void addFaultSubcode(QName subcode); /** Returns the fault node. Optional. */ - String getFaultNode(); + @Nullable String getFaultNode(); /** Sets the fault node. */ void setFaultNode(String uri); @@ -55,6 +57,6 @@ public interface Soap12Fault extends SoapFault { void setFaultReasonText(Locale locale, String text); /** Returns the reason associated with the given language. */ - String getFaultReasonText(Locale locale); + @Nullable String getFaultReasonText(Locale locale); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Header.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Header.java index 77b6920a..33370b0f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Header.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/Soap12Header.java @@ -20,6 +20,8 @@ import java.util.Iterator; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapHeader; import org.springframework.ws.soap.SoapHeaderElement; import org.springframework.ws.soap.SoapHeaderException; @@ -60,7 +62,7 @@ public interface Soap12Header extends SoapHeader { * @throws SoapHeaderException if the headers cannot be returned * @see SoapHeaderElement */ - Iterator examineHeaderElementsToProcess(String[] roles, boolean isUltimateReceiver) + Iterator examineHeaderElementsToProcess(String @Nullable [] roles, boolean isUltimateReceiver) throws SoapHeaderException; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/package-info.java index 1acfb0fa..6c51ab0f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/soap12/package-info.java @@ -17,4 +17,7 @@ /** * Contains interfaces specific to SOAP 1.2. */ +@NullMarked package org.springframework.ws.soap.soap12; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/support/package-info.java index 05fc7580..2f8933cb 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/support/package-info.java @@ -17,4 +17,7 @@ /** * Classes supporting the org.springframework.ws.soap package. */ +@NullMarked package org.springframework.ws.soap.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/stream/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/stream/package-info.java index 920844b3..543e0432 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/stream/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/stream/package-info.java @@ -17,4 +17,7 @@ /** * Streaming support. */ +@NullMarked package org.springframework.ws.stream; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/support/DefaultStrategiesHelper.java b/spring-ws-core/src/main/java/org/springframework/ws/support/DefaultStrategiesHelper.java index 27007644..3c4981a6 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/support/DefaultStrategiesHelper.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/support/DefaultStrategiesHelper.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Properties; import jakarta.servlet.ServletContext; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; @@ -121,7 +122,7 @@ public class DefaultStrategiesHelper { * @throws BeansException if initialization failed */ @SuppressWarnings("unchecked") - public List getDefaultStrategies(Class strategyInterface, ApplicationContext applicationContext) + public List getDefaultStrategies(Class strategyInterface, @Nullable ApplicationContext applicationContext) throws BeanInitializationException { String key = strategyInterface.getName(); try { @@ -155,13 +156,13 @@ public class DefaultStrategiesHelper { } /** Instantiates the given bean, simulating the standard bean life cycle. */ - private T instantiateBean(Class clazz, ApplicationContext applicationContext) { + private T instantiateBean(Class clazz, @Nullable ApplicationContext applicationContext) { T strategy = BeanUtils.instantiateClass(clazz); if (strategy instanceof BeanNameAware beanNameAware) { beanNameAware.setBeanName(clazz.getName()); } if (applicationContext != null) { - if (strategy instanceof BeanClassLoaderAware) { + if (strategy instanceof BeanClassLoaderAware && applicationContext.getClassLoader() != null) { ((BeanClassLoaderAware) strategy).setBeanClassLoader(applicationContext.getClassLoader()); } if (strategy instanceof BeanFactoryAware) { @@ -181,7 +182,9 @@ public class DefaultStrategiesHelper { } if (applicationContext instanceof WebApplicationContext && strategy instanceof ServletContextAware) { ServletContext servletContext = ((WebApplicationContext) applicationContext).getServletContext(); - ((ServletContextAware) strategy).setServletContext(servletContext); + if (servletContext != null) { + ((ServletContextAware) strategy).setServletContext(servletContext); + } } } if (strategy instanceof InitializingBean initializingBean) { @@ -217,7 +220,7 @@ public class DefaultStrategiesHelper { * @return the corresponding strategy object * @throws BeansException if initialization failed */ - public T getDefaultStrategy(Class strategyInterface, ApplicationContext applicationContext) + public T getDefaultStrategy(Class strategyInterface, @Nullable ApplicationContext applicationContext) throws BeanInitializationException { List result = getDefaultStrategies(strategyInterface, applicationContext); if (result.size() != 1) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/support/MarshallingUtils.java b/spring-ws-core/src/main/java/org/springframework/ws/support/MarshallingUtils.java index 90d50846..aeaa2c2a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/support/MarshallingUtils.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/support/MarshallingUtils.java @@ -21,6 +21,7 @@ import java.io.IOException; import javax.xml.transform.Source; import jakarta.activation.DataHandler; +import org.jspecify.annotations.Nullable; import org.springframework.oxm.Marshaller; import org.springframework.oxm.Unmarshaller; @@ -54,7 +55,7 @@ public abstract class MarshallingUtils { * @return the unmarshalled object * @throws IOException in case of I/O errors */ - public static Object unmarshal(Unmarshaller unmarshaller, WebServiceMessage message) throws IOException { + public static @Nullable Object unmarshal(Unmarshaller unmarshaller, WebServiceMessage message) throws IOException { Source payload = message.getPayloadSource(); if (payload == null) { return null; @@ -110,7 +111,7 @@ public abstract class MarshallingUtils { } @Override - public DataHandler getAttachment(String contentId) { + public @Nullable DataHandler getAttachment(String contentId) { Attachment attachment = this.mimeMessage.getAttachment(contentId); return (attachment != null) ? attachment.getDataHandler() : null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/support/package-info.java index ee8c74ad..d405117d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/support/package-info.java @@ -17,4 +17,7 @@ /** * Provides general helper classes for Spring Web Services. */ +@NullMarked package org.springframework.ws.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java index 4943f11d..b919a1a4 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java @@ -21,6 +21,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; +import org.jspecify.annotations.Nullable; + /** * Abstract base class for {@link WebServiceConnection} implementations used for receiving * requests. @@ -32,9 +34,9 @@ import java.util.Iterator; public abstract class AbstractReceiverConnection extends AbstractWebServiceConnection implements HeadersAwareReceiverWebServiceConnection { - private TransportInputStream requestInputStream; + private @Nullable TransportInputStream requestInputStream; - private TransportOutputStream responseOutputStream; + private @Nullable TransportOutputStream responseOutputStream; @Override protected final TransportInputStream createTransportInputStream() throws IOException { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractSenderConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractSenderConnection.java index 31826aa1..fce12dbe 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractSenderConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractSenderConnection.java @@ -21,6 +21,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; +import org.jspecify.annotations.Nullable; + /** * Abstract base class for {@link WebServiceConnection} implementations used for sending * requests. @@ -32,9 +34,9 @@ import java.util.Iterator; public abstract class AbstractSenderConnection extends AbstractWebServiceConnection implements HeadersAwareSenderWebServiceConnection { - private TransportOutputStream requestOutputStream; + private @Nullable TransportOutputStream requestOutputStream; - private TransportInputStream responseInputStream; + private @Nullable TransportInputStream responseInputStream; @Override protected final TransportOutputStream createTransportOutputStream() throws IOException { @@ -45,7 +47,7 @@ public abstract class AbstractSenderConnection extends AbstractWebServiceConnect } @Override - protected final TransportInputStream createTransportInputStream() throws IOException { + protected final @Nullable TransportInputStream createTransportInputStream() throws IOException { if (hasResponse()) { if (this.responseInputStream == null) { this.responseInputStream = new ResponseTransportInputStream(); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java index 8d6a108c..9bb9d20d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java @@ -18,6 +18,8 @@ package org.springframework.ws.transport; import java.io.IOException; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; import org.springframework.ws.WebServiceMessageFactory; @@ -29,9 +31,9 @@ import org.springframework.ws.WebServiceMessageFactory; */ public abstract class AbstractWebServiceConnection implements WebServiceConnection { - private TransportInputStream tis; + private @Nullable TransportInputStream tis; - private TransportOutputStream tos; + private @Nullable TransportOutputStream tos; private boolean closed = false; @@ -65,7 +67,7 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti * @return the output stream * @throws IOException when an I/O exception occurs */ - protected abstract TransportOutputStream createTransportOutputStream() throws IOException; + protected abstract @Nullable TransportOutputStream createTransportOutputStream() throws IOException; /** * Called after the given message has been written to the @@ -79,7 +81,7 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti } @Override - public final WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException { + public final @Nullable WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException { checkClosed(); onReceiveBeforeRead(); this.tis = createTransportInputStream(); @@ -107,7 +109,7 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti * @return the input stream, or {@code null} if no response can be read * @throws IOException when an I/O exception occurs */ - protected abstract TransportInputStream createTransportInputStream() throws IOException; + protected abstract @Nullable TransportInputStream createTransportInputStream() throws IOException; /** * Called when the given message has been read from the {@code TransportInputStream}. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/FaultAwareWebServiceConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/FaultAwareWebServiceConnection.java index 6aab5e31..67000efc 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/FaultAwareWebServiceConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/FaultAwareWebServiceConnection.java @@ -20,6 +20,8 @@ import java.io.IOException; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.SoapFault; /** @@ -50,6 +52,6 @@ public interface FaultAwareWebServiceConnection extends WebServiceConnection { * fault. * @throws IOException in case of I/O errors */ - void setFaultCode(QName faultCode) throws IOException; + void setFaultCode(@Nullable QName faultCode) throws IOException; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportException.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportException.java index 8fe79780..1a69fa8b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportException.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportException.java @@ -18,6 +18,8 @@ package org.springframework.ws.transport; import java.io.IOException; +import org.jspecify.annotations.Nullable; + /** * Abstract base class for exceptions related to the transport layer. * @@ -27,7 +29,7 @@ import java.io.IOException; @SuppressWarnings("serial") public abstract class TransportException extends IOException { - protected TransportException(String msg) { + protected TransportException(@Nullable String msg) { super(msg); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportInputStream.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportInputStream.java index 852146df..a7016c93 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportInputStream.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportInputStream.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Iterator; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -34,7 +36,7 @@ import org.springframework.util.Assert; */ public abstract class TransportInputStream extends InputStream { - private InputStream inputStream; + private @Nullable InputStream inputStream; protected TransportInputStream() { } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportOutputStream.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportOutputStream.java index f342c178..52d61f1e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportOutputStream.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/TransportOutputStream.java @@ -19,6 +19,8 @@ package org.springframework.ws.transport; import java.io.IOException; import java.io.OutputStream; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -32,7 +34,7 @@ import org.springframework.util.Assert; */ public abstract class TransportOutputStream extends OutputStream { - private OutputStream outputStream; + private @Nullable OutputStream outputStream; protected TransportOutputStream() { } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java index 0c409b66..02a36e62 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceMessage; import org.springframework.ws.WebServiceMessageFactory; @@ -49,10 +51,10 @@ public interface WebServiceConnection extends AutoCloseable { * @return the read message, or {@code null} if no message received * @throws IOException in case of I/O errors */ - WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException; + @Nullable WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException; /** Returns the URI for this connection. */ - URI getUri() throws URISyntaxException; + @Nullable URI getUri() throws URISyntaxException; /** * Indicates whether this connection has an error. Typically, error detection is done @@ -67,7 +69,7 @@ public interface WebServiceConnection extends AutoCloseable { * present * @see #hasError() */ - String getErrorMessage() throws IOException; + @Nullable String getErrorMessage() throws IOException; /** * Closes this connection. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/context/TransportContext.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/context/TransportContext.java index 02ffc75c..b89f1d76 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/context/TransportContext.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/context/TransportContext.java @@ -16,6 +16,8 @@ package org.springframework.ws.transport.context; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.transport.WebServiceConnection; /** @@ -31,6 +33,6 @@ import org.springframework.ws.transport.WebServiceConnection; public interface TransportContext { /** Returns the current {@code WebServiceConnection}. */ - WebServiceConnection getConnection(); + @Nullable WebServiceConnection getConnection(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/context/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/context/package-info.java index 36e5832a..a43d2825 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/context/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/context/package-info.java @@ -17,4 +17,7 @@ /** * Abstraction for determining the current TransportInputStream and TransportOutputStream. */ +@NullMarked package org.springframework.ws.transport.context; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpComponents5MessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpComponents5MessageSender.java index 51e5dbcc..275dfa60 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpComponents5MessageSender.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpComponents5MessageSender.java @@ -24,6 +24,7 @@ import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.protocol.HttpContext; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.DisposableBean; import org.springframework.ws.transport.WebServiceConnection; @@ -75,7 +76,7 @@ public abstract class AbstractHttpComponents5MessageSender extends AbstractHttpW * @param uri the URI to create the context for * @return the context, or {@code null} */ - protected HttpContext createContext(URI uri) { + protected @Nullable HttpContext createContext(URI uri) { return null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java index ac41873a..38a4d65b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java @@ -24,6 +24,8 @@ import java.util.zip.GZIPInputStream; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.util.StringUtils; import org.springframework.ws.transport.AbstractSenderConnection; import org.springframework.ws.transport.FaultAwareWebServiceConnection; @@ -43,13 +45,13 @@ public abstract class AbstractHttpSenderConnection extends AbstractSenderConnect /** * Cached result of {@code hasResponse}. */ - private Boolean hasResponse; + private @Nullable Boolean hasResponse; /** * The raw response input stream to use instead of calling * {@link #getRawResponseInputStream()}. */ - private PushbackInputStream rawResponseInputStream; + private @Nullable PushbackInputStream rawResponseInputStream; @Override public final boolean hasError() throws IOException { @@ -168,7 +170,7 @@ public abstract class AbstractHttpSenderConnection extends AbstractSenderConnect } @Override - public final void setFaultCode(QName faultCode) throws IOException { + public final void setFaultCode(@Nullable QName faultCode) throws IOException { } } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestConnection.java index f399d338..da858f13 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestConnection.java @@ -25,6 +25,8 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpResponse; import org.springframework.util.Assert; @@ -44,7 +46,7 @@ public class ClientHttpRequestConnection extends AbstractHttpSenderConnection { private final ClientHttpRequest request; - private ClientHttpResponse response; + private @Nullable ClientHttpResponse response; public ClientHttpRequestConnection(ClientHttpRequest request) { Assert.notNull(request, "'request' must not be null"); @@ -56,6 +58,7 @@ public class ClientHttpRequestConnection extends AbstractHttpSenderConnection { } public ClientHttpResponse getClientHttpResponse() { + Assert.notNull(this.response, "Response is not available"); return this.response; } @@ -87,33 +90,33 @@ public class ClientHttpRequestConnection extends AbstractHttpSenderConnection { @Override protected long getResponseContentLength() throws IOException { - return this.response.getHeaders().getContentLength(); + return getClientHttpResponse().getHeaders().getContentLength(); } @Override public Iterator getResponseHeaderNames() throws IOException { - return this.response.getHeaders().headerNames().iterator(); + return getClientHttpResponse().getHeaders().headerNames().iterator(); } @Override public Iterator getResponseHeaders(String name) throws IOException { - List headers = this.response.getHeaders().get(name); + List headers = getClientHttpResponse().getHeaders().get(name); return (headers != null) ? headers.iterator() : Collections.emptyIterator(); } @Override protected int getResponseCode() throws IOException { - return this.response.getStatusCode().value(); + return getClientHttpResponse().getStatusCode().value(); } @Override protected String getResponseMessage() throws IOException { - return this.response.getStatusText(); + return getClientHttpResponse().getStatusText(); } @Override protected InputStream getRawResponseInputStream() throws IOException { - return this.response.getBody(); + return getClientHttpResponse().getBody(); } @Override diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSender.java index 6ffc9f3a..347a56d6 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSender.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSender.java @@ -43,7 +43,7 @@ public class ClientHttpRequestMessageSender extends AbstractHttpWebServiceMessag } public ClientHttpRequestMessageSender(ClientHttpRequestFactory requestFactory) { - setRequestFactory(requestFactory); + this.requestFactory = requestFactory; } public ClientHttpRequestFactory getRequestFactory() { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5ClientFactory.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5ClientFactory.java index ffe2f16b..c9826fed 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5ClientFactory.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5ClientFactory.java @@ -40,6 +40,7 @@ import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequestInterceptor; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.util.Timeout; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.FactoryBean; import org.springframework.ws.client.support.interceptor.ClientInterceptor; @@ -81,11 +82,11 @@ public class HttpComponents5ClientFactory implements FactoryBean maxConnectionsPerHost = Map.of(); - private PoolingHttpClientConnectionManager connectionManager; + private @Nullable PoolingHttpClientConnectionManager connectionManager; /** * Create a new instance with default settings. This configures @@ -195,7 +196,7 @@ public class HttpComponents5ClientFactory implements FactoryBean getResponseHeaderNames() throws IOException { - return Arrays.stream(this.httpResponse.getHeaders()).map(NameValuePair::getName).iterator(); + return Arrays.stream(getHttpResponse().getHeaders()).map(NameValuePair::getName).iterator(); } @Override public Iterator getResponseHeaders(String name) throws IOException { - return Arrays.stream(this.httpResponse.getHeaders(name)).map(NameValuePair::getValue).iterator(); + return Arrays.stream(getHttpResponse().getHeaders(name)).map(NameValuePair::getValue).iterator(); } } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5MessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5MessageSender.java index 55aa5b5e..265d23f2 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5MessageSender.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5MessageSender.java @@ -23,8 +23,10 @@ import org.apache.hc.client5.http.auth.AuthScope; import org.apache.hc.client5.http.auth.Credentials; import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; /** * {@code AbstractHttpComponents5MessageSender} implementation that configures the @@ -46,7 +48,7 @@ public class HttpComponents5MessageSender extends AbstractHttpComponents5Message private final HttpComponents5ClientFactory clientFactory; - private HttpClient httpClient; + private @Nullable HttpClient httpClient; /** * Create a new instance of the {@code HttpClientMessageSender} with a default @@ -58,6 +60,7 @@ public class HttpComponents5MessageSender extends AbstractHttpComponents5Message @Override public HttpClient getHttpClient() { + Assert.notNull(this.httpClient, "'httpClient' must not be null"); return this.httpClient; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsConnection.java index 454fd5e3..44ff887f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsConnection.java @@ -33,6 +33,7 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; @@ -54,13 +55,13 @@ public class HttpComponentsConnection extends AbstractHttpSenderConnection { private final HttpPost httpPost; - private final HttpContext httpContext; + private final @Nullable HttpContext httpContext; - private HttpResponse httpResponse; + private @Nullable HttpResponse httpResponse; - private ByteArrayOutputStream requestBuffer; + private @Nullable ByteArrayOutputStream requestBuffer; - protected HttpComponentsConnection(HttpClient httpClient, HttpPost httpPost, HttpContext httpContext) { + protected HttpComponentsConnection(HttpClient httpClient, HttpPost httpPost, @Nullable HttpContext httpContext) { Assert.notNull(httpClient, "httpClient must not be null"); Assert.notNull(httpPost, "httpPost must not be null"); this.httpClient = httpClient; @@ -73,6 +74,7 @@ public class HttpComponentsConnection extends AbstractHttpSenderConnection { } public HttpResponse getHttpResponse() { + Assert.notNull(this.httpResponse, "HttpResponse is not available"); return this.httpResponse; } @@ -107,11 +109,13 @@ public class HttpComponentsConnection extends AbstractHttpSenderConnection { @Override protected OutputStream getRequestOutputStream() throws IOException { + Assert.notNull(this.requestBuffer, "Request OutputStream is not available"); return this.requestBuffer; } @Override protected void onSendAfterWrite(WebServiceMessage message) throws IOException { + Assert.state(this.requestBuffer != null, "onSendBeforeWrite has not been called"); this.httpPost.setEntity(new ByteArrayEntity(this.requestBuffer.toByteArray())); this.requestBuffer = null; if (this.httpContext != null) { @@ -128,17 +132,17 @@ public class HttpComponentsConnection extends AbstractHttpSenderConnection { @Override protected int getResponseCode() throws IOException { - return this.httpResponse.getStatusLine().getStatusCode(); + return getHttpResponse().getStatusLine().getStatusCode(); } @Override protected String getResponseMessage() throws IOException { - return this.httpResponse.getStatusLine().getReasonPhrase(); + return getHttpResponse().getStatusLine().getReasonPhrase(); } @Override protected long getResponseContentLength() throws IOException { - HttpEntity entity = this.httpResponse.getEntity(); + HttpEntity entity = getHttpResponse().getEntity(); if (entity != null) { return entity.getContentLength(); } @@ -147,7 +151,7 @@ public class HttpComponentsConnection extends AbstractHttpSenderConnection { @Override protected InputStream getRawResponseInputStream() throws IOException { - HttpEntity entity = this.httpResponse.getEntity(); + HttpEntity entity = getHttpResponse().getEntity(); if (entity != null) { return entity.getContent(); } @@ -156,7 +160,7 @@ public class HttpComponentsConnection extends AbstractHttpSenderConnection { @Override public Iterator getResponseHeaderNames() throws IOException { - Header[] headers = this.httpResponse.getAllHeaders(); + Header[] headers = getHttpResponse().getAllHeaders(); String[] names = new String[headers.length]; for (int i = 0; i < headers.length; i++) { names[i] = headers[i].getName(); @@ -166,7 +170,7 @@ public class HttpComponentsConnection extends AbstractHttpSenderConnection { @Override public Iterator getResponseHeaders(String name) throws IOException { - Header[] headers = this.httpResponse.getHeaders(name); + Header[] headers = getHttpResponse().getHeaders(name); String[] values = new String[headers.length]; for (int i = 0; i < headers.length; i++) { values[i] = headers[i].getValue(); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsMessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsMessageSender.java index b5316dba..949b69d2 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsMessageSender.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsMessageSender.java @@ -34,6 +34,7 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; @@ -66,7 +67,7 @@ public class HttpComponentsMessageSender extends AbstractHttpWebServiceMessageSe private HttpClient httpClient; - private Credentials credentials; + private @Nullable Credentials credentials; private AuthScope authScope = AuthScope.ANY; @@ -248,7 +249,7 @@ public class HttpComponentsMessageSender extends AbstractHttpWebServiceMessageSe * @param uri the URI to create the context for * @return the context, or {@code null} */ - protected HttpContext createContext(URI uri) { + protected @Nullable HttpContext createContext(URI uri) { return null; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpExchangeConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpExchangeConnection.java index 0cf08da0..9a9a1c75 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpExchangeConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpExchangeConnection.java @@ -30,6 +30,7 @@ import javax.xml.namespace.QName; import com.sun.net.httpserver.HttpExchange; import jakarta.xml.soap.SOAPConstants; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; @@ -52,7 +53,7 @@ public class HttpExchangeConnection extends AbstractReceiverConnection private final HttpExchange httpExchange; - private ByteArrayOutputStream responseBuffer; + private @Nullable ByteArrayOutputStream responseBuffer; private int responseStatusCode = HttpTransportConstants.STATUS_ACCEPTED; @@ -93,7 +94,7 @@ public class HttpExchangeConnection extends AbstractReceiverConnection } @Override - public String getErrorMessage() throws IOException { + public @Nullable String getErrorMessage() throws IOException { return null; } @@ -143,6 +144,7 @@ public class HttpExchangeConnection extends AbstractReceiverConnection @Override protected void onSendAfterWrite(WebServiceMessage message) throws IOException { if (!this.chunkedEncoding) { + Assert.state(this.responseBuffer != null, "responseBuffer has not been initialized"); byte[] buf = this.responseBuffer.toByteArray(); this.httpExchange.sendResponseHeaders(this.responseStatusCode, buf.length); OutputStream responseBody = this.httpExchange.getResponseBody(); @@ -170,7 +172,7 @@ public class HttpExchangeConnection extends AbstractReceiverConnection } @Override - public void setFaultCode(QName faultCode) throws IOException { + public void setFaultCode(@Nullable QName faultCode) throws IOException { if (faultCode != null) { if (SOAPConstants.SOAP_SENDER_FAULT.equals(faultCode)) { this.responseStatusCode = HttpTransportConstants.STATUS_BAD_REQUEST; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java index 92699e94..818f4344 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java @@ -28,6 +28,7 @@ import javax.xml.namespace.QName; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.xml.soap.SOAPConstants; +import org.jspecify.annotations.Nullable; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.transport.AbstractReceiverConnection; @@ -87,7 +88,7 @@ public class HttpServletConnection extends AbstractReceiverConnection } @Override - public String getErrorMessage() throws IOException { + public @Nullable String getErrorMessage() throws IOException { return null; } @@ -157,7 +158,7 @@ public class HttpServletConnection extends AbstractReceiverConnection } @Override - public void setFaultCode(QName faultCode) throws IOException { + public void setFaultCode(@Nullable QName faultCode) throws IOException { if (faultCode != null) { if (SOAPConstants.SOAP_SENDER_FAULT.equals(faultCode)) { getHttpServletResponse().setStatus(HttpTransportConstants.STATUS_BAD_REQUEST); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpsUrlConnectionMessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpsUrlConnectionMessageSender.java index 4b4f0dc1..ca2e4d1c 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpsUrlConnectionMessageSender.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpsUrlConnectionMessageSender.java @@ -30,6 +30,8 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -50,17 +52,17 @@ public class HttpsUrlConnectionMessageSender extends HttpUrlConnectionMessageSen private String sslProtocol = DEFAULT_SSL_PROTOCOL; - private String sslProvider; + private @Nullable String sslProvider; - private KeyManager[] keyManagers; + private KeyManager @Nullable [] keyManagers; - private TrustManager[] trustManagers; + private TrustManager @Nullable [] trustManagers; - private HostnameVerifier hostnameVerifier; + private @Nullable HostnameVerifier hostnameVerifier; - private SecureRandom rnd; + private @Nullable SecureRandom rnd; - private SSLSocketFactory sslSocketFactory; + private @Nullable SSLSocketFactory sslSocketFactory; /** * Sets the SSL protocol to use. Default is {@code ssl}. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/JdkHttpClientConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/JdkHttpClientConnection.java index 3e433303..0ab5c8fe 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/JdkHttpClientConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/JdkHttpClientConnection.java @@ -34,6 +34,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.http.HttpStatus; import org.springframework.util.Assert; @@ -62,11 +63,9 @@ public class JdkHttpClientConnection extends AbstractHttpSenderConnection { private final Builder requestBuilder; - private HttpRequest request; + private @Nullable ByteArrayOutputStream requestBuffer; - private ByteArrayOutputStream requestBuffer; - - private HttpResponse response; + private @Nullable HttpResponse response; protected JdkHttpClientConnection(HttpClient httpClient, URI uri, Duration requestTimeout) { @@ -79,19 +78,25 @@ public class JdkHttpClientConnection extends AbstractHttpSenderConnection { this.requestBuilder = HttpRequest.newBuilder(uri).timeout(requestTimeout); } + protected HttpResponse getResponse() { + Assert.notNull(this.response, "HttpResponse is not available"); + return this.response; + } + @Override protected OutputStream getRequestOutputStream() throws IOException { + Assert.notNull(this.requestBuffer, "Request OutputStream is not available"); return this.requestBuffer; } @Override public Iterator getResponseHeaderNames() throws IOException { - return this.response.headers().map().keySet().iterator(); + return getResponse().headers().map().keySet().iterator(); } @Override public Iterator getResponseHeaders(String name) throws IOException { - return this.response.headers().allValues(name).iterator(); + return getResponse().headers().allValues(name).iterator(); } @Override @@ -134,7 +139,7 @@ public class JdkHttpClientConnection extends AbstractHttpSenderConnection { @Override protected InputStream getRawResponseInputStream() throws IOException { - return this.response.body(); + return getResponse().body(); } @Override @@ -144,13 +149,12 @@ public class JdkHttpClientConnection extends AbstractHttpSenderConnection { @Override protected void onSendAfterWrite(WebServiceMessage message) throws IOException { - + Assert.state(this.requestBuffer != null, "onSendBeforeWrite has not been called"); byte[] body = this.requestBuffer.toByteArray(); - this.request = this.requestBuilder.POST(BodyPublishers.ofByteArray(body)).build(); - + HttpRequest request = this.requestBuilder.POST(BodyPublishers.ofByteArray(body)).build(); try { - this.response = this.httpClient.send(this.request, BodyHandlers.ofInputStream()); + this.response = this.httpClient.send(request, BodyHandlers.ofInputStream()); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/JdkHttpClientMessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/JdkHttpClientMessageSender.java index 712aa3af..3e0a4be0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/JdkHttpClientMessageSender.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/JdkHttpClientMessageSender.java @@ -44,7 +44,7 @@ public class JdkHttpClientMessageSender extends AbstractHttpWebServiceMessageSen private static final Duration DEFAULT_REQUEST_TIMEOUT = Duration.ofSeconds(60); - private HttpClient httpClient; + private @Nullable HttpClient httpClient; private Duration connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; @@ -63,17 +63,17 @@ public class JdkHttpClientMessageSender extends AbstractHttpWebServiceMessageSen this.httpClient = httpClient; } - public void setConnectionTimeout(@Nullable Duration connectionTimeout) { + public void setConnectionTimeout(Duration connectionTimeout) { this.connectionTimeout = connectionTimeout; } - public void setRequestTimeout(@Nullable Duration requestTimeout) { + public void setRequestTimeout(Duration requestTimeout) { this.requestTimeout = requestTimeout; } @Override public WebServiceConnection createConnection(URI uri) throws IOException { - + Assert.state(this.httpClient != null, "HttpClient is not available"); JdkHttpClientConnection connection = new JdkHttpClientConnection(this.httpClient, uri, this.requestTimeout); if (isAcceptGzipEncoding()) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java index 234f330c..e1e6bcb6 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java @@ -16,10 +16,12 @@ package org.springframework.ws.transport.http; +import java.util.Collections; import java.util.Map; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanInitializationException; @@ -112,27 +114,31 @@ public class MessageDispatcherServlet extends FrameworkServlet { private String messageReceiverHandlerAdapterBeanName = DEFAULT_MESSAGE_RECEIVER_HANDLER_ADAPTER_BEAN_NAME; /** The {@link WebServiceMessageReceiverHandlerAdapter} used by this servlet. */ + @SuppressWarnings("NullAway.Init") private WebServiceMessageReceiverHandlerAdapter messageReceiverHandlerAdapter; private String wsdlDefinitionHandlerAdapterBeanName = DEFAULT_WSDL_DEFINITION_HANDLER_ADAPTER_BEAN_NAME; /** The {@link WsdlDefinitionHandlerAdapter} used by this servlet. */ + @SuppressWarnings("NullAway.Init") private WsdlDefinitionHandlerAdapter wsdlDefinitionHandlerAdapter; private String xsdSchemaHandlerAdapterBeanName = DEFAULT_XSD_SCHEMA_HANDLER_ADAPTER_BEAN_NAME; /** The {@link XsdSchemaHandlerAdapter} used by this servlet. */ + @SuppressWarnings("NullAway.Init") private XsdSchemaHandlerAdapter xsdSchemaHandlerAdapter; private String messageReceiverBeanName = DEFAULT_MESSAGE_RECEIVER_BEAN_NAME; /** The {@link WebServiceMessageReceiver} used by this servlet. */ + @SuppressWarnings("NullAway.Init") private WebServiceMessageReceiver messageReceiver; /** Keys are bean names, values are {@link WsdlDefinition WsdlDefinitions}. */ - private Map wsdlDefinitions; + private Map wsdlDefinitions = Collections.emptyMap(); - private Map xsdSchemas; + private Map xsdSchemas = Collections.emptyMap(); private boolean transformWsdlLocations = false; @@ -142,7 +148,8 @@ public class MessageDispatcherServlet extends FrameworkServlet { * Public constructor, necessary for some Web application servers. */ public MessageDispatcherServlet() { - this(null); + super(); + this.defaultStrategiesHelper = new DefaultStrategiesHelper(MessageDispatcherServlet.class); } /** @@ -337,7 +344,7 @@ public class MessageDispatcherServlet extends FrameworkServlet { * @param request the {@code HttpServletRequest} * @return a definition, or {@code null} */ - protected WsdlDefinition getWsdlDefinition(HttpServletRequest request) { + protected @Nullable WsdlDefinition getWsdlDefinition(HttpServletRequest request) { if (HttpTransportConstants.METHOD_GET.equals(request.getMethod()) && request.getRequestURI().endsWith(WSDL_SUFFIX_NAME)) { String fileName = WebUtils.extractFilenameFromUrlPath(request.getRequestURI()); @@ -358,7 +365,7 @@ public class MessageDispatcherServlet extends FrameworkServlet { * @param request the {@code HttpServletRequest} * @return a schema, or {@code null} */ - protected XsdSchema getXsdSchema(HttpServletRequest request) { + protected @Nullable XsdSchema getXsdSchema(HttpServletRequest request) { if (HttpTransportConstants.METHOD_GET.equals(request.getMethod()) && request.getRequestURI().endsWith(XSD_SUFFIX_NAME)) { String fileName = WebUtils.extractFilenameFromUrlPath(request.getRequestURI()); @@ -459,7 +466,7 @@ public class MessageDispatcherServlet extends FrameworkServlet { catch (NoSuchBeanDefinitionException ex) { this.messageReceiver = this.defaultStrategiesHelper.getDefaultStrategy(WebServiceMessageReceiver.class, context); - if (this.messageReceiver instanceof BeanNameAware) { + if (this.messageReceiver instanceof BeanNameAware && getServletName() != null) { ((BeanNameAware) this.messageReceiver).setBeanName(getServletName()); } if (this.logger.isDebugEnabled()) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java index cebac6cf..90042428 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java @@ -18,6 +18,7 @@ package org.springframework.ws.transport.http; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.jspecify.annotations.Nullable; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.ModelAndView; @@ -49,7 +50,7 @@ public class WebServiceMessageReceiverHandlerAdapter extends WebServiceMessageRe implements HandlerAdapter { @Override - public ModelAndView handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + public @Nullable ModelAndView handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception { if (HttpTransportConstants.METHOD_POST.equals(httpServletRequest.getMethod())) { WebServiceConnection connection = new HttpServletConnection(httpServletRequest, httpServletResponse); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WsdlDefinitionHandlerAdapter.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WsdlDefinitionHandlerAdapter.java index c1fe2697..27db8baf 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WsdlDefinitionHandlerAdapter.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WsdlDefinitionHandlerAdapter.java @@ -27,9 +27,11 @@ import javax.xml.transform.stream.StreamResult; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.ModelAndView; @@ -95,9 +97,9 @@ public class WsdlDefinitionHandlerAdapter extends LocationTransformerObjectSuppo private String schemaLocationExpression = DEFAULT_SCHEMA_LOCATION_EXPRESSION; - private XPathExpression locationXPathExpression; + private @Nullable XPathExpression locationXPathExpression; - private XPathExpression schemaLocationXPathExpression; + private @Nullable XPathExpression schemaLocationXPathExpression; private boolean transformLocations = false; @@ -141,7 +143,7 @@ public class WsdlDefinitionHandlerAdapter extends LocationTransformerObjectSuppo } @Override - public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) + public @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (HttpTransportConstants.METHOD_GET.equals(request.getMethod())) { WsdlDefinition definition = (WsdlDefinition) handler; @@ -199,6 +201,7 @@ public class WsdlDefinitionHandlerAdapter extends LocationTransformerObjectSuppo * @see #transformLocation(String,jakarta.servlet.http.HttpServletRequest) */ protected void transformLocations(Document definitionDocument, HttpServletRequest request) throws Exception { + Assert.notNull(this.locationXPathExpression, "locationXPathExpression is required"); transformLocations(this.locationXPathExpression, definitionDocument, request); } @@ -215,6 +218,7 @@ public class WsdlDefinitionHandlerAdapter extends LocationTransformerObjectSuppo * @see #transformLocation(String,jakarta.servlet.http.HttpServletRequest) */ protected void transformSchemaLocations(Document definitionDocument, HttpServletRequest request) throws Exception { + Assert.notNull(this.schemaLocationXPathExpression, "schemaLocationXPathExpression is required"); transformLocations(this.schemaLocationXPathExpression, definitionDocument, request); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WsdlDefinitionHttpHandler.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WsdlDefinitionHttpHandler.java index c093094a..b8380d52 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WsdlDefinitionHttpHandler.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/WsdlDefinitionHttpHandler.java @@ -42,6 +42,7 @@ public class WsdlDefinitionHttpHandler extends TransformerObjectSupport implemen private static final String CONTENT_TYPE = "text/xml"; + @SuppressWarnings("NullAway.Init") private WsdlDefinition definition; public WsdlDefinitionHttpHandler() { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/XsdSchemaHandlerAdapter.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/XsdSchemaHandlerAdapter.java index a693988a..25ca49b5 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/XsdSchemaHandlerAdapter.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/XsdSchemaHandlerAdapter.java @@ -27,6 +27,7 @@ import javax.xml.transform.stream.StreamResult; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.springframework.beans.factory.InitializingBean; @@ -65,6 +66,7 @@ public class XsdSchemaHandlerAdapter extends LocationTransformerObjectSupport private String schemaLocationExpression = DEFAULT_SCHEMA_LOCATION_EXPRESSION; + @SuppressWarnings("NullAway.Init") private XPathExpression schemaLocationXPathExpression; private boolean transformSchemaLocations = false; @@ -89,7 +91,7 @@ public class XsdSchemaHandlerAdapter extends LocationTransformerObjectSupport } @Override - public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) + public @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (HttpTransportConstants.METHOD_GET.equals(request.getMethod())) { Source schemaSource = getSchemaSource((XsdSchema) handler); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/package-info.java index e54a45e3..5f2a0157 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/package-info.java @@ -20,4 +20,7 @@ * access, and the {@code HttpUrlConnectionMessageSender} and * {@code CommonsHttpMessageSender} for client-side access. */ +@NullMarked package org.springframework.ws.transport.http; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/support/AbstractAnnotationConfigMessageDispatcherServletInitializer.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/support/AbstractAnnotationConfigMessageDispatcherServletInitializer.java index d457a6e5..1dac23e8 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/support/AbstractAnnotationConfigMessageDispatcherServletInitializer.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/support/AbstractAnnotationConfigMessageDispatcherServletInitializer.java @@ -16,6 +16,8 @@ package org.springframework.ws.transport.http.support; +import org.jspecify.annotations.Nullable; + import org.springframework.context.annotation.Configuration; import org.springframework.util.ObjectUtils; import org.springframework.web.WebApplicationInitializer; @@ -48,7 +50,7 @@ public abstract class AbstractAnnotationConfigMessageDispatcherServletInitialize * Returns {@code null} if {@link #getRootConfigClasses()} returns {@code null}. */ @Override - protected WebApplicationContext createRootApplicationContext() { + protected @Nullable WebApplicationContext createRootApplicationContext() { Class[] configClasses = getRootConfigClasses(); if (!ObjectUtils.isEmpty(configClasses)) { AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext(); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/support/package-info.java index f3b2a67b..759afcfc 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/support/package-info.java @@ -17,4 +17,7 @@ /** * Support classes for handling messages via HTTP. */ +@NullMarked package org.springframework.ws.transport.http.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/package-info.java index 775f1042..ff8d68db 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/package-info.java @@ -17,4 +17,7 @@ /** * Contains the TransportRequest and TransportResponse interfaces. */ +@NullMarked package org.springframework.ws.transport; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/support/AbstractAsyncStandaloneMessageReceiver.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/support/AbstractAsyncStandaloneMessageReceiver.java index e7df2c2c..1db6d3e7 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/support/AbstractAsyncStandaloneMessageReceiver.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/support/AbstractAsyncStandaloneMessageReceiver.java @@ -16,6 +16,8 @@ package org.springframework.ws.transport.support; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.BeanNameAware; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.TaskExecutor; @@ -33,9 +35,10 @@ public abstract class AbstractAsyncStandaloneMessageReceiver extends AbstractSta /** Default thread name prefix. */ public final String DEFAULT_THREAD_NAME_PREFIX = ClassUtils.getShortName(getClass()) + "-"; + @SuppressWarnings("NullAway.Init") private TaskExecutor taskExecutor; - private String beanName; + private @Nullable String beanName; /** * Set the Spring {@link TaskExecutor} to use for running the listener threads. diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/support/SimpleWebServiceMessageReceiverObjectSupport.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/support/SimpleWebServiceMessageReceiverObjectSupport.java index 46e608d7..ec6ec008 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/support/SimpleWebServiceMessageReceiverObjectSupport.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/support/SimpleWebServiceMessageReceiverObjectSupport.java @@ -32,6 +32,7 @@ import org.springframework.ws.transport.WebServiceMessageReceiver; public abstract class SimpleWebServiceMessageReceiverObjectSupport extends WebServiceMessageReceiverObjectSupport implements InitializingBean { + @SuppressWarnings("NullAway.Init") private WebServiceMessageReceiver messageReceiver; /** diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java index 24544bf3..70890c5f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java @@ -51,6 +51,7 @@ public abstract class WebServiceMessageReceiverObjectSupport implements Initiali /** Logger available to subclasses. */ protected final Log logger = LogFactory.getLog(getClass()); + @SuppressWarnings("NullAway.Init") private WebServiceMessageFactory messageFactory; /** Returns the {@code WebServiceMessageFactory}. */ @@ -88,6 +89,7 @@ public abstract class WebServiceMessageReceiverObjectSupport implements Initiali try { WebServiceMessage request = connection.receive(getMessageFactory()); + Assert.notNull(request, "no WebServiceMessage received"); MessageContext messageContext = new DefaultMessageContext(request, getMessageFactory()); receiver.receive(messageContext); if (messageContext.hasResponse()) { diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/support/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/support/package-info.java index 7966d3a7..1640ebd1 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/support/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/support/package-info.java @@ -17,4 +17,7 @@ /** * Classes supporting the org.springframework.ws.transport package. */ +@NullMarked package org.springframework.ws.transport.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/WsdlDefinitionException.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/WsdlDefinitionException.java index b08b3937..00e21cbc 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/WsdlDefinitionException.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/WsdlDefinitionException.java @@ -16,6 +16,8 @@ package org.springframework.ws.wsdl; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceException; /** @@ -31,7 +33,7 @@ public class WsdlDefinitionException extends WebServiceException { super(reason); } - public WsdlDefinitionException(String reason, Throwable throwable) { + public WsdlDefinitionException(@Nullable String reason, Throwable throwable) { super(reason, throwable); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/package-info.java index b0a64276..42b58de0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/package-info.java @@ -18,4 +18,7 @@ * Provides the WSDL functionality of the Spring Web Services framework. Contains the * WsdlDefinition and related interfaces. */ +@NullMarked package org.springframework.ws.wsdl; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/DefaultWsdl11Definition.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/DefaultWsdl11Definition.java index d711c2a0..3e6d850e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/DefaultWsdl11Definition.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/DefaultWsdl11Definition.java @@ -20,6 +20,8 @@ import java.util.Properties; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.InitializingBean; import org.springframework.util.StringUtils; import org.springframework.ws.wsdl.wsdl11.provider.DefaultMessagesProvider; @@ -63,7 +65,7 @@ public class DefaultWsdl11Definition implements Wsdl11Definition, InitializingBe private final ProviderBasedWsdl4jDefinition delegate = new ProviderBasedWsdl4jDefinition(); - private String serviceName; + private @Nullable String serviceName; /** Creates a new instance of the {@link DefaultWsdl11Definition}. */ public DefaultWsdl11Definition() { @@ -175,7 +177,7 @@ public class DefaultWsdl11Definition implements Wsdl11Definition, InitializingBe @Override public void afterPropertiesSet() throws Exception { - if (!StringUtils.hasText(this.delegate.getTargetNamespace()) && this.typesProvider.getSchemaCollection() != null + if (!StringUtils.hasText(this.delegate.getTargetNamespace()) && this.typesProvider.getSchemaCollection().getXsdSchemas().length > 0) { XsdSchema schema = this.typesProvider.getSchemaCollection().getXsdSchemas()[0]; setTargetNamespace(schema.getTargetNamespace()); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/ProviderBasedWsdl4jDefinition.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/ProviderBasedWsdl4jDefinition.java index dd0298f5..02e14af1 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/ProviderBasedWsdl4jDefinition.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/ProviderBasedWsdl4jDefinition.java @@ -20,6 +20,8 @@ import javax.wsdl.Definition; import javax.wsdl.WSDLException; import javax.wsdl.factory.WSDLFactory; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.ws.wsdl.wsdl11.provider.BindingsProvider; @@ -62,19 +64,19 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I /** The prefix used to register the target namespace in the WSDL. */ public static final String TARGET_NAMESPACE_PREFIX = "tns"; - private ImportsProvider importsProvider; + private @Nullable ImportsProvider importsProvider; - private TypesProvider typesProvider; + private @Nullable TypesProvider typesProvider; - private MessagesProvider messagesProvider; + private @Nullable MessagesProvider messagesProvider; - private PortTypesProvider portTypesProvider; + private @Nullable PortTypesProvider portTypesProvider; - private BindingsProvider bindingsProvider; + private @Nullable BindingsProvider bindingsProvider; - private ServicesProvider servicesProvider; + private @Nullable ServicesProvider servicesProvider; - private String targetNamespace; + private @Nullable String targetNamespace; /** * Returns the {@link ImportsProvider} for this definition. @@ -82,7 +84,7 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I * Default is {@code null}, indicating that no {@code <import>} will be created * @return the import provider; or {@code null} */ - public ImportsProvider getImportsProvider() { + public @Nullable ImportsProvider getImportsProvider() { return this.importsProvider; } @@ -102,7 +104,7 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I * Defaults to {@code null}, indicating that no {@code <types>} will be created * @return the types provider; or {@code null} */ - public TypesProvider getTypesProvider() { + public @Nullable TypesProvider getTypesProvider() { return this.typesProvider; } @@ -123,7 +125,7 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I * created * @return the messages provider; or {@code null} */ - public MessagesProvider getMessagesProvider() { + public @Nullable MessagesProvider getMessagesProvider() { return this.messagesProvider; } @@ -145,7 +147,7 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I * created * @return the port types provider; or {@code null} */ - public PortTypesProvider getPortTypesProvider() { + public @Nullable PortTypesProvider getPortTypesProvider() { return this.portTypesProvider; } @@ -167,7 +169,7 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I * created * @return the binding provider; or {@code null} */ - public BindingsProvider getBindingsProvider() { + public @Nullable BindingsProvider getBindingsProvider() { return this.bindingsProvider; } @@ -189,7 +191,7 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I * created * @return the services provider; or {@code null} */ - public ServicesProvider getServicesProvider() { + public @Nullable ServicesProvider getServicesProvider() { return this.servicesProvider; } @@ -209,7 +211,7 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I * @return the target namespace * @see javax.wsdl.Definition#getTargetNamespace() */ - public String getTargetNamespace() { + public @Nullable String getTargetNamespace() { return this.targetNamespace; } @@ -224,11 +226,11 @@ public class ProviderBasedWsdl4jDefinition extends Wsdl4jDefinition implements I @Override public void afterPropertiesSet() throws WSDLException { - Assert.notNull(getTargetNamespace(), "'targetNamespace' is required"); + Assert.notNull(this.targetNamespace, "'targetNamespace' is required"); WSDLFactory wsdlFactory = WSDLFactory.newInstance(); Definition definition = wsdlFactory.newDefinition(); definition.setTargetNamespace(getTargetNamespace()); - definition.addNamespace(TARGET_NAMESPACE_PREFIX, getTargetNamespace()); + definition.addNamespace(TARGET_NAMESPACE_PREFIX, this.targetNamespace); if (this.importsProvider != null) { this.importsProvider.addImports(definition); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/SimpleWsdl11Definition.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/SimpleWsdl11Definition.java index 893df556..9d6dcff3 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/SimpleWsdl11Definition.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/SimpleWsdl11Definition.java @@ -20,6 +20,7 @@ import java.io.IOException; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; @@ -41,7 +42,7 @@ import org.springframework.xml.transform.ResourceSource; */ public class SimpleWsdl11Definition implements Wsdl11Definition, InitializingBean { - private Resource wsdlResource; + private @Nullable Resource wsdlResource; /** * Create a new instance of the {@link SimpleWsdl11Definition} class. @@ -71,6 +72,7 @@ public class SimpleWsdl11Definition implements Wsdl11Definition, InitializingBea @Override public Source getSource() { + Assert.notNull(this.wsdlResource, "wsdl is required"); try { XMLReader xmlReader = SaxUtils.namespaceAwareXmlReader(); xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/Wsdl4jDefinition.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/Wsdl4jDefinition.java index fb7d616d..49c2cb8d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/Wsdl4jDefinition.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/Wsdl4jDefinition.java @@ -23,6 +23,7 @@ import javax.wsdl.xml.WSDLWriter; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.springframework.util.Assert; @@ -42,7 +43,7 @@ import org.springframework.ws.wsdl.WsdlDefinitionException; */ public class Wsdl4jDefinition implements Wsdl11Definition { - private Definition definition; + private @Nullable Definition definition; /** WSDL4J is not thread safe, hence the need for a monitor. */ private final Object monitor = new Object(); @@ -63,7 +64,7 @@ public class Wsdl4jDefinition implements Wsdl11Definition { } /** Returns the WSDL4J {@code Definition}. */ - public Definition getDefinition() { + public @Nullable Definition getDefinition() { synchronized (this.monitor) { return this.definition; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/package-info.java index 67da6e82..0d10ab6e 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/package-info.java @@ -17,4 +17,7 @@ /** * Contains interfaces and classes specific to WSDL 1.1. */ +@NullMarked package org.springframework.ws.wsdl.wsdl11; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/AbstractPortTypesProvider.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/AbstractPortTypesProvider.java index 38a2758c..aafef1f6 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/AbstractPortTypesProvider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/AbstractPortTypesProvider.java @@ -31,8 +31,10 @@ import javax.xml.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; @@ -48,10 +50,10 @@ public abstract class AbstractPortTypesProvider implements PortTypesProvider { /** Logger available to subclasses. */ protected final Log logger = LogFactory.getLog(getClass()); - private String portTypeName; + private @Nullable String portTypeName; /** Returns the port type name used for this definition. */ - public String getPortTypeName() { + public @Nullable String getPortTypeName() { return this.portTypeName; } @@ -116,24 +118,26 @@ public abstract class AbstractPortTypesProvider implements PortTypesProvider { Operation operation = definition.createOperation(); operation.setName(operationName); List messages = operations.get(operationName); - for (Message message : messages) { - if (isInputMessage(message)) { - Input input = definition.createInput(); - input.setMessage(message); - populateInput(definition, input); - operation.setInput(input); - } - else if (isOutputMessage(message)) { - Output output = definition.createOutput(); - output.setMessage(message); - populateOutput(definition, output); - operation.setOutput(output); - } - else if (isFaultMessage(message)) { - Fault fault = definition.createFault(); - fault.setMessage(message); - populateFault(definition, fault); - operation.addFault(fault); + if (!CollectionUtils.isEmpty(messages)) { + for (Message message : messages) { + if (isInputMessage(message)) { + Input input = definition.createInput(); + input.setMessage(message); + populateInput(definition, input); + operation.setInput(input); + } + else if (isOutputMessage(message)) { + Output output = definition.createOutput(); + output.setMessage(message); + populateOutput(definition, output); + operation.setOutput(output); + } + else if (isFaultMessage(message)) { + Fault fault = definition.createFault(); + fault.setMessage(message); + populateFault(definition, fault); + operation.addFault(fault); + } } } operation.setStyle(getOperationType(operation)); @@ -153,7 +157,7 @@ public abstract class AbstractPortTypesProvider implements PortTypesProvider { * @param message the WSDL4J {@code Message} * @return the operation name; or {@code null} */ - protected abstract String getOperationName(Message message); + protected abstract @Nullable String getOperationName(Message message); /** * Indicates whether the given name name should be included as {@link Input} message @@ -224,7 +228,7 @@ public abstract class AbstractPortTypesProvider implements PortTypesProvider { * @param operation the WSDL4J {@code Operation} * @return the operation type for the operation */ - protected OperationType getOperationType(Operation operation) { + protected @Nullable OperationType getOperationType(Operation operation) { if (operation.getInput() != null && operation.getOutput() != null) { return OperationType.REQUEST_RESPONSE; diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/DefaultConcretePartProvider.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/DefaultConcretePartProvider.java index 82f90585..2add2b67 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/DefaultConcretePartProvider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/DefaultConcretePartProvider.java @@ -35,6 +35,7 @@ import javax.xml.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -55,12 +56,12 @@ public class DefaultConcretePartProvider implements BindingsProvider, ServicesPr /** Logger available to subclasses. */ protected final Log logger = LogFactory.getLog(getClass()); - private String bindingSuffix; + private @Nullable String bindingSuffix; - private String serviceName; + private @Nullable String serviceName; /** Returns the service name. */ - public String getServiceName() { + public @Nullable String getServiceName() { return this.serviceName; } @@ -72,7 +73,7 @@ public class DefaultConcretePartProvider implements BindingsProvider, ServicesPr } /** Returns the suffix to append to the port type name to obtain the binding name. */ - public String getBindingSuffix() { + public @Nullable String getBindingSuffix() { return this.bindingSuffix; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/InliningXsdSchemaTypesProvider.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/InliningXsdSchemaTypesProvider.java index af12e1d5..f985947f 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/InliningXsdSchemaTypesProvider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/InliningXsdSchemaTypesProvider.java @@ -26,6 +26,7 @@ import javax.xml.transform.dom.DOMResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -50,7 +51,7 @@ public class InliningXsdSchemaTypesProvider extends TransformerObjectSupport imp /** The prefix used to register the schema namespace in the WSDL. */ public static final String SCHEMA_PREFIX = "sch"; - private XsdSchemaCollection schemaCollection; + private @Nullable XsdSchemaCollection schemaCollection; /** * Sets the single XSD schema to inline. Either this property, or @@ -71,6 +72,7 @@ public class InliningXsdSchemaTypesProvider extends TransformerObjectSupport imp /** Returns the XSD schema collection to inline. */ public XsdSchemaCollection getSchemaCollection() { + Assert.notNull(this.schemaCollection, "setting 'schema' or 'schemaCollection' is required"); return this.schemaCollection; } @@ -84,9 +86,8 @@ public class InliningXsdSchemaTypesProvider extends TransformerObjectSupport imp @Override public void addTypes(Definition definition) throws WSDLException { - Assert.notNull(getSchemaCollection(), "setting 'schema' or 'schemaCollection' is required"); Types types = definition.createTypes(); - XsdSchema[] schemas = this.schemaCollection.getXsdSchemas(); + XsdSchema[] schemas = getSchemaCollection().getXsdSchemas(); for (int i = 0; i < schemas.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Inlining " + schemas[i]); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/Soap11Provider.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/Soap11Provider.java index 4452d529..f65ba40a 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/Soap11Provider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/Soap11Provider.java @@ -38,6 +38,8 @@ import javax.wsdl.extensions.soap.SOAPFault; import javax.wsdl.extensions.soap.SOAPOperation; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -67,7 +69,7 @@ public class Soap11Provider extends DefaultConcretePartProvider { private Properties soapActions = new Properties(); - private String locationUri; + private @Nullable String locationUri; /** * Constructs a new version of the {@link Soap11Provider}. @@ -123,7 +125,7 @@ public class Soap11Provider extends DefaultConcretePartProvider { } /** Returns the value used for the SOAP Address location attribute value. */ - public String getLocationUri() { + public @Nullable String getLocationUri() { return this.locationUri; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/Soap12Provider.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/Soap12Provider.java index 113d5857..3af96b22 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/Soap12Provider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/Soap12Provider.java @@ -37,6 +37,8 @@ import javax.wsdl.extensions.soap12.SOAP12Fault; import javax.wsdl.extensions.soap12.SOAP12Operation; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -66,7 +68,7 @@ public class Soap12Provider extends DefaultConcretePartProvider { private Properties soapActions = new Properties(); - private String locationUri; + private @Nullable String locationUri; /** * Constructs a new version of the {@link Soap12Provider}. @@ -122,7 +124,7 @@ public class Soap12Provider extends DefaultConcretePartProvider { } /** Returns the value used for the SOAP Address location attribute value. */ - public String getLocationUri() { + public @Nullable String getLocationUri() { return this.locationUri; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/SuffixBasedPortTypesProvider.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/SuffixBasedPortTypesProvider.java index 8d71b88f..174972ae 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/SuffixBasedPortTypesProvider.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/SuffixBasedPortTypesProvider.java @@ -18,6 +18,8 @@ package org.springframework.ws.wsdl.wsdl11.provider; import javax.wsdl.Message; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -95,7 +97,7 @@ public class SuffixBasedPortTypesProvider extends AbstractPortTypesProvider { } @Override - protected String getOperationName(Message message) { + protected @Nullable String getOperationName(Message message) { String messageName = getMessageName(message); if (messageName != null) { if (messageName.endsWith(getRequestSuffix())) { @@ -156,7 +158,7 @@ public class SuffixBasedPortTypesProvider extends AbstractPortTypesProvider { return messageName != null && messageName.endsWith(getFaultSuffix()); } - private String getMessageName(Message message) { + private @Nullable String getMessageName(Message message) { return message.getQName().getLocalPart(); } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/package-info.java b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/package-info.java index 7beccb0c..eb3bba06 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/package-info.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/package-info.java @@ -17,4 +17,7 @@ /** * Provides a contribution strategy for WSDL definitions. */ +@NullMarked package org.springframework.ws.wsdl.wsdl11.provider; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-core/src/test/java/org/springframework/ws/server/endpoint/CompositeEndpointExceptionResolverTests.java b/spring-ws-core/src/test/java/org/springframework/ws/server/endpoint/CompositeEndpointExceptionResolverTests.java index 285ab116..d1c4f6db 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/server/endpoint/CompositeEndpointExceptionResolverTests.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/server/endpoint/CompositeEndpointExceptionResolverTests.java @@ -75,7 +75,7 @@ class CompositeEndpointExceptionResolverTests { } @Override - protected void logException(Exception ex, MessageContext messageContext) { + protected void logException(MessageContext messageContext, Exception ex) { if (this.logException) { throw new IllegalStateException("Log exception already called"); } diff --git a/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/SimpleActionEndpointMappingTests.java b/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/SimpleActionEndpointMappingTests.java index 6a15d53c..1dd6284b 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/SimpleActionEndpointMappingTests.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/SimpleActionEndpointMappingTests.java @@ -23,6 +23,7 @@ import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.context.support.StaticApplicationContext; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointInterceptor; @@ -57,6 +58,7 @@ class SimpleActionEndpointMappingTests extends AbstractWsAddressingTests { this.mapping.setPostInterceptors(new EndpointInterceptor[] { new PayloadValidatingInterceptor() }); this.mapping.setAddress(new URI("mailto:fabrikam@example.com")); this.mapping.setActionMap(map); + this.mapping.setApplicationContext(new StaticApplicationContext()); this.mapping.afterPropertiesSet(); } diff --git a/spring-ws-core/src/test/java/org/springframework/ws/transport/http/HttpComponents5MessageSenderTests.java b/spring-ws-core/src/test/java/org/springframework/ws/transport/http/HttpComponents5MessageSenderTests.java index e53bf754..d0a5e7b4 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/transport/http/HttpComponents5MessageSenderTests.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/transport/http/HttpComponents5MessageSenderTests.java @@ -33,7 +33,7 @@ class HttpComponents5MessageSenderTests { @Test void afterPropertiesSetShouldProperlyInitializeHttpClient() throws Exception { HttpComponents5MessageSender messageSender = new HttpComponents5MessageSender(); - assertThat(messageSender.getHttpClient()).isNull(); + assertThat(messageSender).hasFieldOrPropertyWithValue("httpClient", null); messageSender.setConnectionTimeout(Duration.ofSeconds(1)); messageSender.afterPropertiesSet();