@Nullable all the way: null-safety at field level
This commits extends nullability declarations to the field level, formalizing the interaction between methods and their underlying fields and therefore avoiding any nullability mismatch. Issue: SPR-15720
This commit is contained in:
@@ -145,6 +145,7 @@ public final class CloseStatus {
|
||||
|
||||
private final int code;
|
||||
|
||||
@Nullable
|
||||
private final String reason;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,8 @@ package org.springframework.web.socket;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A text WebSocket message.
|
||||
*
|
||||
@@ -26,6 +28,7 @@ import java.nio.charset.StandardCharsets;
|
||||
*/
|
||||
public final class TextMessage extends AbstractWebSocketMessage<String> {
|
||||
|
||||
@Nullable
|
||||
private final byte[] bytes;
|
||||
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ public interface WebSocketSession extends Closeable {
|
||||
/**
|
||||
* Return the address of the remote client.
|
||||
*/
|
||||
@Nullable
|
||||
InetSocketAddress getRemoteAddress();
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,6 +45,7 @@ public abstract class AbstractWebSocketSession<T> implements NativeWebSocketSess
|
||||
|
||||
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private T nativeSession;
|
||||
|
||||
|
||||
@@ -67,6 +68,7 @@ public abstract class AbstractWebSocketSession<T> implements NativeWebSocketSess
|
||||
|
||||
@Override
|
||||
public T getNativeSession() {
|
||||
Assert.state(this.nativeSession != null, "WebSocket session not yet initialized");
|
||||
return this.nativeSession;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.socket.BinaryMessage;
|
||||
@@ -54,16 +55,22 @@ import org.springframework.web.socket.adapter.AbstractWebSocketSession;
|
||||
*/
|
||||
public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||
|
||||
@Nullable
|
||||
private String id;
|
||||
|
||||
@Nullable
|
||||
private URI uri;
|
||||
|
||||
@Nullable
|
||||
private HttpHeaders headers;
|
||||
|
||||
@Nullable
|
||||
private String acceptedProtocol;
|
||||
|
||||
@Nullable
|
||||
private List<WebSocketExtension> extensions;
|
||||
|
||||
@Nullable
|
||||
private Principal user;
|
||||
|
||||
|
||||
@@ -90,19 +97,19 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
checkNativeSessionInitialized();
|
||||
Assert.state(this.id != null, "WebSocket session is not yet initialized");
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
checkNativeSessionInitialized();
|
||||
Assert.state(this.uri != null, "WebSocket session is not yet initialized");
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHandshakeHeaders() {
|
||||
checkNativeSessionInitialized();
|
||||
Assert.state(this.headers != null, "WebSocket session is not yet initialized");
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
@@ -114,7 +121,7 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||
|
||||
@Override
|
||||
public List<WebSocketExtension> getExtensions() {
|
||||
checkNativeSessionInitialized();
|
||||
Assert.state(this.extensions != null, "WebSocket session is not yet initialized");
|
||||
return this.extensions;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ 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;
|
||||
@@ -32,6 +31,7 @@ import javax.websocket.Session;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.socket.BinaryMessage;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
@@ -50,20 +50,27 @@ import org.springframework.web.socket.adapter.AbstractWebSocketSession;
|
||||
*/
|
||||
public class StandardWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||
|
||||
@Nullable
|
||||
private String id;
|
||||
|
||||
@Nullable
|
||||
private URI uri;
|
||||
|
||||
private final HttpHeaders handshakeHeaders;
|
||||
|
||||
@Nullable
|
||||
private String acceptedProtocol;
|
||||
|
||||
@Nullable
|
||||
private List<WebSocketExtension> extensions;
|
||||
|
||||
@Nullable
|
||||
private Principal user;
|
||||
|
||||
@Nullable
|
||||
private final InetSocketAddress localAddress;
|
||||
|
||||
@Nullable
|
||||
private final InetSocketAddress remoteAddress;
|
||||
|
||||
|
||||
@@ -88,7 +95,7 @@ public class StandardWebSocketSession extends AbstractWebSocketSession<Session>
|
||||
* @param localAddress the address on which the request was received
|
||||
* @param remoteAddress the address of the remote client
|
||||
* @param user the user associated with the session; if {@code null} we'll
|
||||
* fallback on the user available in the underlying WebSocket session
|
||||
* fallback on the user available in the underlying WebSocket session
|
||||
*/
|
||||
public StandardWebSocketSession(@Nullable HttpHeaders headers, @Nullable Map<String, Object> attributes,
|
||||
@Nullable InetSocketAddress localAddress, @Nullable InetSocketAddress remoteAddress,
|
||||
@@ -105,13 +112,13 @@ public class StandardWebSocketSession extends AbstractWebSocketSession<Session>
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
checkNativeSessionInitialized();
|
||||
Assert.state(this.id != null, "WebSocket session is not yet initialized");
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
checkNativeSessionInitialized();
|
||||
Assert.state(this.uri != null, "WebSocket session is not yet initialized");
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
@@ -128,7 +135,7 @@ public class StandardWebSocketSession extends AbstractWebSocketSession<Session>
|
||||
|
||||
@Override
|
||||
public List<WebSocketExtension> getExtensions() {
|
||||
checkNativeSessionInitialized();
|
||||
Assert.state(this.extensions != null, "WebSocket session is not yet initialized");
|
||||
return this.extensions;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport {
|
||||
|
||||
private final WebSocketHandler webSocketHandler;
|
||||
|
||||
@Nullable
|
||||
private WebSocketSession webSocketSession;
|
||||
|
||||
private WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
|
||||
@@ -140,7 +141,7 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport {
|
||||
|
||||
future.addCallback(new ListenableFutureCallback<WebSocketSession>() {
|
||||
@Override
|
||||
public void onSuccess(WebSocketSession result) {
|
||||
public void onSuccess(@Nullable WebSocketSession result) {
|
||||
webSocketSession = result;
|
||||
logger.info("Successfully connected");
|
||||
}
|
||||
@@ -153,7 +154,9 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport {
|
||||
|
||||
@Override
|
||||
protected void closeConnection() throws Exception {
|
||||
this.webSocketSession.close();
|
||||
if (this.webSocketSession != null) {
|
||||
this.webSocketSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -63,6 +63,7 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Lif
|
||||
|
||||
private final Object lifecycleMonitor = new Object();
|
||||
|
||||
@Nullable
|
||||
private AsyncListenableTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
|
||||
|
||||
|
||||
@@ -85,9 +86,8 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Lif
|
||||
|
||||
/**
|
||||
* Set an {@link AsyncListenableTaskExecutor} to use when opening connections.
|
||||
* If this property is set to {@code null}, calls to any of the
|
||||
* If this property is set to {@code null}, calls to any of the
|
||||
* {@code doHandshake} methods will block until the connection is established.
|
||||
*
|
||||
* <p>By default an instance of {@code SimpleAsyncTaskExecutor} is used.
|
||||
*/
|
||||
public void setTaskExecutor(@Nullable AsyncListenableTaskExecutor taskExecutor) {
|
||||
@@ -97,6 +97,7 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Lif
|
||||
/**
|
||||
* Return the configured {@link TaskExecutor}.
|
||||
*/
|
||||
@Nullable
|
||||
public AsyncListenableTaskExecutor getTaskExecutor() {
|
||||
return this.taskExecutor;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.socket.client.ConnectionManagerSupport;
|
||||
import org.springframework.web.socket.handler.BeanCreatingHandlerProvider;
|
||||
@@ -41,27 +42,30 @@ import org.springframework.web.socket.handler.BeanCreatingHandlerProvider;
|
||||
*/
|
||||
public class AnnotatedEndpointConnectionManager extends ConnectionManagerSupport implements BeanFactoryAware {
|
||||
|
||||
@Nullable
|
||||
private final Object endpoint;
|
||||
|
||||
@Nullable
|
||||
private final BeanCreatingHandlerProvider<Object> endpointProvider;
|
||||
|
||||
private WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
|
||||
|
||||
private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("AnnotatedEndpointConnectionManager-");
|
||||
|
||||
@Nullable
|
||||
private volatile Session session;
|
||||
|
||||
|
||||
public AnnotatedEndpointConnectionManager(Object endpoint, String uriTemplate, Object... uriVariables) {
|
||||
super(uriTemplate, uriVariables);
|
||||
this.endpointProvider = null;
|
||||
this.endpoint = endpoint;
|
||||
this.endpointProvider = null;
|
||||
}
|
||||
|
||||
public AnnotatedEndpointConnectionManager(Class<?> endpointClass, String uriTemplate, Object... uriVariables) {
|
||||
super(uriTemplate, uriVariables);
|
||||
this.endpointProvider = new BeanCreatingHandlerProvider<>(endpointClass);
|
||||
this.endpoint = null;
|
||||
this.endpointProvider = new BeanCreatingHandlerProvider<>(endpointClass);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +108,11 @@ public class AnnotatedEndpointConnectionManager extends ConnectionManagerSupport
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Connecting to WebSocket at " + getUri());
|
||||
}
|
||||
Object endpointToUse = (endpoint != null) ? endpoint : endpointProvider.getHandler();
|
||||
Object endpointToUse = endpoint;
|
||||
if (endpointToUse == null) {
|
||||
Assert.state(endpointProvider != null, "No endpoint set");
|
||||
endpointToUse = endpointProvider.getHandler();
|
||||
}
|
||||
session = webSocketContainer.connectToServer(endpointToUse, getUri());
|
||||
logger.info("Successfully connected to WebSocket");
|
||||
}
|
||||
@@ -117,8 +125,9 @@ public class AnnotatedEndpointConnectionManager extends ConnectionManagerSupport
|
||||
@Override
|
||||
protected void closeConnection() throws Exception {
|
||||
try {
|
||||
if (isConnected()) {
|
||||
this.session.close();
|
||||
Session session = this.session;
|
||||
if (session != null && session.isOpen()) {
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -128,7 +137,8 @@ public class AnnotatedEndpointConnectionManager extends ConnectionManagerSupport
|
||||
|
||||
@Override
|
||||
protected boolean isConnected() {
|
||||
return (this.session != null && this.session.isOpen());
|
||||
Session session = this.session;
|
||||
return (session != null && session.isOpen());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.socket.client.ConnectionManagerSupport;
|
||||
import org.springframework.web.socket.handler.BeanCreatingHandlerProvider;
|
||||
@@ -48,8 +49,10 @@ import org.springframework.web.socket.handler.BeanCreatingHandlerProvider;
|
||||
*/
|
||||
public class EndpointConnectionManager extends ConnectionManagerSupport implements BeanFactoryAware {
|
||||
|
||||
@Nullable
|
||||
private final Endpoint endpoint;
|
||||
|
||||
@Nullable
|
||||
private final BeanCreatingHandlerProvider<Endpoint> endpointProvider;
|
||||
|
||||
private final ClientEndpointConfig.Builder configBuilder = ClientEndpointConfig.Builder.create();
|
||||
@@ -58,21 +61,22 @@ public class EndpointConnectionManager extends ConnectionManagerSupport implemen
|
||||
|
||||
private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("EndpointConnectionManager-");
|
||||
|
||||
@Nullable
|
||||
private volatile Session session;
|
||||
|
||||
|
||||
public EndpointConnectionManager(Endpoint endpoint, String uriTemplate, Object... uriVariables) {
|
||||
super(uriTemplate, uriVariables);
|
||||
Assert.notNull(endpoint, "endpoint must not be null");
|
||||
this.endpointProvider = null;
|
||||
this.endpoint = endpoint;
|
||||
this.endpointProvider = null;
|
||||
}
|
||||
|
||||
public EndpointConnectionManager(Class<? extends Endpoint> endpointClass, String uriTemplate, Object... uriVars) {
|
||||
super(uriTemplate, uriVars);
|
||||
Assert.notNull(endpointClass, "endpointClass must not be null");
|
||||
this.endpointProvider = new BeanCreatingHandlerProvider<>(endpointClass);
|
||||
this.endpoint = null;
|
||||
this.endpointProvider = new BeanCreatingHandlerProvider<>(endpointClass);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +139,11 @@ public class EndpointConnectionManager extends ConnectionManagerSupport implemen
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Connecting to WebSocket at " + getUri());
|
||||
}
|
||||
Endpoint endpointToUse = (endpoint != null) ? endpoint : endpointProvider.getHandler();
|
||||
Endpoint endpointToUse = endpoint;
|
||||
if (endpointToUse == null) {
|
||||
Assert.state(endpointProvider != null, "No endpoint set");
|
||||
endpointToUse = endpointProvider.getHandler();
|
||||
}
|
||||
ClientEndpointConfig endpointConfig = configBuilder.build();
|
||||
session = getWebSocketContainer().connectToServer(endpointToUse, endpointConfig, getUri());
|
||||
logger.info("Successfully connected to WebSocket");
|
||||
@@ -149,8 +157,9 @@ public class EndpointConnectionManager extends ConnectionManagerSupport implemen
|
||||
@Override
|
||||
protected void closeConnection() throws Exception {
|
||||
try {
|
||||
if (isConnected()) {
|
||||
this.session.close();
|
||||
Session session = this.session;
|
||||
if (session != null && session.isOpen()) {
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -160,7 +169,8 @@ public class EndpointConnectionManager extends ConnectionManagerSupport implemen
|
||||
|
||||
@Override
|
||||
protected boolean isConnected() {
|
||||
return (this.session != null && this.session.isOpen());
|
||||
Session session = this.session;
|
||||
return (session != null && session.isOpen());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ public class StandardWebSocketClient extends AbstractWebSocketClient {
|
||||
|
||||
private final Map<String,Object> userProperties = new HashMap<>();
|
||||
|
||||
@Nullable
|
||||
private AsyncListenableTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
|
||||
|
||||
|
||||
@@ -107,7 +108,7 @@ public class StandardWebSocketClient extends AbstractWebSocketClient {
|
||||
|
||||
/**
|
||||
* Set an {@link AsyncListenableTaskExecutor} to use when opening connections.
|
||||
* If this property is set to {@code null}, calls to any of the
|
||||
* If this property is set to {@code null}, calls to any of the
|
||||
* {@code doHandshake} methods will block until the connection is established.
|
||||
* <p>By default, an instance of {@code SimpleAsyncTaskExecutor} is used.
|
||||
*/
|
||||
@@ -118,6 +119,7 @@ public class StandardWebSocketClient extends AbstractWebSocketClient {
|
||||
/**
|
||||
* Return the configured {@link TaskExecutor}.
|
||||
*/
|
||||
@Nullable
|
||||
public AsyncListenableTaskExecutor getTaskExecutor() {
|
||||
return this.taskExecutor;
|
||||
}
|
||||
|
||||
@@ -54,18 +54,25 @@ public class WebSocketMessageBrokerStats {
|
||||
private static final Log logger = LogFactory.getLog(WebSocketMessageBrokerStats.class);
|
||||
|
||||
|
||||
@Nullable
|
||||
private SubProtocolWebSocketHandler webSocketHandler;
|
||||
|
||||
@Nullable
|
||||
private StompSubProtocolHandler stompSubProtocolHandler;
|
||||
|
||||
@Nullable
|
||||
private StompBrokerRelayMessageHandler stompBrokerRelay;
|
||||
|
||||
@Nullable
|
||||
private ThreadPoolExecutor inboundChannelExecutor;
|
||||
|
||||
@Nullable
|
||||
private ThreadPoolExecutor outboundChannelExecutor;
|
||||
|
||||
@Nullable
|
||||
private ScheduledThreadPoolExecutor sockJsTaskScheduler;
|
||||
|
||||
@Nullable
|
||||
private ScheduledFuture<?> loggingTask;
|
||||
|
||||
private long loggingPeriod = 30 * 60 * 1000;
|
||||
@@ -78,6 +85,9 @@ public class WebSocketMessageBrokerStats {
|
||||
|
||||
@Nullable
|
||||
private StompSubProtocolHandler initStompSubProtocolHandler() {
|
||||
if (this.webSocketHandler == null) {
|
||||
return null;
|
||||
}
|
||||
for (SubProtocolHandler handler : this.webSocketHandler.getProtocolHandlers()) {
|
||||
if (handler instanceof StompSubProtocolHandler) {
|
||||
return (StompSubProtocolHandler) handler;
|
||||
@@ -104,12 +114,12 @@ public class WebSocketMessageBrokerStats {
|
||||
|
||||
public void setSockJsTaskScheduler(ThreadPoolTaskScheduler sockJsTaskScheduler) {
|
||||
this.sockJsTaskScheduler = sockJsTaskScheduler.getScheduledThreadPoolExecutor();
|
||||
this.loggingTask = initLoggingTask(1 * 60 * 1000);
|
||||
this.loggingTask = initLoggingTask(60 * 1000);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ScheduledFuture<?> initLoggingTask(long initialDelay) {
|
||||
if (logger.isInfoEnabled() && this.loggingPeriod > 0) {
|
||||
if (this.sockJsTaskScheduler != null && this.loggingPeriod > 0 && logger.isInfoEnabled()) {
|
||||
return this.sockJsTaskScheduler.scheduleAtFixedRate(() ->
|
||||
logger.info(WebSocketMessageBrokerStats.this.toString()),
|
||||
initialDelay, this.loggingPeriod, TimeUnit.MILLISECONDS);
|
||||
|
||||
@@ -46,14 +46,17 @@ public abstract class AbstractWebSocketHandlerRegistration<M> implements WebSock
|
||||
|
||||
private final MultiValueMap<WebSocketHandler, String> handlerMap = new LinkedMultiValueMap<>();
|
||||
|
||||
@Nullable
|
||||
private HandshakeHandler handshakeHandler;
|
||||
|
||||
private final List<HandshakeInterceptor> interceptors = new ArrayList<>();
|
||||
|
||||
private final List<String> allowedOrigins = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private SockJsServiceRegistration sockJsServiceRegistration;
|
||||
|
||||
@Nullable
|
||||
private TaskScheduler scheduler;
|
||||
|
||||
|
||||
@@ -86,6 +89,7 @@ public abstract class AbstractWebSocketHandlerRegistration<M> implements WebSock
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected HandshakeHandler getHandshakeHandler() {
|
||||
return this.handshakeHandler;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
@@ -42,20 +43,20 @@ public class ServletWebSocketHandlerRegistry implements WebSocketHandlerRegistry
|
||||
|
||||
private final List<ServletWebSocketHandlerRegistration> registrations = new ArrayList<>(4);
|
||||
|
||||
@Nullable
|
||||
private TaskScheduler scheduler;
|
||||
|
||||
private int order = 1;
|
||||
|
||||
@Nullable
|
||||
private UrlPathHelper urlPathHelper;
|
||||
|
||||
|
||||
public ServletWebSocketHandlerRegistry() {
|
||||
this.scheduler = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated constructor with a TaskScheduler for SockJS use.
|
||||
*
|
||||
* @deprecated as of 5.0 a TaskScheduler is not provided upfront, not until
|
||||
* it is obvious that it is needed, see {@link #requiresTaskScheduler()} and
|
||||
* {@link #setTaskScheduler}.
|
||||
@@ -95,6 +96,7 @@ public class ServletWebSocketHandlerRegistry implements WebSocketHandlerRegistry
|
||||
this.urlPathHelper = urlPathHelper;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UrlPathHelper getUrlPathHelper() {
|
||||
return this.urlPathHelper;
|
||||
}
|
||||
@@ -142,7 +144,7 @@ public class ServletWebSocketHandlerRegistry implements WebSocketHandlerRegistry
|
||||
|
||||
private void updateTaskScheduler(ServletWebSocketHandlerRegistration registration) {
|
||||
SockJsServiceRegistration sockJsRegistration = registration.getSockJsServiceRegistration();
|
||||
if (sockJsRegistration != null && sockJsRegistration.getTaskScheduler() == null) {
|
||||
if (sockJsRegistration != null && this.scheduler != null && sockJsRegistration.getTaskScheduler() == null) {
|
||||
sockJsRegistration.setTaskScheduler(this.scheduler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,20 +41,28 @@ import org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsServ
|
||||
*/
|
||||
public class SockJsServiceRegistration {
|
||||
|
||||
@Nullable
|
||||
private TaskScheduler scheduler;
|
||||
|
||||
@Nullable
|
||||
private String clientLibraryUrl;
|
||||
|
||||
@Nullable
|
||||
private Integer streamBytesLimit;
|
||||
|
||||
@Nullable
|
||||
private Boolean sessionCookieNeeded;
|
||||
|
||||
@Nullable
|
||||
private Long heartbeatTime;
|
||||
|
||||
@Nullable
|
||||
private Long disconnectDelay;
|
||||
|
||||
@Nullable
|
||||
private Integer httpMessageCacheSize;
|
||||
|
||||
@Nullable
|
||||
private Boolean webSocketEnabled;
|
||||
|
||||
private final List<TransportHandler> transportHandlers = new ArrayList<>();
|
||||
@@ -65,8 +73,10 @@ public class SockJsServiceRegistration {
|
||||
|
||||
private final List<String> allowedOrigins = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private Boolean suppressCors;
|
||||
|
||||
@Nullable
|
||||
private SockJsMessageCodec messageCodec;
|
||||
|
||||
|
||||
@@ -75,7 +85,6 @@ public class SockJsServiceRegistration {
|
||||
|
||||
/**
|
||||
* Deprecated constructor with a TaskScheduler.
|
||||
*
|
||||
* @deprecated as of 5.0 a TaskScheduler is not provided upfront, not until
|
||||
* it is obvious that it is needed; call {@link #getTaskScheduler()} to check
|
||||
* and then {@link #setTaskScheduler(TaskScheduler)} to set it before a call
|
||||
@@ -91,7 +100,7 @@ public class SockJsServiceRegistration {
|
||||
* A scheduler instance to use for scheduling SockJS heart-beats.
|
||||
*/
|
||||
public SockJsServiceRegistration setTaskScheduler(TaskScheduler scheduler) {
|
||||
Assert.notNull(scheduler, "TaskScheduler is required.");
|
||||
Assert.notNull(scheduler, "TaskScheduler is required");
|
||||
this.scheduler = scheduler;
|
||||
return this;
|
||||
}
|
||||
@@ -302,9 +311,9 @@ public class SockJsServiceRegistration {
|
||||
}
|
||||
|
||||
private TransportHandlingSockJsService createSockJsService() {
|
||||
Assert.state(this.scheduler != null, "No TaskScheduler available");
|
||||
Assert.state(this.transportHandlers.isEmpty() || this.transportHandlerOverrides.isEmpty(),
|
||||
"Specify either TransportHandlers or TransportHandler overrides, not both");
|
||||
|
||||
return (!this.transportHandlers.isEmpty() ?
|
||||
new TransportHandlingSockJsService(this.scheduler, this.transportHandlers) :
|
||||
new DefaultSockJsService(this.scheduler, this.transportHandlerOverrides));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -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;
|
||||
@@ -51,6 +52,7 @@ public class WebMvcStompEndpointRegistry implements StompEndpointRegistry {
|
||||
|
||||
private int order = 1;
|
||||
|
||||
@Nullable
|
||||
private UrlPathHelper urlPathHelper;
|
||||
|
||||
private final SubProtocolWebSocketHandler subProtocolWebSocketHandler;
|
||||
@@ -127,6 +129,7 @@ public class WebMvcStompEndpointRegistry implements StompEndpointRegistry {
|
||||
this.urlPathHelper = urlPathHelper;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected UrlPathHelper getUrlPathHelper() {
|
||||
return this.urlPathHelper;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -35,7 +36,6 @@ import org.springframework.web.socket.sockjs.SockJsService;
|
||||
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
|
||||
import org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler;
|
||||
|
||||
|
||||
/**
|
||||
* An abstract base class for configuring STOMP over WebSocket/SockJS endpoints.
|
||||
*
|
||||
@@ -50,12 +50,14 @@ public class WebMvcStompWebSocketEndpointRegistration implements StompWebSocketE
|
||||
|
||||
private final TaskScheduler sockJsTaskScheduler;
|
||||
|
||||
@Nullable
|
||||
private HandshakeHandler handshakeHandler;
|
||||
|
||||
private final List<HandshakeInterceptor> interceptors = new ArrayList<>();
|
||||
|
||||
private final List<String> allowedOrigins = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private SockJsServiceRegistration registration;
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Date;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
@@ -33,8 +34,10 @@ import org.springframework.web.servlet.HandlerMapping;
|
||||
*/
|
||||
public class WebSocketConfigurationSupport {
|
||||
|
||||
@Nullable
|
||||
private ServletWebSocketHandlerRegistry handlerRegistry;
|
||||
|
||||
@Nullable
|
||||
private TaskScheduler scheduler;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,10 @@
|
||||
package org.springframework.web.socket.config.annotation;
|
||||
|
||||
import org.springframework.beans.factory.config.CustomScopeConfigurer;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
|
||||
import org.springframework.messaging.simp.SimpSessionScope;
|
||||
import org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler;
|
||||
@@ -48,6 +50,7 @@ import org.springframework.web.socket.messaging.WebSocketAnnotationMethodMessage
|
||||
*/
|
||||
public abstract class WebSocketMessageBrokerConfigurationSupport extends AbstractMessageBrokerConfiguration {
|
||||
|
||||
@Nullable
|
||||
private WebSocketTransportRegistration transportRegistration;
|
||||
|
||||
|
||||
@@ -67,7 +70,10 @@ public abstract class WebSocketMessageBrokerConfigurationSupport extends Abstrac
|
||||
WebSocketHandler handler = decorateWebSocketHandler(subProtocolWebSocketHandler());
|
||||
WebMvcStompEndpointRegistry registry = new WebMvcStompEndpointRegistry(handler,
|
||||
getTransportRegistration(), messageBrokerTaskScheduler());
|
||||
registry.setApplicationContext(getApplicationContext());
|
||||
ApplicationContext applicationContext = getApplicationContext();
|
||||
if (applicationContext != null) {
|
||||
registry.setApplicationContext(applicationContext);
|
||||
}
|
||||
registerStompEndpoints(registry);
|
||||
return registry.getHandlerMapping();
|
||||
}
|
||||
@@ -126,8 +132,12 @@ public abstract class WebSocketMessageBrokerConfigurationSupport extends Abstrac
|
||||
protected MappingJackson2MessageConverter createJacksonConverter() {
|
||||
MappingJackson2MessageConverter messageConverter = super.createJacksonConverter();
|
||||
// Use Jackson builder in order to have JSR-310 and Joda-Time modules registered automatically
|
||||
messageConverter.setObjectMapper(Jackson2ObjectMapperBuilder.json()
|
||||
.applicationContext(this.getApplicationContext()).build());
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
|
||||
ApplicationContext applicationContext = getApplicationContext();
|
||||
if (applicationContext != null) {
|
||||
builder.applicationContext(applicationContext);
|
||||
}
|
||||
messageConverter.setObjectMapper(builder.build());
|
||||
return messageConverter;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -34,6 +35,7 @@ public class BeanCreatingHandlerProvider<T> implements BeanFactoryAware {
|
||||
|
||||
private final Class<? extends T> handlerType;
|
||||
|
||||
@Nullable
|
||||
private AutowireCapableBeanFactory beanFactory;
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ public abstract class AbstractSubProtocolEvent extends ApplicationEvent {
|
||||
|
||||
private final Message<byte[]> message;
|
||||
|
||||
@Nullable
|
||||
private final Principal user;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -89,8 +89,7 @@ public class SessionDisconnectEvent extends AbstractSubProtocolEvent {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SessionDisconnectEvent[sessionId=" + this.sessionId + ", " +
|
||||
(this.status != null ? this.status.toString() : "closeStatus=null") + "]";
|
||||
return "SessionDisconnectEvent[sessionId=" + this.sessionId + ", " + this.status.toString() + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE
|
||||
private static final byte[] EMPTY_PAYLOAD = new byte[0];
|
||||
|
||||
|
||||
@Nullable
|
||||
private StompSubProtocolErrorHandler errorHandler;
|
||||
|
||||
private int messageSizeLimit = 64 * 1024;
|
||||
@@ -100,12 +101,15 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE
|
||||
|
||||
private final Map<String, BufferingStompDecoder> decoders = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private MessageHeaderInitializer headerInitializer;
|
||||
|
||||
private final Map<String, Principal> stompAuthentications = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private Boolean immutableMessageInterceptorPresent;
|
||||
|
||||
@Nullable
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
private final Stats stats = new Stats();
|
||||
@@ -289,13 +293,13 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE
|
||||
}
|
||||
if (this.eventPublisher != null) {
|
||||
if (isConnect) {
|
||||
publishEvent(new SessionConnectEvent(this, message, user));
|
||||
publishEvent(this.eventPublisher, new SessionConnectEvent(this, message, user));
|
||||
}
|
||||
else if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())) {
|
||||
publishEvent(new SessionSubscribeEvent(this, message, user));
|
||||
publishEvent(this.eventPublisher, new SessionSubscribeEvent(this, message, user));
|
||||
}
|
||||
else if (StompCommand.UNSUBSCRIBE.equals(headerAccessor.getCommand())) {
|
||||
publishEvent(new SessionUnsubscribeEvent(this, message, user));
|
||||
publishEvent(this.eventPublisher, new SessionUnsubscribeEvent(this, message, user));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -372,9 +376,9 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE
|
||||
return false;
|
||||
}
|
||||
|
||||
private void publishEvent(ApplicationEvent event) {
|
||||
private void publishEvent(ApplicationEventPublisher publisher, ApplicationEvent event) {
|
||||
try {
|
||||
this.eventPublisher.publishEvent(event);
|
||||
publisher.publishEvent(event);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
@@ -418,7 +422,7 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE
|
||||
SimpAttributes simpAttributes = new SimpAttributes(session.getId(), session.getAttributes());
|
||||
SimpAttributesContextHolder.setAttributes(simpAttributes);
|
||||
Principal user = getUser(session);
|
||||
publishEvent(new SessionConnectedEvent(this, (Message<byte[]>) message, user));
|
||||
publishEvent(this.eventPublisher, new SessionConnectedEvent(this, (Message<byte[]>) message, user));
|
||||
}
|
||||
finally {
|
||||
SimpAttributesContextHolder.resetAttributes();
|
||||
@@ -604,7 +608,7 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE
|
||||
SimpAttributesContextHolder.setAttributes(simpAttributes);
|
||||
if (this.eventPublisher != null) {
|
||||
Principal user = getUser(session);
|
||||
publishEvent(new SessionDisconnectEvent(this, message, session.getId(), closeStatus, user));
|
||||
publishEvent(this.eventPublisher, new SessionDisconnectEvent(this, message, session.getId(), closeStatus, user));
|
||||
}
|
||||
outputChannel.send(message);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ public class SubProtocolWebSocketHandler
|
||||
|
||||
private final Set<SubProtocolHandler> protocolHandlers = new LinkedHashSet<>();
|
||||
|
||||
@Nullable
|
||||
private SubProtocolHandler defaultProtocolHandler;
|
||||
|
||||
private final Map<String, WebSocketSessionHolder> sessions = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -59,6 +59,7 @@ public abstract class AbstractStandardUpgradeStrategy implements RequestUpgradeS
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Nullable
|
||||
private volatile List<WebSocketExtension> extensions;
|
||||
|
||||
|
||||
@@ -84,11 +85,13 @@ public abstract class AbstractStandardUpgradeStrategy implements RequestUpgradeS
|
||||
|
||||
@Override
|
||||
public List<WebSocketExtension> getSupportedExtensions(ServerHttpRequest request) {
|
||||
if (this.extensions == null) {
|
||||
List<WebSocketExtension> extensions = this.extensions;
|
||||
if (extensions == null) {
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
this.extensions = getInstalledExtensions(getContainer(servletRequest));
|
||||
extensions = getInstalledExtensions(getContainer(servletRequest));
|
||||
this.extensions = extensions;
|
||||
}
|
||||
return this.extensions;
|
||||
return extensions;
|
||||
}
|
||||
|
||||
protected List<WebSocketExtension> getInstalledExtensions(WebSocketContainer container) {
|
||||
|
||||
@@ -55,8 +55,10 @@ import org.springframework.web.context.support.WebApplicationObjectSupport;
|
||||
public class ServerEndpointExporter extends WebApplicationObjectSupport
|
||||
implements InitializingBean, SmartInitializingSingleton {
|
||||
|
||||
@Nullable
|
||||
private List<Class<?>> annotatedEndpointClasses;
|
||||
|
||||
@Nullable
|
||||
private ServerContainer serverContainer;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,6 +30,7 @@ import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.socket.handler.BeanCreatingHandlerProvider;
|
||||
|
||||
@@ -56,10 +57,12 @@ public class ServerEndpointRegistration extends ServerEndpointConfig.Configurato
|
||||
|
||||
private final String path;
|
||||
|
||||
private final BeanCreatingHandlerProvider<Endpoint> endpointProvider;
|
||||
|
||||
@Nullable
|
||||
private final Endpoint endpoint;
|
||||
|
||||
@Nullable
|
||||
private final BeanCreatingHandlerProvider<Endpoint> endpointProvider;
|
||||
|
||||
private List<Class<? extends Encoder>> encoders = new ArrayList<>();
|
||||
|
||||
private List<Class<? extends Decoder>> decoders = new ArrayList<>();
|
||||
@@ -71,20 +74,6 @@ public class ServerEndpointRegistration extends ServerEndpointConfig.Configurato
|
||||
private final Map<String, Object> userProperties = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link ServerEndpointRegistration} instance from an
|
||||
* {@code javax.websocket.Endpoint} class.
|
||||
* @param path the endpoint path
|
||||
* @param endpointClass the endpoint class
|
||||
*/
|
||||
public ServerEndpointRegistration(String path, Class<? extends Endpoint> endpointClass) {
|
||||
Assert.hasText(path, "path must not be empty");
|
||||
Assert.notNull(endpointClass, "endpointClass must not be null");
|
||||
this.path = path;
|
||||
this.endpointProvider = new BeanCreatingHandlerProvider<>(endpointClass);
|
||||
this.endpoint = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ServerEndpointRegistration} instance from an
|
||||
* {@code javax.websocket.Endpoint} instance.
|
||||
@@ -95,8 +84,22 @@ public class ServerEndpointRegistration extends ServerEndpointConfig.Configurato
|
||||
Assert.hasText(path, "path must not be empty");
|
||||
Assert.notNull(endpoint, "endpoint must not be null");
|
||||
this.path = path;
|
||||
this.endpointProvider = null;
|
||||
this.endpoint = endpoint;
|
||||
this.endpointProvider = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ServerEndpointRegistration} instance from an
|
||||
* {@code javax.websocket.Endpoint} class.
|
||||
* @param path the endpoint path
|
||||
* @param endpointClass the endpoint class
|
||||
*/
|
||||
public ServerEndpointRegistration(String path, Class<? extends Endpoint> endpointClass) {
|
||||
Assert.hasText(path, "path must not be empty");
|
||||
Assert.notNull(endpointClass, "endpointClass must not be null");
|
||||
this.path = path;
|
||||
this.endpoint = null;
|
||||
this.endpointProvider = new BeanCreatingHandlerProvider<>(endpointClass);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,11 +110,23 @@ public class ServerEndpointRegistration extends ServerEndpointConfig.Configurato
|
||||
|
||||
@Override
|
||||
public Class<? extends Endpoint> getEndpointClass() {
|
||||
return (this.endpoint != null ? this.endpoint.getClass() : this.endpointProvider.getHandlerType());
|
||||
if (this.endpoint != null) {
|
||||
return this.endpoint.getClass();
|
||||
}
|
||||
else {
|
||||
Assert.state(this.endpointProvider != null, "No endpoint set");
|
||||
return this.endpointProvider.getHandlerType();
|
||||
}
|
||||
}
|
||||
|
||||
public Endpoint getEndpoint() {
|
||||
return (this.endpoint != null) ? this.endpoint : this.endpointProvider.getHandler();
|
||||
if (this.endpoint != null) {
|
||||
return this.endpoint;
|
||||
}
|
||||
else {
|
||||
Assert.state(this.endpointProvider != null, "No endpoint set");
|
||||
return this.endpointProvider.getHandler();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSubprotocols(List<String> protocols) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import javax.websocket.server.ServerContainer;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
@@ -46,16 +47,22 @@ import org.springframework.web.context.ServletContextAware;
|
||||
public class ServletServerContainerFactoryBean
|
||||
implements FactoryBean<WebSocketContainer>, ServletContextAware, InitializingBean {
|
||||
|
||||
@Nullable
|
||||
private Long asyncSendTimeout;
|
||||
|
||||
@Nullable
|
||||
private Long maxSessionIdleTimeout;
|
||||
|
||||
@Nullable
|
||||
private Integer maxTextMessageBufferSize;
|
||||
|
||||
@Nullable
|
||||
private Integer maxBinaryMessageBufferSize;
|
||||
|
||||
@Nullable
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Nullable
|
||||
private ServerContainer serverContainer;
|
||||
|
||||
|
||||
@@ -63,7 +70,8 @@ public class ServletServerContainerFactoryBean
|
||||
this.asyncSendTimeout = timeoutInMillis;
|
||||
}
|
||||
|
||||
public long getAsyncSendTimeout() {
|
||||
@Nullable
|
||||
public Long getAsyncSendTimeout() {
|
||||
return this.asyncSendTimeout;
|
||||
}
|
||||
|
||||
@@ -71,6 +79,7 @@ public class ServletServerContainerFactoryBean
|
||||
this.maxSessionIdleTimeout = timeoutInMillis;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getMaxSessionIdleTimeout() {
|
||||
return this.maxSessionIdleTimeout;
|
||||
}
|
||||
@@ -79,6 +88,7 @@ public class ServletServerContainerFactoryBean
|
||||
this.maxTextMessageBufferSize = bufferSize;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getMaxTextMessageBufferSize() {
|
||||
return this.maxTextMessageBufferSize;
|
||||
}
|
||||
@@ -87,6 +97,7 @@ public class ServletServerContainerFactoryBean
|
||||
this.maxBinaryMessageBufferSize = bufferSize;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getMaxBinaryMessageBufferSize() {
|
||||
return this.maxBinaryMessageBufferSize;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.lang.Nullable;
|
||||
@SuppressWarnings("serial")
|
||||
public class SockJsException extends NestedRuntimeException {
|
||||
|
||||
@Nullable
|
||||
private final String sessionId;
|
||||
|
||||
|
||||
@@ -55,6 +56,7 @@ public class SockJsException extends NestedRuntimeException {
|
||||
/**
|
||||
* Return the SockJS session id.
|
||||
*/
|
||||
@Nullable
|
||||
public String getSockJsSessionId() {
|
||||
return this.sessionId;
|
||||
}
|
||||
|
||||
@@ -59,8 +59,10 @@ public abstract class AbstractClientSockJsSession implements WebSocketSession {
|
||||
|
||||
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private volatile State state = State.NEW;
|
||||
|
||||
@Nullable
|
||||
private volatile CloseStatus closeStatus;
|
||||
|
||||
|
||||
@@ -315,15 +317,19 @@ public abstract class AbstractClientSockJsSession implements WebSocketSession {
|
||||
}
|
||||
|
||||
public void afterTransportClosed(@Nullable CloseStatus closeStatus) {
|
||||
this.closeStatus = (this.closeStatus != null ? this.closeStatus : closeStatus);
|
||||
Assert.state(this.closeStatus != null, "CloseStatus not available");
|
||||
CloseStatus cs = this.closeStatus;
|
||||
if (cs == null) {
|
||||
cs = closeStatus;
|
||||
this.closeStatus = closeStatus;
|
||||
}
|
||||
Assert.state(cs != null, "CloseStatus not available");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Transport closed with " + this.closeStatus + " in " + this);
|
||||
logger.debug("Transport closed with " + cs + " in " + this);
|
||||
}
|
||||
|
||||
this.state = State.CLOSED;
|
||||
try {
|
||||
this.webSocketHandler.afterConnectionClosed(this, this.closeStatus);
|
||||
this.webSocketHandler.afterConnectionClosed(this, cs);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.error("WebSocketHandler.afterConnectionClosed threw an exception", ex);
|
||||
|
||||
@@ -61,14 +61,17 @@ class DefaultTransportRequest implements TransportRequest {
|
||||
|
||||
private SockJsMessageCodec codec;
|
||||
|
||||
@Nullable
|
||||
private Principal user;
|
||||
|
||||
private long timeoutValue;
|
||||
|
||||
@Nullable
|
||||
private TaskScheduler timeoutScheduler;
|
||||
|
||||
private final List<Runnable> timeoutTasks = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private DefaultTransportRequest fallbackRequest;
|
||||
|
||||
|
||||
@@ -191,7 +194,7 @@ class DefaultTransportRequest implements TransportRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(WebSocketSession session) {
|
||||
public void onSuccess(@Nullable WebSocketSession session) {
|
||||
if (this.handled.compareAndSet(false, true)) {
|
||||
this.future.set(session);
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ public class RestTemplateXhrTransport extends AbstractXhrTransport {
|
||||
|
||||
private final HttpHeaders headers;
|
||||
|
||||
@Nullable
|
||||
private final String body;
|
||||
|
||||
public XhrRequestCallback(HttpHeaders headers) {
|
||||
@@ -178,9 +179,7 @@ public class RestTemplateXhrTransport extends AbstractXhrTransport {
|
||||
|
||||
@Override
|
||||
public void doWithRequest(ClientHttpRequest request) throws IOException {
|
||||
if (this.headers != null) {
|
||||
request.getHeaders().putAll(this.headers);
|
||||
}
|
||||
request.getHeaders().putAll(this.headers);
|
||||
if (this.body != null) {
|
||||
StreamUtils.copy(this.body, SockJsFrame.CHARSET, request.getBody());
|
||||
}
|
||||
|
||||
@@ -79,12 +79,15 @@ public class SockJsClient implements WebSocketClient, Lifecycle {
|
||||
|
||||
private final List<Transport> transports;
|
||||
|
||||
@Nullable
|
||||
private String[] httpHeaderNames;
|
||||
|
||||
private InfoReceiver infoReceiver;
|
||||
|
||||
@Nullable
|
||||
private SockJsMessageCodec messageCodec;
|
||||
|
||||
@Nullable
|
||||
private TaskScheduler connectTimeoutScheduler;
|
||||
|
||||
private volatile boolean running = false;
|
||||
@@ -171,7 +174,7 @@ public class SockJsClient implements WebSocketClient, Lifecycle {
|
||||
* Jackson2SockJsMessageCodec} is used if Jackson is on the classpath.
|
||||
*/
|
||||
public void setMessageCodec(SockJsMessageCodec messageCodec) {
|
||||
Assert.notNull(messageCodec, "'messageCodec' is required");
|
||||
Assert.notNull(messageCodec, "SockJsMessageCodec is required");
|
||||
this.messageCodec = messageCodec;
|
||||
}
|
||||
|
||||
@@ -179,6 +182,7 @@ public class SockJsClient implements WebSocketClient, Lifecycle {
|
||||
* Return the SockJsMessageCodec to use.
|
||||
*/
|
||||
public SockJsMessageCodec getMessageCodec() {
|
||||
Assert.state(this.messageCodec != null, "No SockJsMessageCodec set");
|
||||
return this.messageCodec;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.web.socket.sockjs.client;
|
||||
import java.net.URI;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.IdGenerator;
|
||||
import org.springframework.util.JdkIdGenerator;
|
||||
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||
@@ -39,10 +40,13 @@ public class SockJsUrlInfo {
|
||||
|
||||
private final URI sockJsUrl;
|
||||
|
||||
@Nullable
|
||||
private String serverId;
|
||||
|
||||
@Nullable
|
||||
private String sessionId;
|
||||
|
||||
@Nullable
|
||||
private UUID uuid;
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.springframework.web.socket.adapter.NativeWebSocketSession;
|
||||
*/
|
||||
public class WebSocketClientSockJsSession extends AbstractClientSockJsSession implements NativeWebSocketSession {
|
||||
|
||||
@Nullable
|
||||
private WebSocketSession webSocketSession;
|
||||
|
||||
|
||||
@@ -51,6 +52,7 @@ public class WebSocketClientSockJsSession extends AbstractClientSockJsSession im
|
||||
|
||||
@Override
|
||||
public Object getNativeSession() {
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession;
|
||||
}
|
||||
|
||||
@@ -62,54 +64,50 @@ public class WebSocketClientSockJsSession extends AbstractClientSockJsSession im
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getRemoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAcceptedProtocol() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getAcceptedProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextMessageSizeLimit(int messageSizeLimit) {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
this.webSocketSession.setTextMessageSizeLimit(messageSizeLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextMessageSizeLimit() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getTextMessageSizeLimit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBinaryMessageSizeLimit(int messageSizeLimit) {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
this.webSocketSession.setBinaryMessageSizeLimit(messageSizeLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBinaryMessageSizeLimit() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getBinaryMessageSizeLimit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WebSocketExtension> getExtensions() {
|
||||
checkDelegateSessionInitialized();
|
||||
return this.webSocketSession.getExtensions();
|
||||
}
|
||||
|
||||
private void checkDelegateSessionInitialized() {
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getExtensions();
|
||||
}
|
||||
|
||||
public void initializeDelegateSession(WebSocketSession session) {
|
||||
@@ -118,6 +116,7 @@ public class WebSocketClientSockJsSession extends AbstractClientSockJsSession im
|
||||
|
||||
@Override
|
||||
protected void sendInternal(TextMessage textMessage) throws IOException {
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
this.webSocketSession.sendMessage(textMessage);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,13 +58,11 @@ public class XhrClientSockJsSession extends AbstractClientSockJsSession {
|
||||
XhrTransport transport, SettableListenableFuture<WebSocketSession> connectFuture) {
|
||||
|
||||
super(request, handler, connectFuture);
|
||||
Assert.notNull(transport, "'transport' is required");
|
||||
Assert.notNull(transport, "XhrTransport is required");
|
||||
this.transport = transport;
|
||||
this.headers = request.getHttpRequestHeaders();
|
||||
this.sendHeaders = new HttpHeaders();
|
||||
if (this.headers != null) {
|
||||
this.sendHeaders.putAll(this.headers);
|
||||
}
|
||||
this.sendHeaders.putAll(this.headers);
|
||||
this.sendHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
this.sendUrl = request.getSockJsUrlInfo().getTransportUrl(TransportType.XHR_SEND);
|
||||
}
|
||||
|
||||
@@ -69,12 +69,14 @@ public class TransportHandlingSockJsService extends AbstractSockJsService implem
|
||||
|
||||
private final Map<TransportType, TransportHandler> handlers = new HashMap<>();
|
||||
|
||||
@Nullable
|
||||
private SockJsMessageCodec messageCodec;
|
||||
|
||||
private final List<HandshakeInterceptor> interceptors = new ArrayList<>();
|
||||
|
||||
private final Map<String, SockJsSession> sessions = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private ScheduledFuture<?> sessionCleanupTask;
|
||||
|
||||
private boolean running;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.web.socket.sockjs.transport.handler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -69,7 +70,7 @@ public class SockJsWebSocketHandler extends TextWebSocketHandler implements SubP
|
||||
|
||||
webSocketHandler = WebSocketHandlerDecorator.unwrap(webSocketHandler);
|
||||
this.subProtocols = ((webSocketHandler instanceof SubProtocolCapable) ?
|
||||
new ArrayList<>(((SubProtocolCapable) webSocketHandler).getSubProtocols()) : null);
|
||||
new ArrayList<>(((SubProtocolCapable) webSocketHandler).getSubProtocols()) : Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -33,6 +32,8 @@ import org.springframework.http.server.ServerHttpAsyncRequestControl;
|
||||
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.util.Assert;
|
||||
import org.springframework.web.filter.ShallowEtagHeaderFilter;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.WebSocketExtension;
|
||||
@@ -53,22 +54,31 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
|
||||
private final Queue<String> messageCache;
|
||||
|
||||
@Nullable
|
||||
private volatile URI uri;
|
||||
|
||||
@Nullable
|
||||
private volatile HttpHeaders handshakeHeaders;
|
||||
|
||||
@Nullable
|
||||
private volatile Principal principal;
|
||||
|
||||
@Nullable
|
||||
private volatile InetSocketAddress localAddress;
|
||||
|
||||
@Nullable
|
||||
private volatile InetSocketAddress remoteAddress;
|
||||
|
||||
@Nullable
|
||||
private volatile String acceptedProtocol;
|
||||
|
||||
@Nullable
|
||||
private volatile ServerHttpResponse response;
|
||||
|
||||
@Nullable
|
||||
private volatile SockJsFrameFormat frameFormat;
|
||||
|
||||
@Nullable
|
||||
private volatile ServerHttpAsyncRequestControl asyncRequestControl;
|
||||
|
||||
private boolean readyToSend;
|
||||
@@ -84,12 +94,16 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return this.uri;
|
||||
URI uri = this.uri;
|
||||
Assert.state(uri != null, "No initial request yet");
|
||||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHandshakeHeaders() {
|
||||
return this.handshakeHeaders;
|
||||
HttpHeaders headers = this.handshakeHeaders;
|
||||
Assert.state(headers != null, "No initial request yet");
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -202,8 +216,9 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
try {
|
||||
this.response = response;
|
||||
this.frameFormat = frameFormat;
|
||||
this.asyncRequestControl = request.getAsyncRequestControl(response);
|
||||
this.asyncRequestControl.start(-1);
|
||||
ServerHttpAsyncRequestControl control = request.getAsyncRequestControl(response);
|
||||
this.asyncRequestControl = control;
|
||||
control.start(-1);
|
||||
disableShallowEtagHeaderFilter(request);
|
||||
// Let "our" handler know before sending the open frame to the remote handler
|
||||
delegateConnectionEstablished();
|
||||
@@ -241,8 +256,9 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
}
|
||||
this.response = response;
|
||||
this.frameFormat = frameFormat;
|
||||
this.asyncRequestControl = request.getAsyncRequestControl(response);
|
||||
this.asyncRequestControl.start(-1);
|
||||
ServerHttpAsyncRequestControl control = request.getAsyncRequestControl(response);
|
||||
this.asyncRequestControl = control;
|
||||
control.start(-1);
|
||||
disableShallowEtagHeaderFilter(request);
|
||||
handleRequestInternal(request, response, false);
|
||||
this.readyToSend = isActive();
|
||||
@@ -329,12 +345,16 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
@Override
|
||||
protected void writeFrameInternal(SockJsFrame frame) throws IOException {
|
||||
if (isActive()) {
|
||||
String formattedFrame = this.frameFormat.format(frame);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Writing to HTTP response: " + formattedFrame);
|
||||
SockJsFrameFormat frameFormat = this.frameFormat;
|
||||
ServerHttpResponse response = this.response;
|
||||
if (frameFormat != null && response != null) {
|
||||
String formattedFrame = frameFormat.format(frame);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Writing to HTTP response: " + formattedFrame);
|
||||
}
|
||||
response.getBody().write(formattedFrame.getBytes(SockJsFrame.CHARSET));
|
||||
response.flush();
|
||||
}
|
||||
this.response.getBody().write(formattedFrame.getBytes(SockJsFrame.CHARSET));
|
||||
this.response.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,8 +107,10 @@ public abstract class AbstractSockJsSession implements SockJsSession {
|
||||
|
||||
private volatile long timeLastActive = this.timeCreated;
|
||||
|
||||
@Nullable
|
||||
private ScheduledFuture<?> heartbeatFuture;
|
||||
|
||||
@Nullable
|
||||
private HeartbeatTask heartbeatTask;
|
||||
|
||||
private volatile boolean heartbeatDisabled;
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.Queue;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
@@ -47,6 +48,7 @@ import org.springframework.web.socket.sockjs.transport.SockJsServiceConfig;
|
||||
*/
|
||||
public class WebSocketServerSockJsSession extends AbstractSockJsSession implements NativeWebSocketSession {
|
||||
|
||||
@Nullable
|
||||
private WebSocketSession webSocketSession;
|
||||
|
||||
private volatile boolean openFrameSent;
|
||||
@@ -61,7 +63,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
|
||||
|
||||
|
||||
public WebSocketServerSockJsSession(String id, SockJsServiceConfig config,
|
||||
WebSocketHandler handler, Map<String, Object> attributes) {
|
||||
WebSocketHandler handler, @Nullable Map<String, Object> attributes) {
|
||||
|
||||
super(id, config, handler, attributes);
|
||||
}
|
||||
@@ -69,76 +71,73 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getUri();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHandshakeHeaders() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getHandshakeHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getPrincipal() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getRemoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAcceptedProtocol() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getAcceptedProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextMessageSizeLimit(int messageSizeLimit) {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
this.webSocketSession.setTextMessageSizeLimit(messageSizeLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextMessageSizeLimit() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getTextMessageSizeLimit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBinaryMessageSizeLimit(int messageSizeLimit) {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
this.webSocketSession.setBinaryMessageSizeLimit(messageSizeLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBinaryMessageSizeLimit() {
|
||||
checkDelegateSessionInitialized();
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getBinaryMessageSizeLimit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WebSocketExtension> getExtensions() {
|
||||
checkDelegateSessionInitialized();
|
||||
return this.webSocketSession.getExtensions();
|
||||
}
|
||||
|
||||
private void checkDelegateSessionInitialized() {
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return this.webSocketSession.getExtensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNativeSession() {
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
return (this.webSocketSession instanceof NativeWebSocketSession ?
|
||||
((NativeWebSocketSession) this.webSocketSession).getNativeSession() : this.webSocketSession);
|
||||
}
|
||||
@@ -215,6 +214,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
|
||||
|
||||
@Override
|
||||
protected void writeFrameInternal(SockJsFrame frame) throws IOException {
|
||||
Assert.state(this.webSocketSession != null, "WebSocketSession not yet initialized");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Writing " + frame);
|
||||
}
|
||||
@@ -228,7 +228,9 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
|
||||
synchronized (this.disconnectLock) {
|
||||
if (isActive()) {
|
||||
this.disconnected = true;
|
||||
this.webSocketSession.close(status);
|
||||
if (this.webSocketSession != null) {
|
||||
this.webSocketSession.close(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -75,7 +75,7 @@ public class XhrTransportTests {
|
||||
TestXhrTransport transport = new TestXhrTransport();
|
||||
transport.sendMessageResponseToReturn = new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
URI url = new URI("http://example.com");
|
||||
transport.executeSendRequest(url, null, new TextMessage("payload"));
|
||||
transport.executeSendRequest(url, new HttpHeaders(), new TextMessage("payload"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,6 +86,7 @@ public class XhrTransportTests {
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
given(request.getSockJsUrlInfo()).willReturn(new SockJsUrlInfo(new URI("http://example.com")));
|
||||
given(request.getHandshakeHeaders()).willReturn(handshakeHeaders);
|
||||
given(request.getHttpRequestHeaders()).willReturn(new HttpHeaders());
|
||||
|
||||
TestXhrTransport transport = new TestXhrTransport();
|
||||
WebSocketHandler handler = mock(WebSocketHandler.class);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.web.socket.sockjs.transport.handler;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
@@ -59,7 +61,7 @@ public class SockJsWebSocketHandlerTests {
|
||||
WebSocketServerSockJsSession session = new WebSocketServerSockJsSession("1", service, handler, null);
|
||||
SockJsWebSocketHandler sockJsHandler = new SockJsWebSocketHandler(service, handler, session);
|
||||
|
||||
assertNull(sockJsHandler.getSubProtocols());
|
||||
assertEquals(Collections.emptyList(), sockJsHandler.getSubProtocols());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user