Introduce null-safety of Spring Framework API

This commit introduces 2 new @Nullable and @NonNullApi
annotations that leverage JSR 305 (dormant but available via
Findbugs jsr305 dependency and already used by libraries
like OkHttp) meta-annotations to specify explicitly
null-safety of Spring Framework parameters and return values.

In order to avoid adding too much annotations, the
default is set at package level with @NonNullApi and
@Nullable annotations are added when needed at parameter or
return value level. These annotations are intended to be used
on Spring Framework itself but also by other Spring projects.

@Nullable annotations have been introduced based on Javadoc
and search of patterns like "return null;". It is expected that
nullability of Spring Framework API will be polished with
complementary commits.

In practice, this will make the whole Spring Framework API
null-safe for Kotlin projects (when KT-10942 will be fixed)
since Kotlin will be able to leverage these annotations to
know if a parameter or a return value is nullable or not. But
this is also useful for Java developers as well since IntelliJ
IDEA, for example, also understands these annotations to
generate warnings when unsafe nullable usages are detected.

Issue: SPR-15540
This commit is contained in:
Sebastien Deleuze
2017-05-27 08:14:59 +02:00
parent 2d37c966b2
commit 87598f48e4
1315 changed files with 4831 additions and 963 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.web.socket;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -177,6 +178,7 @@ public final class CloseStatus {
/**
* Return the reason, or {@code null} if none.
*/
@Nullable
public String getReason() {
return this.reason;
}

View File

@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
/**
* A WebSocket session abstraction. Allows sending messages over a WebSocket
@@ -71,6 +72,7 @@ public interface WebSocketSession extends Closeable {
/**
* Return the address on which the request was received.
*/
@Nullable
InetSocketAddress getLocalAddress();
/**
@@ -83,6 +85,7 @@ public interface WebSocketSession extends Closeable {
* @return the protocol identifier, or {@code null} if no protocol
* was specified or negotiated successfully
*/
@Nullable
String getAcceptedProtocol();
/**

View File

@@ -16,6 +16,7 @@
package org.springframework.web.socket.adapter;
import org.springframework.lang.Nullable;
import org.springframework.web.socket.WebSocketSession;
/**
@@ -31,6 +32,7 @@ public interface NativeWebSocketSession extends WebSocketSession {
* Return the underlying native WebSocketSession, if available.
* @return the native session or {@code null}
*/
@Nullable
Object getNativeSession();
/**
@@ -38,6 +40,7 @@ public interface NativeWebSocketSession extends WebSocketSession {
* @param requiredType the required type of the session
* @return the native session of the required type or {@code null}
*/
@Nullable
<T> T getNativeSession(Class<T> requiredType);
}

View File

