diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsMessageReceiver.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsMessageReceiver.java index f6d7ec60..9e37e17e 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsMessageReceiver.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsMessageReceiver.java @@ -20,6 +20,7 @@ import jakarta.jms.BytesMessage; import jakarta.jms.Message; import jakarta.jms.Session; import jakarta.jms.TextMessage; +import org.jspecify.annotations.Nullable; import org.springframework.jms.core.MessagePostProcessor; import org.springframework.ws.transport.WebServiceMessageReceiver; @@ -44,7 +45,7 @@ public class JmsMessageReceiver extends SimpleWebServiceMessageReceiverObjectSup private String textMessageEncoding = DEFAULT_TEXT_MESSAGE_ENCODING; - private MessagePostProcessor postProcessor; + private @Nullable MessagePostProcessor postProcessor; /** * Sets the encoding used to read from and write to {@link TextMessage} messages. diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsMessageSender.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsMessageSender.java index 06e16c9b..61a1686e 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsMessageSender.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsMessageSender.java @@ -27,11 +27,13 @@ import jakarta.jms.Message; import jakarta.jms.Queue; import jakarta.jms.Session; import jakarta.jms.Topic; +import org.jspecify.annotations.Nullable; import org.springframework.jms.connection.ConnectionFactoryUtils; import org.springframework.jms.core.MessagePostProcessor; import org.springframework.jms.support.JmsUtils; import org.springframework.jms.support.destination.JmsDestinationAccessor; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.ws.transport.WebServiceConnection; import org.springframework.ws.transport.WebServiceMessageSender; @@ -117,7 +119,7 @@ public class JmsMessageSender extends JmsDestinationAccessor implements WebServi private String textMessageEncoding = DEFAULT_TEXT_MESSAGE_ENCODING; - private MessagePostProcessor postProcessor; + private @Nullable MessagePostProcessor postProcessor; /** * Create a new {@code JmsMessageSender} @@ -165,6 +167,8 @@ public class JmsMessageSender extends JmsDestinationAccessor implements WebServi @Override public WebServiceConnection createConnection(URI uri) throws IOException { + ConnectionFactory connectionFactory = getConnectionFactory(); + Assert.notNull(connectionFactory, "ConnectionFactory is required"); Connection jmsConnection = null; Session jmsSession = null; try { @@ -172,8 +176,8 @@ public class JmsMessageSender extends JmsDestinationAccessor implements WebServi jmsSession = createSession(jmsConnection); Destination requestDestination = resolveRequestDestination(jmsSession, uri); Message requestMessage = createRequestMessage(jmsSession, uri); - JmsSenderConnection wsConnection = new JmsSenderConnection(getConnectionFactory(), jmsConnection, - jmsSession, requestDestination, requestMessage); + JmsSenderConnection wsConnection = new JmsSenderConnection(connectionFactory, jmsConnection, jmsSession, + requestDestination, requestMessage); wsConnection.setDeliveryMode(JmsTransportUtils.getDeliveryMode(uri)); wsConnection.setPriority(JmsTransportUtils.getPriority(uri)); wsConnection.setReceiveTimeout(this.receiveTimeout); @@ -197,10 +201,12 @@ public class JmsMessageSender extends JmsDestinationAccessor implements WebServi } private Destination resolveRequestDestination(Session session, URI uri) throws JMSException { - return resolveDestinationName(session, JmsTransportUtils.getDestinationName(uri)); + String destinationName = JmsTransportUtils.getDestinationName(uri); + Assert.notNull(destinationName, "No destination name found for URI [" + uri + "]"); + return resolveDestinationName(session, destinationName); } - private Destination resolveResponseDestination(Session session, URI uri) throws JMSException { + private @Nullable Destination resolveResponseDestination(Session session, URI uri) throws JMSException { String destinationName = JmsTransportUtils.getReplyToName(uri); return StringUtils.hasLength(destinationName) ? resolveDestinationName(session, destinationName) : null; } diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java index 65ed4c57..a3443ded 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java @@ -29,6 +29,7 @@ import jakarta.jms.Message; import jakarta.jms.MessageProducer; import jakarta.jms.Session; import jakarta.jms.TextMessage; +import org.jspecify.annotations.Nullable; import org.springframework.jms.core.MessagePostProcessor; import org.springframework.jms.support.JmsUtils; @@ -57,11 +58,11 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { private final Session session; - private Message responseMessage; + private @Nullable Message responseMessage; - private String textMessageEncoding; + private @Nullable String textMessageEncoding; - private MessagePostProcessor postProcessor; + private @Nullable MessagePostProcessor postProcessor; private JmsReceiverConnection(Message requestMessage, Session session) { Assert.notNull(requestMessage, "requestMessage must not be null"); @@ -89,7 +90,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { this.textMessageEncoding = encoding; } - void setPostProcessor(MessagePostProcessor postProcessor) { + void setPostProcessor(@Nullable MessagePostProcessor postProcessor) { this.postProcessor = postProcessor; } @@ -105,7 +106,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { * Returns the response message, if any, for this connection. Returns either a * {@link BytesMessage} or a {@link TextMessage}. */ - public Message getResponseMessage() { + public @Nullable Message getResponseMessage() { return this.responseMessage; } @@ -114,7 +115,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { */ @Override - public URI getUri() throws URISyntaxException { + public @Nullable URI getUri() throws URISyntaxException { try { return JmsTransportUtils.toUri(this.requestMessage.getJMSDestination()); } @@ -128,7 +129,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { */ @Override - public String getErrorMessage() throws IOException { + public @Nullable String getErrorMessage() throws IOException { return null; } @@ -167,6 +168,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { return new BytesMessageInputStream((BytesMessage) this.requestMessage); } else if (this.requestMessage instanceof TextMessage) { + Assert.notNull(this.textMessageEncoding, "MessageEncoding for TextMessage is required"); return new TextMessageInputStream((TextMessage) this.requestMessage, this.textMessageEncoding); } else { @@ -181,15 +183,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { @Override protected void onSendBeforeWrite(WebServiceMessage message) throws IOException { try { - if (this.requestMessage instanceof BytesMessage) { - this.responseMessage = this.session.createBytesMessage(); - } - else if (this.requestMessage instanceof TextMessage) { - this.responseMessage = this.session.createTextMessage(); - } - else { - throw new IllegalStateException("Unknown request message type [" + this.requestMessage + "]"); - } + this.responseMessage = createResponseMessage(); String correlation = this.requestMessage.getJMSCorrelationID(); if (correlation == null) { correlation = this.requestMessage.getJMSMessageID(); @@ -201,8 +195,21 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { } } + private Message createResponseMessage() throws JMSException { + if (this.requestMessage instanceof BytesMessage) { + return this.session.createBytesMessage(); + } + else if (this.requestMessage instanceof TextMessage) { + return this.session.createTextMessage(); + } + else { + throw new IllegalStateException("Unknown request message type [" + this.requestMessage + "]"); + } + } + @Override public void addResponseHeader(String name, String value) throws IOException { + Assert.state(this.responseMessage != null, "Response message is not available"); try { JmsTransportUtils.addHeader(this.responseMessage, name, value); } @@ -217,6 +224,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { return new BytesMessageOutputStream((BytesMessage) this.responseMessage); } else if (this.responseMessage instanceof TextMessage) { + Assert.notNull(this.textMessageEncoding, "MessageEncoding for TextMessage is required"); return new TextMessageOutputStream((TextMessage) this.responseMessage, this.textMessageEncoding); } else { @@ -226,6 +234,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { @Override protected void onSendAfterWrite(WebServiceMessage message) throws IOException { + Assert.state(this.responseMessage != null, "Response message is not available"); MessageProducer messageProducer = null; try { if (this.requestMessage.getJMSReplyTo() != null) { diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsSenderConnection.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsSenderConnection.java index 258ab5a2..7470efda 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsSenderConnection.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/JmsSenderConnection.java @@ -34,6 +34,7 @@ import jakarta.jms.MessageProducer; import jakarta.jms.Session; import jakarta.jms.TemporaryQueue; import jakarta.jms.TextMessage; +import org.jspecify.annotations.Nullable; import org.springframework.jms.connection.ConnectionFactoryUtils; import org.springframework.jms.core.MessagePostProcessor; @@ -64,9 +65,9 @@ public class JmsSenderConnection extends AbstractSenderConnection { private Message requestMessage; - private Destination responseDestination; + private @Nullable Destination responseDestination; - private Message responseMessage; + private @Nullable Message responseMessage; private long receiveTimeout; @@ -76,9 +77,9 @@ public class JmsSenderConnection extends AbstractSenderConnection { private int priority; - private String textMessageEncoding; + private @Nullable String textMessageEncoding; - private MessagePostProcessor postProcessor; + private @Nullable MessagePostProcessor postProcessor; private boolean sessionTransacted = false; @@ -111,7 +112,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { * Returns the response message, if any, for this connection. Returns either a * {@link BytesMessage} or a {@link TextMessage}. */ - public Message getResponseMessage() { + public @Nullable Message getResponseMessage() { return this.responseMessage; } @@ -119,7 +120,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { * Package-friendly setters */ - void setResponseDestination(Destination responseDestination) { + void setResponseDestination(@Nullable Destination responseDestination) { this.responseDestination = responseDestination; } @@ -143,7 +144,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { this.textMessageEncoding = textMessageEncoding; } - void setPostProcessor(MessagePostProcessor postProcessor) { + void setPostProcessor(@Nullable MessagePostProcessor postProcessor) { this.postProcessor = postProcessor; } @@ -156,7 +157,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { */ @Override - public URI getUri() throws URISyntaxException { + public @Nullable URI getUri() throws URISyntaxException { try { return JmsTransportUtils.toUri(this.requestDestination); } @@ -175,7 +176,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { } @Override - public String getErrorMessage() throws IOException { + public @Nullable String getErrorMessage() throws IOException { return null; } @@ -199,6 +200,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { return new BytesMessageOutputStream((BytesMessage) this.requestMessage); } else if (this.requestMessage instanceof TextMessage) { + Assert.notNull(this.textMessageEncoding, "MessageEncoding for TextMessage is required"); return new TextMessageOutputStream((TextMessage) this.requestMessage, this.textMessageEncoding); } else { @@ -277,9 +279,10 @@ public class JmsSenderConnection extends AbstractSenderConnection { } finally { JmsUtils.closeMessageConsumer(messageConsumer); - if (this.temporaryResponseQueueCreated) { + if (this.temporaryResponseQueueCreated + && this.responseDestination instanceof TemporaryQueue temporaryQueue) { try { - ((TemporaryQueue) this.responseDestination).delete(); + temporaryQueue.delete(); } catch (JMSException ex) { // ignore @@ -296,6 +299,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { @Override public Iterator getResponseHeaderNames() throws IOException { try { + Assert.state(this.responseMessage != null, "ResponseMessage is required"); return JmsTransportUtils.getHeaderNames(this.responseMessage); } catch (JMSException ex) { @@ -306,6 +310,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { @Override public Iterator getResponseHeaders(String name) throws IOException { try { + Assert.state(this.responseMessage != null, "ResponseMessage is required"); return JmsTransportUtils.getHeaders(this.responseMessage, name); } catch (JMSException ex) { @@ -319,6 +324,7 @@ public class JmsSenderConnection extends AbstractSenderConnection { return new BytesMessageInputStream((BytesMessage) this.responseMessage); } else if (this.responseMessage instanceof TextMessage) { + Assert.notNull(this.textMessageEncoding, "MessageEncoding for TextMessage is required"); return new TextMessageInputStream((TextMessage) this.responseMessage, this.textMessageEncoding); } else { diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/package-info.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/package-info.java index cc815875..c2b6919d 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/package-info.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/package-info.java @@ -17,4 +17,7 @@ /** * Package providing support for handling messages via JMS. */ +@NullMarked package org.springframework.ws.transport.jms; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/support/JmsTransportUtils.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/support/JmsTransportUtils.java index 5470c0fc..cd8f7448 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/support/JmsTransportUtils.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/support/JmsTransportUtils.java @@ -32,6 +32,7 @@ import jakarta.jms.JMSException; import jakarta.jms.Message; import jakarta.jms.Queue; import jakarta.jms.Topic; +import org.jspecify.annotations.Nullable; import org.springframework.ws.transport.jms.JmsTransportConstants; @@ -100,7 +101,7 @@ public abstract class JmsTransportUtils { * @param destination the destination * @return a jms URI */ - public static URI toUri(Destination destination) throws URISyntaxException, JMSException { + public static @Nullable URI toUri(@Nullable Destination destination) throws URISyntaxException, JMSException { if (destination == null) { return null; } @@ -118,7 +119,7 @@ public abstract class JmsTransportUtils { } /** Returns the destination name of the given URI. */ - public static String getDestinationName(URI uri) { + public static @Nullable String getDestinationName(URI uri) { return getStringParameter(DESTINATION_NAME_PATTERN, uri); } @@ -215,11 +216,11 @@ public abstract class JmsTransportUtils { * Returns the reply-to name of the given URI. * @see Message#setJMSReplyTo(Destination) */ - public static String getReplyToName(URI uri) { + public static @Nullable String getReplyToName(URI uri) { return getStringParameter(REPLY_TO_NAME_PATTERN, uri); } - private static String getStringParameter(Pattern pattern, URI uri) { + private static @Nullable String getStringParameter(Pattern pattern, URI uri) { Matcher matcher = pattern.matcher(uri.getSchemeSpecificPart()); if (matcher.find() && matcher.groupCount() == 1) { return matcher.group(1); diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/support/package-info.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/support/package-info.java index c21354fc..e7b5db05 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/support/package-info.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/jms/support/package-info.java @@ -17,4 +17,7 @@ /** * Classes supporting the org.springframework.ws.transport.jms package. */ +@NullMarked package org.springframework.ws.transport.jms.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailMessageReceiver.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailMessageReceiver.java index df65e92b..6c7b4d4d 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailMessageReceiver.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailMessageReceiver.java @@ -16,6 +16,7 @@ package org.springframework.ws.transport.mail; +import java.util.Objects; import java.util.Properties; import jakarta.mail.Folder; @@ -27,6 +28,7 @@ import jakarta.mail.Store; import jakarta.mail.URLName; import jakarta.mail.internet.AddressException; import jakarta.mail.internet.InternetAddress; +import org.jspecify.annotations.Nullable; import org.springframework.scheduling.SchedulingAwareRunnable; import org.springframework.util.Assert; @@ -58,18 +60,21 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver private Session session = Session.getInstance(new Properties(), null); + @SuppressWarnings("NullAway.Init") private URLName storeUri; + @SuppressWarnings("NullAway.Init") private URLName transportUri; - private Folder folder; - - private Store store; - - private InternetAddress from; - + @SuppressWarnings("NullAway.Init") private MonitoringStrategy monitoringStrategy; + private @Nullable Folder folder; + + private @Nullable Store store; + + private @Nullable InternetAddress from; + /** Sets the from address to use when sending response messages. */ public void setFrom(String from) throws AddressException { this.from = new InternetAddress(from); @@ -201,7 +206,7 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver if (this.folder != null && this.folder.isOpen()) { return; } - this.folder = this.store.getFolder(this.storeUri); + this.folder = Objects.requireNonNull(this.store).getFolder(this.storeUri); if (this.folder == null || !this.folder.exists()) { throw new IllegalStateException("No default folder to receive from"); } @@ -228,7 +233,7 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver while (isRunning()) { try { Message[] messages = MailMessageReceiver.this.monitoringStrategy - .monitor(MailMessageReceiver.this.folder); + .monitor(Objects.requireNonNull(MailMessageReceiver.this.folder)); for (Message message : messages) { MessageHandler handler = new MessageHandler(message); execute(handler); @@ -274,7 +279,7 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver MailReceiverConnection connection = new MailReceiverConnection(this.message, MailMessageReceiver.this.session); connection.setTransportUri(MailMessageReceiver.this.transportUri); - connection.setFrom(MailMessageReceiver.this.from); + connection.setFrom(Objects.requireNonNull(MailMessageReceiver.this.from)); try { handleConnection(connection); } diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailMessageSender.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailMessageSender.java index 4f56c3f8..9a2aaffa 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailMessageSender.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailMessageSender.java @@ -25,6 +25,7 @@ import jakarta.mail.URLName; import jakarta.mail.internet.AddressException; import jakarta.mail.internet.InternetAddress; import jakarta.mail.internet.MimeMessage; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; @@ -83,11 +84,11 @@ public class MailMessageSender implements WebServiceMessageSender, InitializingB private Session session = Session.getInstance(new Properties(), null); - private URLName storeUri; + private @Nullable URLName storeUri; - private URLName transportUri; + private @Nullable URLName transportUri; - private InternetAddress from; + private @Nullable InternetAddress from; /** * Sets the from address to use when sending request messages. @@ -163,7 +164,10 @@ public class MailMessageSender implements WebServiceMessageSender, InitializingB @Override public WebServiceConnection createConnection(URI uri) throws IOException { + Assert.notNull(this.transportUri, "'transportUri' is required"); + Assert.notNull(this.storeUri, "'storeUri' is required"); InternetAddress to = MailTransportUtils.getTo(uri); + Assert.notNull(to, "No TO address found for '" + uri + "'"); MailSenderConnection connection = new MailSenderConnection(this.session, this.transportUri, this.storeUri, to, this.receiveSleepTime); if (this.from != null) { diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailReceiverConnection.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailReceiverConnection.java index aa4187b1..80323fd8 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailReceiverConnection.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailReceiverConnection.java @@ -39,6 +39,7 @@ import jakarta.mail.Session; import jakarta.mail.Transport; import jakarta.mail.URLName; import jakarta.mail.internet.InternetAddress; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -62,15 +63,15 @@ public class MailReceiverConnection extends AbstractReceiverConnection { private final Session session; - private Message responseMessage; + private @Nullable Message responseMessage; - private ByteArrayOutputStream responseBuffer; + private @Nullable ByteArrayOutputStream responseBuffer; - private String responseContentType; + private @Nullable String responseContentType; - private URLName transportUri; + private @Nullable URLName transportUri; - private InternetAddress from; + private @Nullable InternetAddress from; /** Constructs a new Mail connection with the given parameters. */ protected MailReceiverConnection(Message requestMessage, Session session) { @@ -87,6 +88,7 @@ public class MailReceiverConnection extends AbstractReceiverConnection { /** Returns the response message, if any, for this connection. */ public Message getResponseMessage() { + Assert.notNull(this.responseMessage, "ResponseMessage is not available"); return this.responseMessage; } @@ -125,7 +127,7 @@ public class MailReceiverConnection extends AbstractReceiverConnection { */ @Override - public String getErrorMessage() throws IOException { + public @Nullable String getErrorMessage() throws IOException { return null; } @@ -178,7 +180,7 @@ public class MailReceiverConnection extends AbstractReceiverConnection { @Override public void addResponseHeader(String name, String value) throws IOException { try { - this.responseMessage.addHeader(name, value); + getResponseMessage().addHeader(name, value); if (TransportConstants.HEADER_CONTENT_TYPE.equals(name)) { this.responseContentType = value; } @@ -190,6 +192,7 @@ public class MailReceiverConnection extends AbstractReceiverConnection { @Override protected OutputStream getResponseOutputStream() throws IOException { + Assert.state(this.responseBuffer != null, "onSendBeforeWrite has not been called"); return this.responseBuffer; } @@ -213,9 +216,12 @@ public class MailReceiverConnection extends AbstractReceiverConnection { @Override protected void onSendAfterWrite(WebServiceMessage message) throws IOException { Transport transport = null; + Assert.state(this.responseMessage != null, "onSendAfterWrite has not been called"); + Assert.state(this.responseBuffer != null, "onSendAfterWrite has not been called"); + Assert.notNull(this.transportUri, "'transportUri' must not be null"); try { this.responseMessage.setDataHandler(new DataHandler( - new ByteArrayDataSource(this.responseContentType, this.responseBuffer.toByteArray()))); + new ByteArrayDataSource(this.responseBuffer.toByteArray(), this.responseContentType))); transport = this.session.getTransport(this.transportUri); transport.connect(); this.responseMessage.saveChanges(); @@ -235,9 +241,9 @@ public class MailReceiverConnection extends AbstractReceiverConnection { private final byte[] data; - ByteArrayDataSource(String contentType, byte[] data) { + ByteArrayDataSource(byte[] data, @Nullable String contentType) { this.data = data; - this.contentType = contentType; + this.contentType = (contentType != null) ? contentType : "application/octet-stream"; } @Override diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailSenderConnection.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailSenderConnection.java index 036ef0e8..7d8305b5 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailSenderConnection.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/MailSenderConnection.java @@ -47,6 +47,7 @@ import jakarta.mail.search.HeaderTerm; import jakarta.mail.search.SearchTerm; 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.ws.WebServiceMessage; @@ -70,11 +71,11 @@ public class MailSenderConnection extends AbstractSenderConnection { private final Session session; - private MimeMessage requestMessage; + private @Nullable MimeMessage requestMessage; - private Message responseMessage; + private @Nullable Message responseMessage; - private String requestContentType; + private @Nullable String requestContentType; private boolean deleteAfterReceive = false; @@ -82,19 +83,19 @@ public class MailSenderConnection extends AbstractSenderConnection { private final URLName transportUri; - private ByteArrayOutputStream requestBuffer; + private @Nullable ByteArrayOutputStream requestBuffer; - private InternetAddress from; + private @Nullable InternetAddress from; private final InternetAddress to; - private String subject; + private @Nullable String subject; private final long receiveTimeout; - private Store store; + private @Nullable Store store; - private Folder folder; + private @Nullable Folder folder; /** Constructs a new Mail connection with the given parameters. */ protected MailSenderConnection(Session session, URLName transportUri, URLName storeUri, InternetAddress to, @@ -111,12 +112,14 @@ public class MailSenderConnection extends AbstractSenderConnection { } /** Returns the request message for this connection. */ - public Message getRequestMessage() { + public MimeMessage getRequestMessage() { + Assert.notNull(this.requestMessage, "RequestMessage is not available"); return this.requestMessage; } /** Returns the response message, if any, for this connection. */ public Message getResponseMessage() { + Assert.notNull(this.responseMessage, "ResponseMessage is not available"); return this.responseMessage; } @@ -165,7 +168,7 @@ public class MailSenderConnection extends AbstractSenderConnection { @Override public void addRequestHeader(String name, String value) throws IOException { try { - this.requestMessage.addHeader(name, value); + getRequestMessage().addHeader(name, value); if (TransportConstants.HEADER_CONTENT_TYPE.equals(name)) { this.requestContentType = value; } @@ -177,15 +180,18 @@ public class MailSenderConnection extends AbstractSenderConnection { @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.requestMessage != null, "onSendBeforeWrite has not been called"); + Assert.state(this.requestBuffer != null, "onSendBeforeWrite has not been called"); Transport transport = null; try { this.requestMessage.setDataHandler(new DataHandler( - new ByteArrayDataSource(this.requestContentType, this.requestBuffer.toByteArray()))); + new ByteArrayDataSource(this.requestBuffer.toByteArray(), this.requestContentType))); transport = this.session.getTransport(this.transportUri); transport.connect(); this.requestMessage.saveChanges(); @@ -195,7 +201,9 @@ public class MailSenderConnection extends AbstractSenderConnection { throw new MailTransportException(ex); } finally { - MailTransportUtils.closeService(transport); + if (transport != null) { + MailTransportUtils.closeService(transport); + } } } @@ -205,6 +213,7 @@ public class MailSenderConnection extends AbstractSenderConnection { @Override protected void onReceiveBeforeRead() throws IOException { + Assert.state(this.requestMessage != null, "onSendBeforeWrite has not been called"); try { String requestMessageId = this.requestMessage.getMessageID(); Assert.hasLength(requestMessageId, "No Message-ID found on request message [" + this.requestMessage + "]"); @@ -215,7 +224,7 @@ public class MailSenderConnection extends AbstractSenderConnection { // Re-interrupt current thread, to allow other threads to react. Thread.currentThread().interrupt(); } - openFolder(); + this.folder = openFolder(); SearchTerm searchTerm = new HeaderTerm(MailTransportConstants.HEADER_IN_REPLY_TO, requestMessageId); Message[] responses = this.folder.search(searchTerm); if (responses.length > 0) { @@ -224,7 +233,7 @@ public class MailSenderConnection extends AbstractSenderConnection { } this.responseMessage = responses[0]; } - if (this.deleteAfterReceive) { + if (this.deleteAfterReceive && this.responseMessage != null) { this.responseMessage.setFlag(Flags.Flag.DELETED, true); } } @@ -233,19 +242,20 @@ public class MailSenderConnection extends AbstractSenderConnection { } } - private void openFolder() throws MessagingException { + private Folder openFolder() throws MessagingException { this.store = this.session.getStore(this.storeUri); this.store.connect(); - this.folder = this.store.getFolder(this.storeUri); - if (this.folder == null || !this.folder.exists()) { + Folder folder = this.store.getFolder(this.storeUri); + if (folder == null || !folder.exists()) { throw new IllegalStateException("No default folder to receive from"); } if (this.deleteAfterReceive) { - this.folder.open(Folder.READ_WRITE); + folder.open(Folder.READ_WRITE); } else { - this.folder.open(Folder.READ_ONLY); + folder.open(Folder.READ_ONLY); } + return folder; } @Override @@ -257,7 +267,7 @@ public class MailSenderConnection extends AbstractSenderConnection { public Iterator getResponseHeaderNames() throws IOException { try { List headers = new ArrayList<>(); - Enumeration enumeration = this.responseMessage.getAllHeaders(); + Enumeration enumeration = getResponseMessage().getAllHeaders(); while (enumeration.hasMoreElements()) { Header header = (Header) enumeration.nextElement(); headers.add(header.getName()); @@ -272,7 +282,7 @@ public class MailSenderConnection extends AbstractSenderConnection { @Override public Iterator getResponseHeaders(String name) throws IOException { try { - String[] headers = this.responseMessage.getHeader(name); + String[] headers = getResponseMessage().getHeader(name); return Arrays.asList(headers).iterator(); } catch (MessagingException ex) { @@ -284,7 +294,7 @@ public class MailSenderConnection extends AbstractSenderConnection { @Override protected InputStream getResponseInputStream() throws IOException { try { - return this.responseMessage.getDataHandler().getInputStream(); + return getResponseMessage().getDataHandler().getInputStream(); } catch (MessagingException ex) { throw new MailTransportException(ex); @@ -297,14 +307,18 @@ public class MailSenderConnection extends AbstractSenderConnection { } @Override - public String getErrorMessage() throws IOException { + public @Nullable String getErrorMessage() throws IOException { return null; } @Override public void onClose() throws IOException { - MailTransportUtils.closeFolder(this.folder, this.deleteAfterReceive); - MailTransportUtils.closeService(this.store); + if (this.folder != null) { + MailTransportUtils.closeFolder(this.folder, this.deleteAfterReceive); + } + if (this.store != null) { + MailTransportUtils.closeService(this.store); + } } private static final class ByteArrayDataSource implements DataSource { @@ -313,9 +327,9 @@ public class MailSenderConnection extends AbstractSenderConnection { private final byte[] data; - ByteArrayDataSource(String contentType, byte[] data) { + ByteArrayDataSource(byte[] data, @Nullable String contentType) { this.data = data; - this.contentType = contentType; + this.contentType = (contentType != null) ? contentType : "application/octet-stream"; } @Override diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/monitor/ImapIdleMonitoringStrategy.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/monitor/ImapIdleMonitoringStrategy.java index 3ca9502d..2ac02156 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/monitor/ImapIdleMonitoringStrategy.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/monitor/ImapIdleMonitoringStrategy.java @@ -23,6 +23,7 @@ import jakarta.mail.event.MessageCountAdapter; import jakarta.mail.event.MessageCountEvent; import jakarta.mail.event.MessageCountListener; import org.eclipse.angus.mail.imap.IMAPFolder; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; @@ -38,7 +39,7 @@ import org.springframework.util.Assert; */ public class ImapIdleMonitoringStrategy extends AbstractMonitoringStrategy { - private MessageCountListener messageCountListener; + private @Nullable MessageCountListener messageCountListener; @Override protected void waitForNewMessages(Folder folder) throws MessagingException, InterruptedException { diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/monitor/package-info.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/monitor/package-info.java index d3d3f0d2..f9635b1d 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/monitor/package-info.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/monitor/package-info.java @@ -18,4 +18,7 @@ * Provides the MonitoringStrategy interface and implementations. Used for monitoring a * JavaMail Folder for new email messages. */ +@NullMarked package org.springframework.ws.transport.mail.monitor; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/package-info.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/package-info.java index 79b2082c..63b261a1 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/package-info.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/package-info.java @@ -17,4 +17,7 @@ /** * Package providing support for handling messages via email. */ +@NullMarked package org.springframework.ws.transport.mail; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/support/MailTransportUtils.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/support/MailTransportUtils.java index 60cc82e5..40155dd9 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/support/MailTransportUtils.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/support/MailTransportUtils.java @@ -29,6 +29,7 @@ import jakarta.mail.internet.AddressException; import jakarta.mail.internet.InternetAddress; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.util.StringUtils; import org.springframework.ws.transport.mail.MailTransportConstants; @@ -50,7 +51,7 @@ public abstract class MailTransportUtils { private MailTransportUtils() { } - public static InternetAddress getTo(URI uri) { + public static @Nullable InternetAddress getTo(URI uri) { Matcher matcher = TO_PATTERN.matcher(uri.getSchemeSpecificPart()); if (matcher.find()) { for (int i = 1; i <= matcher.groupCount(); i++) { @@ -68,7 +69,7 @@ public abstract class MailTransportUtils { return null; } - public static String getSubject(URI uri) { + public static @Nullable String getSubject(URI uri) { Matcher matcher = SUBJECT_PATTERN.matcher(uri.getSchemeSpecificPart()); if (matcher.find()) { return matcher.group(1); @@ -83,7 +84,7 @@ public abstract class MailTransportUtils { * @see jakarta.mail.Transport * @see jakarta.mail.Store */ - public static void closeService(Service service) { + public static void closeService(@Nullable Service service) { if (service != null) { try { service.close(); @@ -110,7 +111,7 @@ public abstract class MailTransportUtils { * @param folder the JavaMail Folder to close (may be {@code null}) * @param expunge whether all deleted messages should be expunged from the folder */ - public static void closeFolder(Folder folder, boolean expunge) { + public static void closeFolder(@Nullable Folder folder, boolean expunge) { if (folder != null && folder.isOpen()) { try { folder.close(expunge); @@ -172,7 +173,7 @@ public abstract class MailTransportUtils { * @param subject the subject, may be {@code null} * @return a mailto URI */ - public static URI toUri(InternetAddress to, String subject) throws URISyntaxException { + public static URI toUri(InternetAddress to, @Nullable String subject) throws URISyntaxException { if (StringUtils.hasLength(subject)) { return new URI(MailTransportConstants.MAIL_URI_SCHEME, to.getAddress() + "?subject=" + subject, null); } diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/support/package-info.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/support/package-info.java index 2a9024ff..e495bea1 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/support/package-info.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/mail/support/package-info.java @@ -17,4 +17,7 @@ /** * Classes supporting the org.springframework.ws.transport.mail package. */ +@NullMarked package org.springframework.ws.transport.mail.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageReceiver.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageReceiver.java index 1c43da60..3823f47f 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageReceiver.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageReceiver.java @@ -26,7 +26,9 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jspecify.annotations.Nullable; +import org.springframework.util.Assert; import org.springframework.ws.transport.support.AbstractStandaloneMessageReceiver; /** @@ -51,9 +53,9 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver { */ public static final String DEFAULT_MESSAGE_ENCODING = "UTF-8"; - private XMPPTCPConnection connection; + private @Nullable XMPPTCPConnection connection; - private WebServicePacketListener packetListener; + private @Nullable WebServicePacketListener packetListener; private final String messageEncoding = DEFAULT_MESSAGE_ENCODING; @@ -65,11 +67,16 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver { this.connection = connection; } + private XMPPTCPConnection getConnection() { + Assert.state(this.connection != null, "Connection is required"); + return this.connection; + } + @Override protected void onActivate() throws XMPPException, IOException, SmackException { - if (!this.connection.isConnected()) { + if (!getConnection().isConnected()) { try { - this.connection.connect(); + getConnection().connect(); } catch (InterruptedException ex) { throw new IOException(ex); @@ -80,29 +87,29 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver { @Override protected void onStart() { if (this.logger.isInfoEnabled()) { - this.logger.info("Starting XMPP receiver [" + this.connection.getUser() + "]"); + this.logger.info("Starting XMPP receiver [" + getConnection().getUser() + "]"); } this.packetListener = new WebServicePacketListener(); StanzaFilter packetFilter = new StanzaTypeFilter(Message.class); - this.connection.addAsyncStanzaListener(this.packetListener, packetFilter); + getConnection().addAsyncStanzaListener(this.packetListener, packetFilter); } @Override protected void onStop() { if (this.logger.isInfoEnabled()) { - this.logger.info("Stopping XMPP receiver [" + this.connection.getUser() + "]"); + this.logger.info("Stopping XMPP receiver [" + getConnection().getUser() + "]"); } - this.connection.removeAsyncStanzaListener(this.packetListener); + getConnection().removeAsyncStanzaListener(this.packetListener); this.packetListener = null; } @Override protected void onShutdown() { if (this.logger.isInfoEnabled()) { - this.logger.info("Shutting down XMPP receiver [" + this.connection.getUser() + "]"); + this.logger.info("Shutting down XMPP receiver [" + getConnection().getUser() + "]"); } - if (this.connection.isConnected()) { - this.connection.disconnect(); + if (getConnection().isConnected()) { + getConnection().disconnect(); } } @@ -113,8 +120,7 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver { XmppMessageReceiver.this.logger.info("Received " + packet); if (packet instanceof Message message) { try { - XmppReceiverConnection wsConnection = new XmppReceiverConnection( - XmppMessageReceiver.this.connection, message); + XmppReceiverConnection wsConnection = new XmppReceiverConnection(getConnection(), message); wsConnection.setMessageEncoding(XmppMessageReceiver.this.messageEncoding); handleConnection(wsConnection); } diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageSender.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageSender.java index 50e5a64b..920f8dd0 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageSender.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageSender.java @@ -18,9 +18,11 @@ package org.springframework.ws.transport.xmpp; import java.io.IOException; import java.net.URI; +import java.util.Objects; import java.util.UUID; import org.jivesoftware.smack.XMPPConnection; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; @@ -58,7 +60,7 @@ public class XmppMessageSender implements WebServiceMessageSender, InitializingB private String messageEncoding = DEFAULT_MESSAGE_ENCODING; - private XMPPConnection connection; + private @Nullable XMPPConnection connection; /** * Sets the {@code XMPPConnection}. Setting this property is required. @@ -93,7 +95,7 @@ public class XmppMessageSender implements WebServiceMessageSender, InitializingB public WebServiceConnection createConnection(URI uri) throws IOException { String to = XmppTransportUtils.getTo(uri); String thread = createThread(); - XmppSenderConnection connection = new XmppSenderConnection(this.connection, to, thread); + XmppSenderConnection connection = new XmppSenderConnection(Objects.requireNonNull(this.connection), to, thread); connection.setReceiveTimeout(this.receiveTimeout); connection.setMessageEncoding(this.messageEncoding); return connection; diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppReceiverConnection.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppReceiverConnection.java index 6139ebf2..46c73a4d 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppReceiverConnection.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppReceiverConnection.java @@ -22,10 +22,12 @@ import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.Iterator; +import java.util.Objects; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Message; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; @@ -48,9 +50,9 @@ public class XmppReceiverConnection extends AbstractReceiverConnection { private final Message requestMessage; - private Message responseMessage; + private @Nullable Message responseMessage; - private String messageEncoding; + private String messageEncoding = XmppMessageReceiver.DEFAULT_MESSAGE_ENCODING; public XmppReceiverConnection(XMPPConnection connection, Message requestMessage) { Assert.notNull(connection, "'connection' must not be null"); @@ -65,7 +67,7 @@ public class XmppReceiverConnection extends AbstractReceiverConnection { } /** Returns the response message, if any, for this connection. */ - public Message getResponseMessage() { + public @Nullable Message getResponseMessage() { return this.responseMessage; } @@ -96,7 +98,7 @@ public class XmppReceiverConnection extends AbstractReceiverConnection { } @Override - public String getErrorMessage() { + public @Nullable String getErrorMessage() { return XmppTransportUtils.getErrorMessage(this.responseMessage); } @@ -132,12 +134,12 @@ public class XmppReceiverConnection extends AbstractReceiverConnection { @Override public void addResponseHeader(String name, String value) throws IOException { - XmppTransportUtils.addHeader(this.responseMessage, name, value); + XmppTransportUtils.addHeader(Objects.requireNonNull(this.responseMessage), name, value); } @Override protected OutputStream getResponseOutputStream() throws IOException { - return new MessageOutputStream(this.responseMessage, this.messageEncoding); + return new MessageOutputStream(Objects.requireNonNull(this.responseMessage), this.messageEncoding); } @Override diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppSenderConnection.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppSenderConnection.java index f7bd8f24..0c56ced6 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppSenderConnection.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppSenderConnection.java @@ -22,6 +22,7 @@ import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.Iterator; +import java.util.Objects; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.StanzaCollector; @@ -32,6 +33,7 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.filter.ThreadFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; +import org.jspecify.annotations.Nullable; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.stringprep.XmppStringprepException; @@ -56,9 +58,9 @@ public class XmppSenderConnection extends AbstractSenderConnection { private final XMPPConnection connection; - private Message responseMessage; + private @Nullable Message responseMessage; - private String messageEncoding; + private String messageEncoding = XmppMessageReceiver.DEFAULT_MESSAGE_ENCODING; private long receiveTimeout; @@ -82,7 +84,7 @@ public class XmppSenderConnection extends AbstractSenderConnection { } /** Returns the response message, if any, for this connection. */ - public Message getResponseMessage() { + public @Nullable Message getResponseMessage() { return this.responseMessage; } @@ -117,7 +119,7 @@ public class XmppSenderConnection extends AbstractSenderConnection { } @Override - public String getErrorMessage() { + public @Nullable String getErrorMessage() { return XmppTransportUtils.getErrorMessage(this.responseMessage); } @@ -185,17 +187,17 @@ public class XmppSenderConnection extends AbstractSenderConnection { @Override public Iterator getResponseHeaderNames() { - return XmppTransportUtils.getHeaderNames(this.responseMessage); + return XmppTransportUtils.getHeaderNames(Objects.requireNonNull(this.responseMessage)); } @Override public Iterator getResponseHeaders(String name) throws IOException { - return XmppTransportUtils.getHeaders(this.responseMessage, name); + return XmppTransportUtils.getHeaders(Objects.requireNonNull(this.responseMessage), name); } @Override protected InputStream getResponseInputStream() throws IOException { - return new MessageInputStream(this.responseMessage, this.messageEncoding); + return new MessageInputStream(Objects.requireNonNull(this.responseMessage), this.messageEncoding); } } diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/package-info.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/package-info.java index fafabfb6..95fa5b50 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/package-info.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/package-info.java @@ -17,4 +17,7 @@ /** * Package providing support for handling messages via XMPP. */ +@NullMarked package org.springframework.ws.transport.xmpp; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppConnectionFactoryBean.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppConnectionFactoryBean.java index bd774a20..d1d53ef5 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppConnectionFactoryBean.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppConnectionFactoryBean.java @@ -17,11 +17,13 @@ package org.springframework.ws.transport.xmpp.support; import java.io.IOException; +import java.util.Objects; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.jspecify.annotations.Nullable; import org.jxmpp.jid.parts.Resourcepart; import org.jxmpp.stringprep.XmppStringprepException; @@ -43,19 +45,19 @@ public class XmppConnectionFactoryBean implements FactoryBean private static final int DEFAULT_PORT = 5222; - private XMPPTCPConnection connection; + private @Nullable XMPPTCPConnection connection; - private String host; + private @Nullable String host; private int port = DEFAULT_PORT; - private String serviceName; + private @Nullable String serviceName; - private String username; + private @Nullable String username; - private String password; + private @Nullable String password; - private String resource; + private @Nullable String resource; /** Sets the server host to connect to. */ public void setHost(String host) { @@ -91,6 +93,7 @@ public class XmppConnectionFactoryBean implements FactoryBean @Override public void afterPropertiesSet() throws XMPPException, IOException, SmackException { + Assert.hasText(this.host, "'host' must not be empty"); XMPPTCPConnectionConfiguration configuration = createConnectionConfiguration(this.host, this.port, this.serviceName); Assert.notNull(configuration, "'configuration' must not be null"); @@ -114,12 +117,12 @@ public class XmppConnectionFactoryBean implements FactoryBean @Override public void destroy() { - this.connection.disconnect(); + Objects.requireNonNull(this.connection).disconnect(); } @Override public XMPPTCPConnection getObject() { - return this.connection; + return Objects.requireNonNull(this.connection); } @Override @@ -138,8 +141,8 @@ public class XmppConnectionFactoryBean implements FactoryBean * @param port the port to connect to * @param serviceName the name of the service to connect to. May be {@code null} */ - protected XMPPTCPConnectionConfiguration createConnectionConfiguration(String host, int port, String serviceName) - throws XmppStringprepException { + protected XMPPTCPConnectionConfiguration createConnectionConfiguration(String host, int port, + @Nullable String serviceName) throws XmppStringprepException { Assert.hasText(host, "'host' must not be empty"); if (StringUtils.hasText(serviceName)) { return XMPPTCPConnectionConfiguration.builder() diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppTransportUtils.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppTransportUtils.java index 6e730804..e555e40a 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppTransportUtils.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppTransportUtils.java @@ -23,6 +23,7 @@ import java.util.Iterator; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smackx.jiveproperties.JivePropertiesManager; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.ws.transport.xmpp.XmppTransportConstants; @@ -49,11 +50,11 @@ public abstract class XmppTransportUtils { return uri.getSchemeSpecificPart(); } - public static boolean hasError(Message message) { + public static boolean hasError(@Nullable Message message) { return message != null && Message.Type.error.equals(message.getType()); } - public static String getErrorMessage(Message message) { + public static @Nullable String getErrorMessage(@Nullable Message message) { if (message == null || !Message.Type.error.equals(message.getType())) { return null; } diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/package-info.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/package-info.java index 4bfed310..47e1b38a 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/package-info.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/package-info.java @@ -17,4 +17,7 @@ /** * Support classes for handling messages via XMPP. */ +@NullMarked package org.springframework.ws.transport.xmpp.support; + +import org.jspecify.annotations.NullMarked;