@@ -31,6 +31,7 @@ import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.socket.BinaryMessage;
@@ -81,7 +82,7 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
* @param user the user associated with the session; if {@code null} we'll fallback on the
* user available via {@link org.eclipse.jetty.websocket.api.Session#getUpgradeRequest()}
*/
public JettyWebSocketSession(Map<String, Object> attributes, Principal user) {
public JettyWebSocketSession(Map<String, Object> attributes, @Nullable Principal user) {
super(attributes);
this.user = user;
}

View File

@@ -1,4 +1,7 @@
/**
* Adapter classes for the Jetty WebSocket API.
*/
@NonNullApi
package org.springframework.web.socket.adapter.jetty;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Classes adapting Spring's WebSocket API to and from WebSocket providers.
*/
@NonNullApi
package org.springframework.web.socket.adapter;
import org.springframework.lang.NonNullApi;

View File

@@ -17,6 +17,7 @@
package org.springframework.web.socket.adapter.standard;
import java.nio.ByteBuffer;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EncodeException;
@@ -32,6 +33,7 @@ import org.springframework.core.GenericTypeResolver;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.context.ContextLoader;
@@ -122,6 +124,7 @@ public abstract class ConvertingEncoderDecoderSupport<T, M> {
* not using {@link ContextLoader}, this method should be overridden.
* @return the {@link ApplicationContext} or {@code null}
*/
@Nullable
protected ApplicationContext getApplicationContext() {
return ContextLoader.getCurrentWebApplicationContext();
}

View File

@@ -24,12 +24,14 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.websocket.CloseReason;
import javax.websocket.CloseReason.CloseCodes;
import javax.websocket.Extension;
import javax.websocket.Session;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
@@ -89,7 +91,7 @@ public class StandardWebSocketSession extends AbstractWebSocketSession<Session>
* fallback on the user available in the underlying WebSocket session
*/
public StandardWebSocketSession(HttpHeaders headers, Map<String, Object> attributes,
InetSocketAddress localAddress, InetSocketAddress remoteAddress, Principal user) {
InetSocketAddress localAddress, InetSocketAddress remoteAddress, @Nullable Principal user) {
super(attributes);
headers = (headers != null) ? headers : new HttpHeaders();

View File

@@ -1,4 +1,7 @@
/**
* Adapter classes for the standard Java WebSocket API.
*/
@NonNullApi
package org.springframework.web.socket.adapter.standard;
import org.springframework.lang.NonNullApi;

View File

@@ -32,6 +32,7 @@ import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
import org.springframework.web.socket.WebSocketExtension;
@@ -89,7 +90,7 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Lif
*
* <p>By default an instance of {@code SimpleAsyncTaskExecutor} is used.
*/
public void setTaskExecutor(AsyncListenableTaskExecutor taskExecutor) {
public void setTaskExecutor(@Nullable AsyncListenableTaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
@@ -192,6 +193,7 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Lif
* @return the user to make available through {@link WebSocketSession#getPrincipal()};
* by default this method returns {@code null}
*/
@Nullable
protected Principal getUser() {
return null;
}

View File

@@ -1,4 +1,7 @@
/**
* Client-side support for the Jetty WebSocket API.
*/
@NonNullApi
package org.springframework.web.socket.client.jetty;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Client-side abstractions for WebSocket applications.
*/
@NonNullApi
package org.springframework.web.socket.client;
import org.springframework.lang.NonNullApi;

View File

@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Callable;
import javax.websocket.ClientEndpointConfig;
import javax.websocket.ClientEndpointConfig.Configurator;
import javax.websocket.ContainerProvider;
@@ -38,6 +39,7 @@ import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
@@ -100,6 +102,7 @@ public class StandardWebSocketClient extends AbstractWebSocketClient {
/**
* The configured user properties, or {@code null}.
*/
@Nullable
public Map<String, Object> getUserProperties() {
return this.userProperties;
}
@@ -110,7 +113,7 @@ public class StandardWebSocketClient extends AbstractWebSocketClient {
* {@code doHandshake} methods will block until the connection is established.
* <p>By default, an instance of {@code SimpleAsyncTaskExecutor} is used.
*/
public void setTaskExecutor(AsyncListenableTaskExecutor taskExecutor) {
public void setTaskExecutor(@Nullable AsyncListenableTaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}

View File

@@ -1,4 +1,7 @@
/**
* Client-side classes for use with standard Java WebSocket endpoints.
*/
@NonNullApi
package org.springframework.web.socket.client.standard;
import org.springframework.lang.NonNullApi;

View File

@@ -38,6 +38,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
import org.springframework.lang.Nullable;
import org.springframework.messaging.converter.ByteArrayMessageConverter;
import org.springframework.messaging.converter.CompositeMessageConverter;
import org.springframework.messaging.converter.DefaultContentTypeResolver;
@@ -260,6 +261,7 @@ class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
return new RuntimeBeanReference(name);
}
@Nullable
private RootBeanDefinition getDefaultExecutorBeanDefinition(String channelName) {
if (channelName.equals("brokerChannel")) {
return null;
@@ -545,6 +547,7 @@ class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
registerBeanDef(beanDef, context, source);
}
@Nullable
private RuntimeBeanReference getValidator(Element messageBrokerElement, Object source, ParserContext parserContext) {
if (messageBrokerElement.hasAttribute("validator")) {
return new RuntimeBeanReference(messageBrokerElement.getAttribute("validator"));

View File

@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@@ -75,6 +76,7 @@ public class WebSocketMessageBrokerStats {
this.stompSubProtocolHandler = initStompSubProtocolHandler();
}
@Nullable
private StompSubProtocolHandler initStompSubProtocolHandler() {
for (SubProtocolHandler handler : this.webSocketHandler.getProtocolHandlers()) {
if (handler instanceof StompSubProtocolHandler) {
@@ -105,6 +107,7 @@ public class WebSocketMessageBrokerStats {
this.loggingTask = initLoggingTask(1 * 60 * 1000);
}
@Nullable
private ScheduledFuture<?> initLoggingTask(long initialDelay) {
if (logger.isInfoEnabled() && this.loggingPeriod > 0) {
return this.sockJsTaskScheduler.scheduleAtFixedRate(new Runnable() {

View File

@@ -27,6 +27,7 @@ import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
@@ -61,6 +62,7 @@ class WebSocketNamespaceUtils {
return handlerRef;
}
@Nullable
public static RuntimeBeanReference registerSockJsService(Element element, String schedulerName,
ParserContext context, Object source) {

View File

@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
@@ -140,6 +141,7 @@ public abstract class AbstractWebSocketHandlerRegistration<M> implements WebSock
* if the application did not provide one. This should be done prior to
* calling {@link #getMappings()}.
*/
@Nullable
protected SockJsServiceRegistration getSockJsServiceRegistration() {
return this.sockJsServiceRegistration;
}

View File

@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
@@ -146,6 +147,7 @@ public class WebMvcStompEndpointRegistry implements StompEndpointRegistry {
* Return a handler mapping with the mapped ViewControllers; or {@code null}
* in case of no registrations.
*/
@Nullable
public AbstractHandlerMapping getHandlerMapping() {
Map<String, Object> urlMap = new LinkedHashMap<>();
for (WebMvcStompWebSocketEndpointRegistration registration : this.registrations) {

View File

@@ -1,4 +1,7 @@
/**
* Support for annotation-based WebSocket setup in configuration classes.
*/
@NonNullApi
package org.springframework.web.socket.config.annotation;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Configuration support for WebSocket request handling.
*/
@NonNullApi
package org.springframework.web.socket.config;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Convenient {@link org.springframework.web.socket.WebSocketHandler}
* implementations and decorators.
*/
@NonNullApi
package org.springframework.web.socket.handler;
import org.springframework.lang.NonNullApi;

View File

@@ -32,6 +32,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.SimpAttributes;
@@ -531,6 +532,7 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE
return connectedHeaders;
}
@Nullable
private String getDisconnectReceipt(SimpMessageHeaderAccessor simpHeaders) {
String name = StompHeaderAccessor.DISCONNECT_MESSAGE_HEADER;
Message<?> message = (Message<?>) simpHeaders.getHeader(name);

View File

@@ -16,6 +16,7 @@
package org.springframework.web.socket.messaging;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
/**
@@ -39,7 +40,8 @@ public interface SubProtocolErrorHandler<P> {
* @return the error message to send to the client, or {@code null} in which
* case no message will be sent.
*/
Message<P> handleClientMessageProcessingError(Message<P> clientMessage, Throwable ex);
@Nullable
Message<P> handleClientMessageProcessingError(@Nullable Message<P> clientMessage, Throwable ex);
/**
* Handle errors sent from the server side to clients, e.g. errors from the
@@ -50,6 +52,7 @@ public interface SubProtocolErrorHandler<P> {
* @return the error message to send to the client, or {@code null} in which
* case no message will be sent.
*/
@Nullable
Message<P> handleErrorMessageToClient(Message<P> errorMessage);
}

View File

@@ -18,6 +18,7 @@ package org.springframework.web.socket.messaging;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.web.socket.CloseStatus;
@@ -67,6 +68,7 @@ public interface SubProtocolHandler {
* Resolve the session id from the given message or return {@code null}.
* @param message the message to resolve the session id from
*/
@Nullable
String resolveSessionId(Message<?> message);
/**

View File

@@ -1,4 +1,7 @@
/**
* WebSocket integration for Spring's messaging module.
*/
@NonNullApi
package org.springframework.web.socket.messaging;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Common abstractions and Spring configuration support for WebSocket applications.
*/
@NonNullApi
package org.springframework.web.socket;
import org.springframework.lang.NonNullApi;

View File

@@ -22,6 +22,7 @@ import java.util.Map;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.socket.WebSocketExtension;
import org.springframework.web.socket.WebSocketHandler;
@@ -61,7 +62,7 @@ public interface RequestUpgradeStrategy {
* handshake request.
*/
void upgrade(ServerHttpRequest request, ServerHttpResponse response,
String selectedProtocol, List<WebSocketExtension> selectedExtensions, Principal user,
@Nullable String selectedProtocol, List<WebSocketExtension> selectedExtensions, Principal user,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws HandshakeFailureException;
}

View File

@@ -1,4 +1,7 @@
/**
* Server-side abstractions for WebSocket interactions.
*/
@NonNullApi
package org.springframework.web.socket.server;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Server-side classes for use with standard JSR-356 WebSocket endpoints.
*/
@NonNullApi
package org.springframework.web.socket.server.standard;
import org.springframework.lang.NonNullApi;

View File

@@ -33,6 +33,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -340,6 +341,7 @@ public abstract class AbstractHandshakeHandler implements HandshakeHandler, Life
* @return the selected protocols or {@code null}
* @see #determineHandlerSupportedProtocols(WebSocketHandler)
*/
@Nullable
protected String selectProtocol(List<String> requestedProtocols, WebSocketHandler webSocketHandler) {
if (requestedProtocols != null) {
List<String> handlerProtocols = determineHandlerSupportedProtocols(webSocketHandler);
@@ -402,6 +404,7 @@ public abstract class AbstractHandshakeHandler implements HandshakeHandler, Life
* @param attributes handshake attributes to pass to the WebSocket session
* @return the user for the WebSocket session, or {@code null} if not available
*/
@Nullable
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
Map<String, Object> attributes) {

View File

@@ -25,6 +25,7 @@ import javax.servlet.http.HttpSession;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.server.HandshakeInterceptor;
@@ -160,6 +161,7 @@ public class HttpSessionHandshakeInterceptor implements HandshakeInterceptor {
return true;
}
@Nullable
private HttpSession getSession(ServerHttpRequest request) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;

View File

@@ -2,4 +2,7 @@
* Server-side support classes including container-specific strategies
* for upgrading a request.
*/
@NonNullApi
package org.springframework.web.socket.server.support;
import org.springframework.lang.NonNullApi;

View File

@@ -30,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.context.Lifecycle;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -323,6 +324,7 @@ public class SockJsClient implements WebSocketClient, Lifecycle {
* <p>By default this method returns {@code null}.
* @return the user to associate with the session (possibly {@code null})
*/
@Nullable
protected Principal getUser() {
return null;
}

View File

@@ -20,6 +20,7 @@ import java.net.URI;
import java.security.Principal;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.web.socket.sockjs.frame.SockJsMessageCodec;
/**
@@ -62,6 +63,7 @@ public interface TransportRequest {
/**
* Return the user associated with the request, if any.
*/
@Nullable
Principal getUser();
/**

View File

@@ -2,4 +2,7 @@
* SockJS client implementation of
* {@link org.springframework.web.socket.client.WebSocketClient}.
*/
@NonNullApi
package org.springframework.web.socket.sockjs.client;
import org.springframework.lang.NonNullApi;

View File

@@ -19,6 +19,7 @@ package org.springframework.web.socket.sockjs.frame;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -104,6 +105,7 @@ public class SockJsFrame {
* for SockJS "open" and "close" frames, which do not contain data, return
* {@code null}.
*/
@Nullable
public String getFrameData() {
if (getType() == SockJsFrameType.OPEN || getType() == SockJsFrameType.HEARTBEAT) {
return null;

View File

@@ -19,6 +19,8 @@ package org.springframework.web.socket.sockjs.frame;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.lang.Nullable;
/**
* Encode and decode messages to and from a SockJS message frame,
* essentially an array of JSON-encoded messages. For example:
@@ -48,6 +50,7 @@ public interface SockJsMessageCodec {
* @return an array of messages, or {@code null} if none
* @throws IOException if the content could not be parsed
*/
@Nullable
String[] decode(String content) throws IOException;
/**
@@ -56,6 +59,7 @@ public interface SockJsMessageCodec {
* @return an array of messages, or {@code null} if none
* @throws IOException if the content could not be parsed
*/
@Nullable
String[] decodeInputStream(InputStream content) throws IOException;
}

View File

@@ -2,4 +2,7 @@
* Support classes for creating SockJS frames including the encoding and decoding
* of SockJS message frames.
*/
@NonNullApi
package org.springframework.web.socket.sockjs.frame;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Top-level SockJS types.
*/
@NonNullApi
package org.springframework.web.socket.sockjs;
import org.springframework.lang.NonNullApi;

View File

@@ -3,4 +3,7 @@
* {@link org.springframework.web.socket.sockjs.support.AbstractSockJsService}
* implementation.
*/
@NonNullApi
package org.springframework.web.socket.sockjs.support;
import org.springframework.lang.NonNullApi;

View File

@@ -23,6 +23,7 @@ import java.util.regex.Pattern;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketHandler;
@@ -112,6 +113,7 @@ public abstract class AbstractHttpSendingTransportHandler extends AbstractTransp
protected abstract SockJsFrameFormat getFrameFormat(ServerHttpRequest request);
@Nullable
protected final String getCallbackParam(ServerHttpRequest request) {
String query = request.getURI().getQuery();
MultiValueMap<String, String> params = UriComponentsBuilder.newInstance().query(query).build().getQueryParams();

View File

@@ -3,4 +3,7 @@
* implementation classes as well as a concrete
* {@link org.springframework.web.socket.sockjs.SockJsService}.
*/
@NonNullApi
package org.springframework.web.socket.sockjs.transport.handler;
import org.springframework.lang.NonNullApi;

View File

@@ -6,4 +6,7 @@
* counterparts for sending messages over the various transports, and
* {@link org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService}.
*/
@NonNullApi
package org.springframework.web.socket.sockjs.transport;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* SockJS specific implementations of
* {@link org.springframework.web.socket.WebSocketSession}.
*/
@NonNullApi
package org.springframework.web.socket.sockjs.transport.session;
import org.springframework.lang.NonNullApi;