Merge HandshakeInterceptor-related config updates

This commit is contained in:
Rossen Stoyanchev 2014-07-15 13:32:08 -04:00
commit be4d73e92d
25 changed files with 1464 additions and 1500 deletions

View File

@ -38,13 +38,13 @@ import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
/**
* A {@link BeanDefinitionParser} that provides the configuration for the
* {@code <websocket:handlers/>} namespace element. It registers a Spring MVC
* {@link org.springframework.web.servlet.handler.SimpleUrlHandlerMapping}
* to map HTTP WebSocket handshake requests to
* {@link org.springframework.web.socket.WebSocketHandler}s.
* Parses the configuration for the {@code <websocket:handlers/>} namespace
* element. Registers a Spring MVC {@code SimpleUrlHandlerMapping} to map HTTP
* WebSocket handshake (or SockJS) requests to
* {@link org.springframework.web.socket.WebSocketHandler WebSocketHandler}s.
*
* @author Brian Clozel
* @author Rossen Stoyanchev
* @since 4.0
*/
class HandlersBeanDefinitionParser implements BeanDefinitionParser {
@ -55,11 +55,10 @@ class HandlersBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserCxt) {
Object source = parserCxt.extractSource(element);
public BeanDefinition parse(Element element, ParserContext context) {
Object source = context.extractSource(element);
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
parserCxt.pushContainingComponent(compDefinition);
context.pushContainingComponent(compDefinition);
String orderAttribute = element.getAttribute("order");
int order = orderAttribute.isEmpty() ? DEFAULT_MAPPING_ORDER : Integer.valueOf(orderAttribute);
@ -68,128 +67,106 @@ class HandlersBeanDefinitionParser implements BeanDefinitionParser {
handlerMappingDef.setSource(source);
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
handlerMappingDef.getPropertyValues().add("order", order);
String handlerMappingName = parserCxt.getReaderContext().registerWithGeneratedName(handlerMappingDef);
String handlerMappingName = context.getReaderContext().registerWithGeneratedName(handlerMappingDef);
RuntimeBeanReference handshakeHandler = WebSocketNamespaceUtils.registerHandshakeHandler(element, parserCxt, source);
Element interceptorsElement = DomUtils.getChildElementByTagName(element, "handshake-interceptors");
ManagedList<?> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptorsElement, parserCxt);
RuntimeBeanReference sockJsServiceRef =
WebSocketNamespaceUtils.registerSockJsService(element, SOCK_JS_SCHEDULER_NAME, parserCxt, source);
RuntimeBeanReference sockJsService = WebSocketNamespaceUtils.registerSockJsService(
element, SOCK_JS_SCHEDULER_NAME, context, source);
HandlerMappingStrategy strategy = createHandlerMappingStrategy(sockJsServiceRef, handshakeHandler, interceptors);
HandlerMappingStrategy strategy;
if (sockJsService != null) {
strategy = new SockJsHandlerMappingStrategy(sockJsService);
}
else {
RuntimeBeanReference handshakeHandler = WebSocketNamespaceUtils.registerHandshakeHandler(element, context, source);
Element interceptorsElement = DomUtils.getChildElementByTagName(element, "handshake-interceptors");
ManagedList<?> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptorsElement, context);
strategy = new WebSocketHandlerMappingStrategy(handshakeHandler, interceptors);
}
List<Element> mappingElements = DomUtils.getChildElementsByTagName(element, "mapping");
ManagedMap<String, Object> urlMap = new ManagedMap<String, Object>();
urlMap.setSource(source);
for(Element mappingElement : mappingElements) {
urlMap.putAll(strategy.createMappings(mappingElement, parserCxt));
for(Element mappingElement : DomUtils.getChildElementsByTagName(element, "mapping")) {
strategy.addMapping(mappingElement, urlMap, context);
}
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
parserCxt.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingName));
parserCxt.popAndRegisterContainingComponent();
context.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingName));
context.popAndRegisterContainingComponent();
return null;
}
private interface HandlerMappingStrategy {
public ManagedMap<String, Object> createMappings(Element mappingElement, ParserContext parserContext);
void addMapping(Element mappingElement, ManagedMap<String, Object> map, ParserContext context);
}
private HandlerMappingStrategy createHandlerMappingStrategy(
RuntimeBeanReference sockJsServiceRef, RuntimeBeanReference handshakeHandlerRef,
ManagedList<? extends Object> interceptorsList) {
private static class WebSocketHandlerMappingStrategy implements HandlerMappingStrategy {
if(sockJsServiceRef != null) {
SockJSHandlerMappingStrategy strategy = new SockJSHandlerMappingStrategy();
strategy.setSockJsServiceRef(sockJsServiceRef);
return strategy;
private final RuntimeBeanReference handshakeHandlerReference;
private final ManagedList<?> interceptorsList;
private WebSocketHandlerMappingStrategy(RuntimeBeanReference handshakeHandler, ManagedList<?> interceptors) {
this.handshakeHandlerReference = handshakeHandler;
this.interceptorsList = interceptors;
}
else {
WebSocketHandlerMappingStrategy strategy = new WebSocketHandlerMappingStrategy();
strategy.setHandshakeHandlerReference(handshakeHandlerRef);
strategy.setInterceptorsList(interceptorsList);
return strategy;
}
}
private class WebSocketHandlerMappingStrategy implements HandlerMappingStrategy {
private RuntimeBeanReference handshakeHandlerReference;
private ManagedList<?> interceptorsList;
public void setHandshakeHandlerReference(RuntimeBeanReference handshakeHandlerReference) {
this.handshakeHandlerReference = handshakeHandlerReference;
}
public void setInterceptorsList(ManagedList<?> interceptorsList) { this.interceptorsList = interceptorsList; }
@Override
public ManagedMap<String, Object> createMappings(Element mappingElement, ParserContext parserContext) {
ManagedMap<String, Object> urlMap = new ManagedMap<String, Object>();
Object source = parserContext.extractSource(mappingElement);
String path = mappingElement.getAttribute("path");
List<String> mappings = Arrays.asList(StringUtils.tokenizeToStringArray(path, ","));
RuntimeBeanReference webSocketHandlerReference = new RuntimeBeanReference(mappingElement.getAttribute("handler"));
public void addMapping(Element element, ManagedMap<String, Object> urlMap, ParserContext context) {
String pathAttribute = element.getAttribute("path");
List<String> mappings = Arrays.asList(StringUtils.tokenizeToStringArray(pathAttribute, ","));
RuntimeBeanReference handlerReference = new RuntimeBeanReference(element.getAttribute("handler"));
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, webSocketHandlerReference);
cavs.addIndexedArgumentValue(0, handlerReference);
if(this.handshakeHandlerReference != null) {
cavs.addIndexedArgumentValue(1, this.handshakeHandlerReference);
}
RootBeanDefinition requestHandlerDef = new RootBeanDefinition(WebSocketHttpRequestHandler.class, cavs, null);
requestHandlerDef.setSource(source);
requestHandlerDef.setSource(context.extractSource(element));
requestHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
requestHandlerDef.getPropertyValues().add("handshakeInterceptors", this.interceptorsList);
String requestHandlerName = parserContext.getReaderContext().registerWithGeneratedName(requestHandlerDef);
String requestHandlerName = context.getReaderContext().registerWithGeneratedName(requestHandlerDef);
RuntimeBeanReference requestHandlerRef = new RuntimeBeanReference(requestHandlerName);
for(String mapping : mappings) {
for (String mapping : mappings) {
urlMap.put(mapping, requestHandlerRef);
}
return urlMap;
}
}
private class SockJSHandlerMappingStrategy implements HandlerMappingStrategy {
private static class SockJsHandlerMappingStrategy implements HandlerMappingStrategy {
private RuntimeBeanReference sockJsServiceRef;
private final RuntimeBeanReference sockJsService;
public void setSockJsServiceRef(RuntimeBeanReference sockJsServiceRef) {
this.sockJsServiceRef = sockJsServiceRef;
private SockJsHandlerMappingStrategy(RuntimeBeanReference sockJsService) {
this.sockJsService = sockJsService;
}
@Override
public ManagedMap<String, Object> createMappings(Element mappingElement, ParserContext parserContext) {
ManagedMap<String, Object> urlMap = new ManagedMap<String, Object>();
Object source = parserContext.extractSource(mappingElement);
String pathValue = mappingElement.getAttribute("path");
List<String> mappings = Arrays.asList(StringUtils.tokenizeToStringArray(pathValue, ","));
RuntimeBeanReference webSocketHandlerReference = new RuntimeBeanReference(mappingElement.getAttribute("handler"));
public void addMapping(Element element, ManagedMap<String, Object> urlMap, ParserContext context) {
String pathAttribute = element.getAttribute("path");
List<String> mappings = Arrays.asList(StringUtils.tokenizeToStringArray(pathAttribute, ","));
RuntimeBeanReference handlerReference = new RuntimeBeanReference(element.getAttribute("handler"));
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, this.sockJsServiceRef, "SockJsService");
cavs.addIndexedArgumentValue(1, webSocketHandlerReference, "WebSocketHandler");
cavs.addIndexedArgumentValue(0, this.sockJsService, "SockJsService");
cavs.addIndexedArgumentValue(1, handlerReference, "WebSocketHandler");
RootBeanDefinition requestHandlerDef = new RootBeanDefinition(SockJsHttpRequestHandler.class, cavs, null);
requestHandlerDef.setSource(source);
requestHandlerDef.setSource(context.extractSource(element));
requestHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String requestHandlerName = parserContext.getReaderContext().registerWithGeneratedName(requestHandlerDef);
String requestHandlerName = context.getReaderContext().registerWithGeneratedName(requestHandlerDef);
RuntimeBeanReference requestHandlerRef = new RuntimeBeanReference(requestHandlerName);
for(String path : mappings) {
String pathPattern = path.endsWith("/") ? path + "**" : path + "/**";
for (String mapping : mappings) {
String pathPattern = (mapping.endsWith("/") ? mapping + "**" : mapping + "/**");
urlMap.put(pathPattern, requestHandlerRef);
}
return urlMap;
}
}

View File

@ -50,7 +50,6 @@ import org.springframework.messaging.simp.user.UserDestinationMessageHandler;
import org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler;
import org.springframework.messaging.support.ExecutorSubscribableChannel;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.MimeTypeUtils;
@ -92,7 +91,7 @@ import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
*/
class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
protected static final String SOCKJS_SCHEDULER_BEAN_NAME = "messageBrokerSockJsScheduler";
private static final String SOCKJS_SCHEDULER_BEAN_NAME = "messageBrokerSockJsScheduler";
private static final int DEFAULT_MAPPING_ORDER = 1;
@ -101,142 +100,111 @@ class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserCxt) {
Object source = parserCxt.extractSource(element);
public BeanDefinition parse(Element element, ParserContext context) {
Object source = context.extractSource(element);
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
parserCxt.pushContainingComponent(compDefinition);
context.pushContainingComponent(compDefinition);
String orderAttribute = element.getAttribute("order");
int order = orderAttribute.isEmpty() ? DEFAULT_MAPPING_ORDER : Integer.valueOf(orderAttribute);
ManagedMap<String, Object> urlMap = new ManagedMap<String, Object>();
urlMap.setSource(source);
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
handlerMappingDef.getPropertyValues().add("order", order);
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
registerBeanDef(handlerMappingDef, context, source);
String beanName = "clientInboundChannel";
Element channelElem = DomUtils.getChildElementByTagName(element, "client-inbound-channel");
RuntimeBeanReference clientInChannel = getMessageChannel(beanName, channelElem, parserCxt, source);
RuntimeBeanReference inChannel = getMessageChannel("clientInboundChannel", channelElem, context, source);
beanName = "clientOutboundChannel";
channelElem = DomUtils.getChildElementByTagName(element, "client-outbound-channel");
RuntimeBeanReference clientOutChannel = getMessageChannel(beanName, channelElem, parserCxt, source);
RuntimeBeanReference outChannel = getMessageChannel("clientOutboundChannel", channelElem, context, source);
RootBeanDefinition beanDef = new RootBeanDefinition(DefaultUserSessionRegistry.class);
beanName = registerBeanDef(beanDef, parserCxt, source);
RuntimeBeanReference userSessionRegistry = new RuntimeBeanReference(beanName);
RootBeanDefinition registryBeanDef = new RootBeanDefinition(DefaultUserSessionRegistry.class);
String registryBeanName = registerBeanDef(registryBeanDef, context, source);
RuntimeBeanReference sessionRegistry = new RuntimeBeanReference(registryBeanName);
RuntimeBeanReference subProtocolHandlerDef = registerSubProtocolWebSocketHandler(
element, clientInChannel, clientOutChannel, userSessionRegistry, parserCxt, source);
RuntimeBeanReference subProtoHandler = registerSubProtoHandler(element, inChannel, outChannel,
sessionRegistry, context, source);
for(Element stompEndpointElem : DomUtils.getChildElementsByTagName(element, "stomp-endpoint")) {
RuntimeBeanReference httpRequestHandler = registerHttpRequestHandler(
stompEndpointElem, subProtocolHandlerDef, parserCxt, source);
String pathAttribute = stompEndpointElem.getAttribute("path");
for (Element endpointElem : DomUtils.getChildElementsByTagName(element, "stomp-endpoint")) {
RuntimeBeanReference requestHandler = registerRequestHandler(endpointElem, subProtoHandler, context, source);
String pathAttribute = endpointElem.getAttribute("path");
Assert.state(StringUtils.hasText(pathAttribute), "Invalid <stomp-endpoint> (no path mapping)");
List<String> paths = Arrays.asList(StringUtils.tokenizeToStringArray(pathAttribute, ","));
for(String path : paths) {
path = path.trim();
Assert.state(StringUtils.hasText(path), "Invalid <stomp-endpoint> path attribute: " + pathAttribute);
if (DomUtils.getChildElementByTagName(stompEndpointElem, "sockjs") != null) {
if (DomUtils.getChildElementByTagName(endpointElem, "sockjs") != null) {
path = path.endsWith("/") ? path + "**" : path + "/**";
}
urlMap.put(path, httpRequestHandler);
urlMap.put(path, requestHandler);
}
}
registerBeanDef(handlerMappingDef, parserCxt, source);
beanName = "brokerChannel";
channelElem = DomUtils.getChildElementByTagName(element, "broker-channel");
RuntimeBeanReference brokerChannel = getMessageChannel(beanName, channelElem, parserCxt, source);
RootBeanDefinition brokerDef = registerMessageBroker(element, clientInChannel,
clientOutChannel, brokerChannel, parserCxt, source);
RuntimeBeanReference brokerChannel = getMessageChannel("brokerChannel", channelElem, context, source);
RootBeanDefinition broker = registerMessageBroker(element, inChannel, outChannel, brokerChannel, context, source);
RuntimeBeanReference messageConverter = registerBrokerMessageConverter(element, parserCxt, source);
RuntimeBeanReference converter = registerMessageConverter(element, context, source);
RuntimeBeanReference template = registerMessagingTemplate(element, brokerChannel, converter, context, source);
registerAnnotationMethodMessageHandler(element, inChannel, outChannel,converter, template, context, source);
RuntimeBeanReference messagingTemplate = registerBrokerMessagingTemplate(element, brokerChannel,
messageConverter, parserCxt, source);
registerAnnotationMethodMessageHandler(element, clientInChannel, clientOutChannel,
messageConverter, messagingTemplate, parserCxt, source);
RuntimeBeanReference userDestinationResolver = registerUserDestinationResolver(element,
userSessionRegistry, parserCxt, source);
registerUserDestinationMessageHandler(clientInChannel, clientOutChannel, brokerChannel,
userDestinationResolver, parserCxt, source);
RuntimeBeanReference resolver = registerUserDestinationResolver(element, sessionRegistry, context, source);
registerUserDestinationMessageHandler(inChannel, brokerChannel, resolver, context, source);
Map<String, Object> scopeMap = Collections.<String, Object>singletonMap("websocket", new SimpSessionScope());
RootBeanDefinition scopeConfigurerDef = new RootBeanDefinition(CustomScopeConfigurer.class);
scopeConfigurerDef.getPropertyValues().add("scopes", scopeMap);
registerBeanDefByName("webSocketScopeConfigurer", scopeConfigurerDef, parserCxt, source);
RootBeanDefinition scopeConfigurer = new RootBeanDefinition(CustomScopeConfigurer.class);
scopeConfigurer.getPropertyValues().add("scopes", scopeMap);
registerBeanDefByName("webSocketScopeConfigurer", scopeConfigurer, context, source);
registerWebSocketMessageBrokerStats(subProtocolHandlerDef, brokerDef, clientInChannel,
clientOutChannel, parserCxt, source);
parserCxt.popAndRegisterContainingComponent();
registerWebSocketMessageBrokerStats(subProtoHandler, broker, inChannel, outChannel, context, source);
context.popAndRegisterContainingComponent();
return null;
}
private RuntimeBeanReference getMessageChannel(String channelName, Element channelElement,
ParserContext parserCxt, Object source) {
RootBeanDefinition executorDef = null;
if (channelElement == null) {
executorDef = getDefaultExecutorBeanDefinition(channelName);
private RuntimeBeanReference getMessageChannel(String name, Element element, ParserContext context, Object source) {
RootBeanDefinition executor = null;
if (element == null) {
executor = getDefaultExecutorBeanDefinition(name);
}
else {
Element executor = DomUtils.getChildElementByTagName(channelElement, "executor");
if (executor == null) {
executorDef = getDefaultExecutorBeanDefinition(channelName);
Element executorElem = DomUtils.getChildElementByTagName(element, "executor");
if (executorElem == null) {
executor = getDefaultExecutorBeanDefinition(name);
}
else {
executorDef = new RootBeanDefinition(ThreadPoolTaskExecutor.class);
String attrValue = executor.getAttribute("core-pool-size");
if (!StringUtils.isEmpty(attrValue)) {
executorDef.getPropertyValues().add("corePoolSize", attrValue);
executor = new RootBeanDefinition(ThreadPoolTaskExecutor.class);
if (executorElem.hasAttribute("core-pool-size")) {
executor.getPropertyValues().add("corePoolSize", executorElem.getAttribute("core-pool-size"));
}
attrValue = executor.getAttribute("max-pool-size");
if (!StringUtils.isEmpty(attrValue)) {
executorDef.getPropertyValues().add("maxPoolSize", attrValue);
if (executorElem.hasAttribute("max-pool-size")) {
executor.getPropertyValues().add("maxPoolSize", executorElem.getAttribute("max-pool-size"));
}
attrValue = executor.getAttribute("keep-alive-seconds");
if (!StringUtils.isEmpty(attrValue)) {
executorDef.getPropertyValues().add("keepAliveSeconds", attrValue);
if (executorElem.hasAttribute("keep-alive-seconds")) {
executor.getPropertyValues().add("keepAliveSeconds", executorElem.getAttribute("keep-alive-seconds"));
}
attrValue = executor.getAttribute("queue-capacity");
if (!StringUtils.isEmpty(attrValue)) {
executorDef.getPropertyValues().add("queueCapacity", attrValue);
if (executorElem.hasAttribute("queue-capacity")) {
executor.getPropertyValues().add("queueCapacity", executorElem.getAttribute("queue-capacity"));
}
}
}
ConstructorArgumentValues argValues = new ConstructorArgumentValues();
if (executorDef != null) {
executorDef.getPropertyValues().add("threadNamePrefix", channelName + "-");
String executorName = channelName + "Executor";
registerBeanDefByName(executorName, executorDef, parserCxt, source);
if (executor != null) {
executor.getPropertyValues().add("threadNamePrefix", name + "-");
String executorName = name + "Executor";
registerBeanDefByName(executorName, executor, context, source);
argValues.addIndexedArgumentValue(0, new RuntimeBeanReference(executorName));
}
RootBeanDefinition channelDef = new RootBeanDefinition(ExecutorSubscribableChannel.class, argValues, null);
if (channelElement != null) {
Element interceptorsElement = DomUtils.getChildElementByTagName(channelElement, "interceptors");
ManagedList<?> interceptorList = WebSocketNamespaceUtils.parseBeanSubElements(interceptorsElement, parserCxt);
channelDef.getPropertyValues().add("interceptors", interceptorList);
if (element != null) {
Element interceptorsElement = DomUtils.getChildElementByTagName(element, "interceptors");
ManagedList<?> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptorsElement, context);
channelDef.getPropertyValues().add("interceptors", interceptors);
}
registerBeanDefByName(channelName, channelDef, parserCxt, source);
return new RuntimeBeanReference(channelName);
registerBeanDefByName(name, channelDef, context, source);
return new RuntimeBeanReference(name);
}
private RootBeanDefinition getDefaultExecutorBeanDefinition(String channelName) {
@ -250,81 +218,74 @@ class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
return executorDef;
}
private RuntimeBeanReference registerSubProtocolWebSocketHandler(Element element,
RuntimeBeanReference clientInChannel, RuntimeBeanReference clientOutChannel,
RuntimeBeanReference userSessionRegistry, ParserContext parserCxt, Object source) {
private RuntimeBeanReference registerSubProtoHandler(Element element, RuntimeBeanReference inChannel,
RuntimeBeanReference outChannel, RuntimeBeanReference registry, ParserContext context, Object source) {
RootBeanDefinition stompHandlerDef = new RootBeanDefinition(StompSubProtocolHandler.class);
stompHandlerDef.getPropertyValues().add("userSessionRegistry", userSessionRegistry);
registerBeanDef(stompHandlerDef, parserCxt, source);
stompHandlerDef.getPropertyValues().add("userSessionRegistry", registry);
registerBeanDef(stompHandlerDef, context, source);
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, clientInChannel);
cavs.addIndexedArgumentValue(1, clientOutChannel);
cavs.addIndexedArgumentValue(0, inChannel);
cavs.addIndexedArgumentValue(1, outChannel);
RootBeanDefinition subProtocolWshDef = new RootBeanDefinition(SubProtocolWebSocketHandler.class, cavs, null);
subProtocolWshDef.getPropertyValues().addPropertyValue("protocolHandlers", stompHandlerDef);
String subProtocolWshName = registerBeanDef(subProtocolWshDef, parserCxt, source);
RootBeanDefinition beanDef = new RootBeanDefinition(SubProtocolWebSocketHandler.class, cavs, null);
beanDef.getPropertyValues().addPropertyValue("protocolHandlers", stompHandlerDef);
Element transportElem = DomUtils.getChildElementByTagName(element, "transport");
if (transportElem != null) {
String messageSize = transportElem.getAttribute("message-size");
if (messageSize != null) {
stompHandlerDef.getPropertyValues().add("messageSizeLimit", messageSize);
if (transportElem.hasAttribute("message-size")) {
stompHandlerDef.getPropertyValues().add("messageSizeLimit", transportElem.getAttribute("message-size"));
}
String sendTimeLimit = transportElem.getAttribute("send-timeout");
if (sendTimeLimit != null) {
subProtocolWshDef.getPropertyValues().add("sendTimeLimit", sendTimeLimit);
if (transportElem.hasAttribute("send-timeout")) {
beanDef.getPropertyValues().add("sendTimeLimit", transportElem.getAttribute("send-timeout"));
}
String sendBufferSizeLimit = transportElem.getAttribute("send-buffer-size");
if (sendBufferSizeLimit != null) {
subProtocolWshDef.getPropertyValues().add("sendBufferSizeLimit", sendBufferSizeLimit);
if (transportElem.hasAttribute("send-buffer-size")) {
beanDef.getPropertyValues().add("sendBufferSizeLimit", transportElem.getAttribute("send-buffer-size"));
}
}
return new RuntimeBeanReference(subProtocolWshName);
return new RuntimeBeanReference(registerBeanDef(beanDef, context, source));
}
private RuntimeBeanReference registerHttpRequestHandler(Element stompEndpointElement,
RuntimeBeanReference subProtocolWebSocketHandler, ParserContext parserCxt, Object source) {
private RuntimeBeanReference registerRequestHandler(Element element, RuntimeBeanReference subProtoHandler,
ParserContext context, Object source) {
RootBeanDefinition httpRequestHandlerDef;
RootBeanDefinition beanDef;
RuntimeBeanReference sockJsService = WebSocketNamespaceUtils.registerSockJsService(
stompEndpointElement, SOCKJS_SCHEDULER_BEAN_NAME, parserCxt, source);
element, SOCKJS_SCHEDULER_BEAN_NAME, context, source);
if (sockJsService != null) {
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, sockJsService);
cavs.addIndexedArgumentValue(1, subProtocolWebSocketHandler);
httpRequestHandlerDef = new RootBeanDefinition(SockJsHttpRequestHandler.class, cavs, null);
cavs.addIndexedArgumentValue(1, subProtoHandler);
beanDef = new RootBeanDefinition(SockJsHttpRequestHandler.class, cavs, null);
}
else {
RuntimeBeanReference handshakeHandler =
WebSocketNamespaceUtils.registerHandshakeHandler(stompEndpointElement, parserCxt, source);
RuntimeBeanReference handshakeHandler = WebSocketNamespaceUtils.registerHandshakeHandler(element, context, source);
Element interceptorsElement = DomUtils.getChildElementByTagName(element, "handshake-interceptors");
ManagedList<?> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptorsElement, context);
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, subProtocolWebSocketHandler);
if(handshakeHandler != null) {
cavs.addIndexedArgumentValue(0, subProtoHandler);
if (handshakeHandler != null) {
cavs.addIndexedArgumentValue(1, handshakeHandler);
}
httpRequestHandlerDef = new RootBeanDefinition(WebSocketHttpRequestHandler.class, cavs, null);
beanDef = new RootBeanDefinition(WebSocketHttpRequestHandler.class, cavs, null);
beanDef.getPropertyValues().add("handshakeInterceptors", interceptors);
}
String httpRequestHandlerBeanName = registerBeanDef(httpRequestHandlerDef, parserCxt, source);
return new RuntimeBeanReference(httpRequestHandlerBeanName);
return new RuntimeBeanReference(registerBeanDef(beanDef, context, source));
}
private RootBeanDefinition registerMessageBroker(Element messageBrokerElement, RuntimeBeanReference clientInChannelDef,
RuntimeBeanReference clientOutChannelDef, RuntimeBeanReference brokerChannelDef,
ParserContext parserCxt, Object source) {
private RootBeanDefinition registerMessageBroker(Element messageBrokerElement, RuntimeBeanReference inChannel,
RuntimeBeanReference outChannel, RuntimeBeanReference brokerChannel, ParserContext context, Object source) {
Element simpleBrokerElem = DomUtils.getChildElementByTagName(messageBrokerElement, "simple-broker");
Element brokerRelayElem = DomUtils.getChildElementByTagName(messageBrokerElement, "stomp-broker-relay");
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, clientInChannelDef);
cavs.addIndexedArgumentValue(1, clientOutChannelDef);
cavs.addIndexedArgumentValue(2, brokerChannelDef);
cavs.addIndexedArgumentValue(0, inChannel);
cavs.addIndexedArgumentValue(1, outChannel);
cavs.addIndexedArgumentValue(2, brokerChannel);
RootBeanDefinition brokerDef;
if (simpleBrokerElem != null) {
@ -332,213 +293,177 @@ class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
cavs.addIndexedArgumentValue(3, Arrays.asList(StringUtils.tokenizeToStringArray(prefix, ",")));
brokerDef = new RootBeanDefinition(SimpleBrokerMessageHandler.class, cavs, null);
if (messageBrokerElement.hasAttribute("path-matcher")) {
brokerDef.getPropertyValues().add("pathMatcher",
new RuntimeBeanReference(messageBrokerElement.getAttribute("path-matcher")));
String pathMatcherRef = messageBrokerElement.getAttribute("path-matcher");
brokerDef.getPropertyValues().add("pathMatcher", new RuntimeBeanReference(pathMatcherRef));
}
}
else if (brokerRelayElem != null) {
String prefix = brokerRelayElem.getAttribute("prefix");
cavs.addIndexedArgumentValue(3, Arrays.asList(StringUtils.tokenizeToStringArray(prefix, ",")));
MutablePropertyValues mpvs = new MutablePropertyValues();
String relayHost = brokerRelayElem.getAttribute("relay-host");
if(!relayHost.isEmpty()) {
mpvs.add("relayHost",relayHost);
MutablePropertyValues values = new MutablePropertyValues();
if (brokerRelayElem.hasAttribute("relay-host")) {
values.add("relayHost", brokerRelayElem.getAttribute("relay-host"));
}
String relayPort = brokerRelayElem.getAttribute("relay-port");
if(!relayPort.isEmpty()) {
mpvs.add("relayPort", Integer.valueOf(relayPort));
if (brokerRelayElem.hasAttribute("relay-port")) {
values.add("relayPort", brokerRelayElem.getAttribute("relay-port"));
}
String attrValue = brokerRelayElem.getAttribute("client-login");
if(!attrValue.isEmpty()) {
mpvs.add("clientLogin",attrValue);
if (brokerRelayElem.hasAttribute("client-login")) {
values.add("clientLogin", brokerRelayElem.getAttribute("client-login"));
}
attrValue = brokerRelayElem.getAttribute("client-passcode");
if(!attrValue.isEmpty()) {
mpvs.add("clientPasscode", attrValue);
if (brokerRelayElem.hasAttribute("client-passcode")) {
values.add("clientPasscode", brokerRelayElem.getAttribute("client-passcode"));
}
attrValue = brokerRelayElem.getAttribute("system-login");
if(!attrValue.isEmpty()) {
mpvs.add("systemLogin",attrValue);
if (brokerRelayElem.hasAttribute("system-login")) {
values.add("systemLogin", brokerRelayElem.getAttribute("system-login"));
}
attrValue = brokerRelayElem.getAttribute("system-passcode");
if(!attrValue.isEmpty()) {
mpvs.add("systemPasscode", attrValue);
if (brokerRelayElem.hasAttribute("system-passcode")) {
values.add("systemPasscode", brokerRelayElem.getAttribute("system-passcode"));
}
attrValue = brokerRelayElem.getAttribute("heartbeat-send-interval");
if(!attrValue.isEmpty()) {
mpvs.add("systemHeartbeatSendInterval", Long.parseLong(attrValue));
if (brokerRelayElem.hasAttribute("heartbeat-send-interval")) {
values.add("systemHeartbeatSendInterval", brokerRelayElem.getAttribute("heartbeat-send-interval"));
}
attrValue = brokerRelayElem.getAttribute("heartbeat-receive-interval");
if(!attrValue.isEmpty()) {
mpvs.add("systemHeartbeatReceiveInterval", Long.parseLong(attrValue));
if (brokerRelayElem.hasAttribute("heartbeat-receive-interval")) {
values.add("systemHeartbeatReceiveInterval", brokerRelayElem.getAttribute("heartbeat-receive-interval"));
}
attrValue = brokerRelayElem.getAttribute("virtual-host");
if(!attrValue.isEmpty()) {
mpvs.add("virtualHost", attrValue);
if (brokerRelayElem.hasAttribute("virtual-host")) {
values.add("virtualHost", brokerRelayElem.getAttribute("virtual-host"));
}
Class<?> handlerType = StompBrokerRelayMessageHandler.class;
brokerDef = new RootBeanDefinition(handlerType, cavs, mpvs);
brokerDef = new RootBeanDefinition(handlerType, cavs, values);
}
else {
// Should not happen
throw new IllegalStateException("Neither <simple-broker> nor <stomp-broker-relay> elements found.");
}
registerBeanDef(brokerDef, parserCxt, source);
registerBeanDef(brokerDef, context, source);
return brokerDef;
}
private RuntimeBeanReference registerBrokerMessageConverter(Element element,
ParserContext parserCxt, Object source) {
private RuntimeBeanReference registerMessageConverter(Element element, ParserContext context, Object source) {
Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters");
ManagedList<? super Object> convertersDef = new ManagedList<Object>();
ManagedList<? super Object> converters = new ManagedList<Object>();
if (convertersElement != null) {
convertersDef.setSource(source);
converters.setSource(source);
for (Element beanElement : DomUtils.getChildElementsByTagName(convertersElement, "bean", "ref")) {
Object object = parserCxt.getDelegate().parsePropertySubElement(beanElement, null);
convertersDef.add(object);
Object object = context.getDelegate().parsePropertySubElement(beanElement, null);
converters.add(object);
}
}
if (convertersElement == null || Boolean.valueOf(convertersElement.getAttribute("register-defaults"))) {
convertersDef.setSource(source);
convertersDef.add(new RootBeanDefinition(StringMessageConverter.class));
convertersDef.add(new RootBeanDefinition(ByteArrayMessageConverter.class));
converters.setSource(source);
converters.add(new RootBeanDefinition(StringMessageConverter.class));
converters.add(new RootBeanDefinition(ByteArrayMessageConverter.class));
if (jackson2Present) {
RootBeanDefinition jacksonConverterDef = new RootBeanDefinition(MappingJackson2MessageConverter.class);
RootBeanDefinition resolverDef = new RootBeanDefinition(DefaultContentTypeResolver.class);
resolverDef.getPropertyValues().add("defaultMimeType", MimeTypeUtils.APPLICATION_JSON);
jacksonConverterDef.getPropertyValues().add("contentTypeResolver", resolverDef);
convertersDef.add(jacksonConverterDef);
converters.add(jacksonConverterDef);
}
}
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, convertersDef);
cavs.addIndexedArgumentValue(0, converters);
RootBeanDefinition messageConverterDef = new RootBeanDefinition(CompositeMessageConverter.class, cavs, null);
return new RuntimeBeanReference(registerBeanDef(messageConverterDef, parserCxt, source));
return new RuntimeBeanReference(registerBeanDef(messageConverterDef, context, source));
}
private RuntimeBeanReference registerBrokerMessagingTemplate(
Element element, RuntimeBeanReference brokerChannelDef, RuntimeBeanReference messageConverterRef,
ParserContext parserCxt, Object source) {
private RuntimeBeanReference registerMessagingTemplate(Element element, RuntimeBeanReference brokerChannel,
RuntimeBeanReference messageConverter, ParserContext context, Object source) {
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, brokerChannelDef);
RootBeanDefinition messagingTemplateDef = new RootBeanDefinition(SimpMessagingTemplate.class,cavs, null);
String userDestinationPrefixAttribute = element.getAttribute("user-destination-prefix");
if(!userDestinationPrefixAttribute.isEmpty()) {
messagingTemplateDef.getPropertyValues().add("userDestinationPrefix", userDestinationPrefixAttribute);
cavs.addIndexedArgumentValue(0, brokerChannel);
RootBeanDefinition beanDef = new RootBeanDefinition(SimpMessagingTemplate.class,cavs, null);
if(element.hasAttribute("user-destination-prefix")) {
beanDef.getPropertyValues().add("userDestinationPrefix", element.getAttribute("user-destination-prefix"));
}
messagingTemplateDef.getPropertyValues().add("messageConverter", messageConverterRef);
return new RuntimeBeanReference(registerBeanDef(messagingTemplateDef,parserCxt, source));
beanDef.getPropertyValues().add("messageConverter", messageConverter);
return new RuntimeBeanReference(registerBeanDef(beanDef,context, source));
}
private void registerAnnotationMethodMessageHandler(Element messageBrokerElement,
RuntimeBeanReference clientInChannelDef, RuntimeBeanReference clientOutChannelDef,
RuntimeBeanReference brokerMessageConverterRef, RuntimeBeanReference brokerMessagingTemplateRef,
ParserContext parserCxt, Object source) {
String appDestPrefix = messageBrokerElement.getAttribute("application-destination-prefix");
RuntimeBeanReference inChannel, RuntimeBeanReference outChannel,
RuntimeBeanReference converter, RuntimeBeanReference messagingTemplate,
ParserContext context, Object source) {
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, clientInChannelDef);
cavs.addIndexedArgumentValue(1, clientOutChannelDef);
cavs.addIndexedArgumentValue(2, brokerMessagingTemplateRef);
cavs.addIndexedArgumentValue(0, inChannel);
cavs.addIndexedArgumentValue(1, outChannel);
cavs.addIndexedArgumentValue(2, messagingTemplate);
MutablePropertyValues mpvs = new MutablePropertyValues();
mpvs.add("destinationPrefixes",Arrays.asList(StringUtils.tokenizeToStringArray(appDestPrefix, ",")));
mpvs.add("messageConverter", brokerMessageConverterRef);
MutablePropertyValues values = new MutablePropertyValues();
String prefixAttribute = messageBrokerElement.getAttribute("application-destination-prefix");
values.add("destinationPrefixes", Arrays.asList(StringUtils.tokenizeToStringArray(prefixAttribute, ",")));
values.add("messageConverter", converter);
RootBeanDefinition beanDef = new RootBeanDefinition(SimpAnnotationMethodMessageHandler.class, cavs, mpvs);
RootBeanDefinition beanDef = new RootBeanDefinition(SimpAnnotationMethodMessageHandler.class, cavs, values);
if (messageBrokerElement.hasAttribute("path-matcher")) {
beanDef.getPropertyValues().add("pathMatcher",
new RuntimeBeanReference(messageBrokerElement.getAttribute("path-matcher")));
String pathMatcherRef = messageBrokerElement.getAttribute("path-matcher");
beanDef.getPropertyValues().add("pathMatcher", new RuntimeBeanReference(pathMatcherRef));
}
registerBeanDef(beanDef, parserCxt, source);
registerBeanDef(beanDef, context, source);
}
private RuntimeBeanReference registerUserDestinationResolver(Element messageBrokerElement,
RuntimeBeanReference userSessionRegistry, ParserContext parserCxt, Object source) {
private RuntimeBeanReference registerUserDestinationResolver(Element brokerElem,
RuntimeBeanReference userSessionRegistry, ParserContext context, Object source) {
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, userSessionRegistry);
RootBeanDefinition userDestinationResolverDef =
new RootBeanDefinition(DefaultUserDestinationResolver.class, cavs, null);
String prefix = messageBrokerElement.getAttribute("user-destination-prefix");
if (!prefix.isEmpty()) {
userDestinationResolverDef.getPropertyValues().add("userDestinationPrefix", prefix);
RootBeanDefinition beanDef = new RootBeanDefinition(DefaultUserDestinationResolver.class, cavs, null);
if (brokerElem.hasAttribute("user-destination-prefix")) {
beanDef.getPropertyValues().add("userDestinationPrefix", brokerElem.getAttribute("user-destination-prefix"));
}
String userDestinationResolverName = registerBeanDef(userDestinationResolverDef, parserCxt, source);
return new RuntimeBeanReference(userDestinationResolverName);
return new RuntimeBeanReference(registerBeanDef(beanDef, context, source));
}
private RuntimeBeanReference registerUserDestinationMessageHandler(RuntimeBeanReference clientInChannelDef,
RuntimeBeanReference clientOutChannelDef, RuntimeBeanReference brokerChannelDef,
RuntimeBeanReference userDestinationResolverRef, ParserContext parserCxt, Object source) {
private RuntimeBeanReference registerUserDestinationMessageHandler(RuntimeBeanReference inChannel,
RuntimeBeanReference brokerChannel, RuntimeBeanReference userDestinationResolver,
ParserContext context, Object source) {
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addIndexedArgumentValue(0, clientInChannelDef);
cavs.addIndexedArgumentValue(1, brokerChannelDef);
cavs.addIndexedArgumentValue(2, userDestinationResolverRef);
RootBeanDefinition userDestinationMessageHandlerDef =
new RootBeanDefinition(UserDestinationMessageHandler.class, cavs, null);
String userDestinationMessageHandleName = registerBeanDef(userDestinationMessageHandlerDef, parserCxt, source);
return new RuntimeBeanReference(userDestinationMessageHandleName);
cavs.addIndexedArgumentValue(0, inChannel);
cavs.addIndexedArgumentValue(1, brokerChannel);
cavs.addIndexedArgumentValue(2, userDestinationResolver);
RootBeanDefinition beanDef = new RootBeanDefinition(UserDestinationMessageHandler.class, cavs, null);
return new RuntimeBeanReference(registerBeanDef(beanDef, context, source));
}
private void registerWebSocketMessageBrokerStats(RuntimeBeanReference subProtocolHandlerDef,
RootBeanDefinition brokerDef, RuntimeBeanReference clientInChannel,
RuntimeBeanReference clientOutChannel, ParserContext parserCxt, Object source) {
private void registerWebSocketMessageBrokerStats(RuntimeBeanReference subProtoHandler,
RootBeanDefinition broker, RuntimeBeanReference inChannel, RuntimeBeanReference outChannel,
ParserContext context, Object source) {
RootBeanDefinition statsDef = new RootBeanDefinition(WebSocketMessageBrokerStats.class);
statsDef.getPropertyValues().add("subProtocolWebSocketHandler", subProtocolHandlerDef);
RootBeanDefinition beanDef = new RootBeanDefinition(WebSocketMessageBrokerStats.class);
beanDef.getPropertyValues().add("subProtocolWebSocketHandler", subProtoHandler);
if (StompBrokerRelayMessageHandler.class.equals(brokerDef.getBeanClass())) {
statsDef.getPropertyValues().add("stompBrokerRelay", brokerDef);
if (StompBrokerRelayMessageHandler.class.equals(broker.getBeanClass())) {
beanDef.getPropertyValues().add("stompBrokerRelay", broker);
}
String beanName = clientInChannel.getBeanName() + "Executor";
if (parserCxt.getRegistry().containsBeanDefinition(beanName)) {
BeanDefinition beanDef = parserCxt.getRegistry().getBeanDefinition(beanName);
statsDef.getPropertyValues().add("inboundChannelExecutor", beanDef);
String name = inChannel.getBeanName() + "Executor";
if (context.getRegistry().containsBeanDefinition(name)) {
beanDef.getPropertyValues().add("inboundChannelExecutor", context.getRegistry().getBeanDefinition(name));
}
beanName = clientOutChannel.getBeanName() + "Executor";
if (parserCxt.getRegistry().containsBeanDefinition(beanName)) {
BeanDefinition beanDef = parserCxt.getRegistry().getBeanDefinition(beanName);
statsDef.getPropertyValues().add("outboundChannelExecutor", beanDef);
name = outChannel.getBeanName() + "Executor";
if (context.getRegistry().containsBeanDefinition(name)) {
beanDef.getPropertyValues().add("outboundChannelExecutor", context.getRegistry().getBeanDefinition(name));
}
beanName = SOCKJS_SCHEDULER_BEAN_NAME;
if (parserCxt.getRegistry().containsBeanDefinition(beanName)) {
BeanDefinition beanDef = parserCxt.getRegistry().getBeanDefinition(beanName);
statsDef.getPropertyValues().add("sockJsTaskScheduler", beanDef);
name = SOCKJS_SCHEDULER_BEAN_NAME;
if (context.getRegistry().containsBeanDefinition(name)) {
beanDef.getPropertyValues().add("sockJsTaskScheduler", context.getRegistry().getBeanDefinition(name));
}
registerBeanDefByName("webSocketMessageBrokerStats", statsDef, parserCxt, source);
registerBeanDefByName("webSocketMessageBrokerStats", beanDef, context, source);
}
private static String registerBeanDef(RootBeanDefinition beanDef, ParserContext parserCxt, Object source) {
String beanName = parserCxt.getReaderContext().generateBeanName(beanDef);
registerBeanDefByName(beanName, beanDef, parserCxt, source);
return beanName;
private static String registerBeanDef(RootBeanDefinition beanDef, ParserContext context, Object source) {
String name = context.getReaderContext().generateBeanName(beanDef);
registerBeanDefByName(name, beanDef, context, source);
return name;
}
private static void registerBeanDefByName(String beanName, RootBeanDefinition beanDef,
ParserContext parserCxt, Object source) {
private static void registerBeanDefByName(String name, RootBeanDefinition beanDef, ParserContext context, Object source) {
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserCxt.getRegistry().registerBeanDefinition(beanName, beanDef);
parserCxt.registerComponent(new BeanComponentDefinition(beanDef, beanName));
context.getRegistry().registerBeanDefinition(name, beanDef);
context.registerComponent(new BeanComponentDefinition(beanDef, name));
}
}

View File

@ -31,8 +31,6 @@ import org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsSe
import org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService;
import org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler;
import java.util.concurrent.ScheduledThreadPoolExecutor;
/**
* Provides utility methods for parsing common WebSocket XML namespace elements.
*
@ -43,7 +41,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
class WebSocketNamespaceUtils {
public static RuntimeBeanReference registerHandshakeHandler(Element element, ParserContext parserContext, Object source) {
public static RuntimeBeanReference registerHandshakeHandler(Element element, ParserContext context, Object source) {
RuntimeBeanReference handlerRef;
Element handlerElem = DomUtils.getChildElementByTagName(element, "handshake-handler");
if (handlerElem != null) {
@ -53,19 +51,19 @@ class WebSocketNamespaceUtils {
RootBeanDefinition defaultHandlerDef = new RootBeanDefinition(DefaultHandshakeHandler.class);
defaultHandlerDef.setSource(source);
defaultHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String handlerName = parserContext.getReaderContext().registerWithGeneratedName(defaultHandlerDef);
String handlerName = context.getReaderContext().registerWithGeneratedName(defaultHandlerDef);
handlerRef = new RuntimeBeanReference(handlerName);
}
return handlerRef;
}
public static RuntimeBeanReference registerSockJsService(Element element, String sockJsSchedulerName,
ParserContext parserContext, Object source) {
ParserContext context, Object source) {
Element sockJsElement = DomUtils.getChildElementByTagName(element, "sockjs");
if (sockJsElement != null) {
Element handshakeHandlerElement = DomUtils.getChildElementByTagName(element, "handshake-handler");
Element handshakeHandler = DomUtils.getChildElementByTagName(element, "handshake-handler");
RootBeanDefinition sockJsServiceDef = new RootBeanDefinition(DefaultSockJsService.class);
sockJsServiceDef.setSource(source);
@ -76,26 +74,31 @@ class WebSocketNamespaceUtils {
scheduler = new RuntimeBeanReference(customTaskSchedulerName);
}
else {
scheduler = registerSockJsTaskScheduler(sockJsSchedulerName, parserContext, source);
scheduler = registerSockJsScheduler(sockJsSchedulerName, context, source);
}
sockJsServiceDef.getConstructorArgumentValues().addIndexedArgumentValue(0, scheduler);
Element transportHandlersElement = DomUtils.getChildElementByTagName(sockJsElement, "transport-handlers");
if (transportHandlersElement != null) {
String registerDefaultsAttribute = transportHandlersElement.getAttribute("register-defaults");
if (registerDefaultsAttribute.equals("false")) {
String registerDefaults = transportHandlersElement.getAttribute("register-defaults");
if (registerDefaults.equals("false")) {
sockJsServiceDef.setBeanClass(TransportHandlingSockJsService.class);
}
ManagedList<?> transportHandlersList = parseBeanSubElements(transportHandlersElement, parserContext);
sockJsServiceDef.getConstructorArgumentValues().addIndexedArgumentValue(1, transportHandlersList);
} else if(handshakeHandlerElement != null){
RuntimeBeanReference handshakeHandlerRef = new RuntimeBeanReference(handshakeHandlerElement.getAttribute("ref"));
RootBeanDefinition wsTransportHandler = new RootBeanDefinition(WebSocketTransportHandler.class);
wsTransportHandler.setSource(source);
wsTransportHandler.getConstructorArgumentValues().addIndexedArgumentValue(0, handshakeHandlerRef);
sockJsServiceDef.getConstructorArgumentValues().addIndexedArgumentValue(1, wsTransportHandler);
ManagedList<?> transportHandlers = parseBeanSubElements(transportHandlersElement, context);
sockJsServiceDef.getConstructorArgumentValues().addIndexedArgumentValue(1, transportHandlers);
}
else if (handshakeHandler != null) {
RuntimeBeanReference handshakeHandlerRef = new RuntimeBeanReference(handshakeHandler.getAttribute("ref"));
RootBeanDefinition transportHandler = new RootBeanDefinition(WebSocketTransportHandler.class);
transportHandler.setSource(source);
transportHandler.getConstructorArgumentValues().addIndexedArgumentValue(0, handshakeHandlerRef);
sockJsServiceDef.getConstructorArgumentValues().addIndexedArgumentValue(1, transportHandler);
}
Element interceptorsElement = DomUtils.getChildElementByTagName(element, "handshake-interceptors");
ManagedList<?> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptorsElement, context);
sockJsServiceDef.getPropertyValues().add("handshakeInterceptors", interceptors);
String attrValue = sockJsElement.getAttribute("name");
if (!attrValue.isEmpty()) {
@ -125,43 +128,35 @@ class WebSocketNamespaceUtils {
if (!attrValue.isEmpty()) {
sockJsServiceDef.getPropertyValues().add("heartbeatTime", Long.valueOf(attrValue));
}
sockJsServiceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sockJsServiceName = parserContext.getReaderContext().registerWithGeneratedName(sockJsServiceDef);
String sockJsServiceName = context.getReaderContext().registerWithGeneratedName(sockJsServiceDef);
return new RuntimeBeanReference(sockJsServiceName);
}
return null;
}
private static RuntimeBeanReference registerSockJsTaskScheduler(String schedulerName,
ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(schedulerName)) {
private static RuntimeBeanReference registerSockJsScheduler(String schedulerName, ParserContext context, Object source) {
if (!context.getRegistry().containsBeanDefinition(schedulerName)) {
RootBeanDefinition taskSchedulerDef = new RootBeanDefinition(ThreadPoolTaskScheduler.class);
taskSchedulerDef.setSource(source);
taskSchedulerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
taskSchedulerDef.getPropertyValues().add("poolSize", Runtime.getRuntime().availableProcessors());
taskSchedulerDef.getPropertyValues().add("threadNamePrefix", schedulerName + "-");
taskSchedulerDef.getPropertyValues().add("removeOnCancelPolicy", true);
parserContext.getRegistry().registerBeanDefinition(schedulerName, taskSchedulerDef);
parserContext.registerComponent(new BeanComponentDefinition(taskSchedulerDef, schedulerName));
context.getRegistry().registerBeanDefinition(schedulerName, taskSchedulerDef);
context.registerComponent(new BeanComponentDefinition(taskSchedulerDef, schedulerName));
}
return new RuntimeBeanReference(schedulerName);
}
public static ManagedList<? super Object> parseBeanSubElements(Element parentElement, ParserContext parserContext) {
public static ManagedList<? super Object> parseBeanSubElements(Element parentElement, ParserContext context) {
ManagedList<? super Object> beans = new ManagedList<Object>();
if (parentElement != null) {
beans.setSource(parserContext.extractSource(parentElement));
for (Element beanElement : DomUtils.getChildElementsByTagName(parentElement, new String[] { "bean", "ref" })) {
Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
beans.add(object);
beans.setSource(context.extractSource(parentElement));
for (Element beanElement : DomUtils.getChildElementsByTagName(parentElement, new String[] {"bean", "ref"})) {
beans.add(context.getDelegate().parsePropertySubElement(beanElement, null));
}
}
return beans;
}

View File

@ -38,15 +38,15 @@ import org.springframework.web.socket.sockjs.transport.handler.WebSocketTranspor
*/
public abstract class AbstractWebSocketHandlerRegistration<M> implements WebSocketHandlerRegistration {
private MultiValueMap<WebSocketHandler, String> handlerMap = new LinkedMultiValueMap<WebSocketHandler, String>();
private final TaskScheduler sockJsTaskScheduler;
private HandshakeInterceptor[] interceptors;
private MultiValueMap<WebSocketHandler, String> handlerMap = new LinkedMultiValueMap<WebSocketHandler, String>();
private HandshakeHandler handshakeHandler;
private SockJsServiceRegistration sockJsServiceRegistration;
private HandshakeInterceptor[] interceptors;
private final TaskScheduler sockJsTaskScheduler;
private SockJsServiceRegistration sockJsServiceRegistration;
public AbstractWebSocketHandlerRegistration(TaskScheduler defaultTaskScheduler) {
@ -68,8 +68,8 @@ public abstract class AbstractWebSocketHandlerRegistration<M> implements WebSock
return this;
}
public HandshakeHandler getHandshakeHandler() {
return handshakeHandler;
protected HandshakeHandler getHandshakeHandler() {
return this.handshakeHandler;
}
@Override
@ -82,30 +82,21 @@ public abstract class AbstractWebSocketHandlerRegistration<M> implements WebSock
return this.interceptors;
}
/**
* @param interceptors the interceptors to set
*/
public void setInterceptors(HandshakeInterceptor[] interceptors) {
this.interceptors = interceptors;
}
@Override
public SockJsServiceRegistration withSockJS() {
this.sockJsServiceRegistration = new SockJsServiceRegistration(this.sockJsTaskScheduler);
this.sockJsServiceRegistration.setInterceptors(this.interceptors);
if (this.interceptors != null) {
this.sockJsServiceRegistration.setInterceptors(this.interceptors);
}
if (this.handshakeHandler != null) {
WebSocketTransportHandler transportHandler = new WebSocketTransportHandler(this.handshakeHandler);
this.sockJsServiceRegistration.setTransportHandlerOverrides(transportHandler);
}
return this.sockJsServiceRegistration;
}
public final M getMappings() {
protected final M getMappings() {
M mappings = createMappings();
if (this.sockJsServiceRegistration != null) {
SockJsService sockJsService = this.sockJsServiceRegistration.getSockJsService();
for (WebSocketHandler wsHandler : this.handlerMap.keySet()) {

View File

@ -17,6 +17,7 @@
package org.springframework.web.socket.config.annotation;
import org.springframework.web.socket.server.HandshakeHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
/**
* A contract for configuring a STOMP over WebSocket endpoint.
@ -36,4 +37,9 @@ public interface StompWebSocketEndpointRegistration {
*/
StompWebSocketEndpointRegistration setHandshakeHandler(HandshakeHandler handshakeHandler);
/**
* Configure the HandshakeInterceptor's to use.
*/
StompWebSocketEndpointRegistration addInterceptors(HandshakeInterceptor... interceptors);
}

View File

@ -23,11 +23,14 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
import org.springframework.web.socket.sockjs.SockJsService;
import org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler;
import java.util.Arrays;
/**
* An abstract base class class for configuring STOMP over WebSocket/SockJS endpoints.
*
@ -44,6 +47,8 @@ public class WebMvcStompWebSocketEndpointRegistration implements StompWebSocketE
private HandshakeHandler handshakeHandler;
private HandshakeInterceptor[] interceptors;
private StompSockJsServiceRegistration registration;
@ -58,9 +63,6 @@ public class WebMvcStompWebSocketEndpointRegistration implements StompWebSocketE
this.sockJsTaskScheduler = sockJsTaskScheduler;
}
/**
* Provide a custom or pre-configured {@link HandshakeHandler}.
*/
@Override
public StompWebSocketEndpointRegistration setHandshakeHandler(HandshakeHandler handshakeHandler) {
Assert.notNull(handshakeHandler, "'handshakeHandler' must not be null");
@ -68,12 +70,22 @@ public class WebMvcStompWebSocketEndpointRegistration implements StompWebSocketE
return this;
}
/**
* Enable SockJS fallback options.
*/
@Override
public StompWebSocketEndpointRegistration addInterceptors(HandshakeInterceptor... interceptors) {
this.interceptors = interceptors;
return this;
}
protected HandshakeInterceptor[] getInterceptors() {
return this.interceptors;
}
@Override
public SockJsServiceRegistration withSockJS() {
this.registration = new StompSockJsServiceRegistration(this.sockJsTaskScheduler);
if (this.interceptors != null) {
this.registration.setInterceptors(this.interceptors);
}
if (this.handshakeHandler != null) {
WebSocketTransportHandler transportHandler = new WebSocketTransportHandler(this.handshakeHandler);
this.registration.setTransportHandlerOverrides(transportHandler);
@ -93,9 +105,16 @@ public class WebMvcStompWebSocketEndpointRegistration implements StompWebSocketE
}
else {
for (String path : this.paths) {
WebSocketHttpRequestHandler handler = (this.handshakeHandler != null) ?
new WebSocketHttpRequestHandler(this.webSocketHandler, this.handshakeHandler) :
new WebSocketHttpRequestHandler(this.webSocketHandler);
WebSocketHttpRequestHandler handler;
if (this.handshakeHandler != null) {
handler = new WebSocketHttpRequestHandler(this.webSocketHandler, this.handshakeHandler);
}
else {
handler = new WebSocketHttpRequestHandler(this.webSocketHandler);
}
if (this.interceptors != null) {
handler.setHandshakeInterceptors(Arrays.asList(this.interceptors));
}
mappings.add(handler, path);
}
}

View File

@ -34,16 +34,16 @@ public interface WebSocketHandlerRegistration {
*/
WebSocketHandlerRegistration addHandler(WebSocketHandler handler, String... paths);
/**
* Configure interceptors for the handshake request.
*/
WebSocketHandlerRegistration addInterceptors(HandshakeInterceptor... interceptors);
/**
* Configure the HandshakeHandler to use.
*/
WebSocketHandlerRegistration setHandshakeHandler(HandshakeHandler handshakeHandler);
/**
* Configure interceptors for the handshake request.
*/
WebSocketHandlerRegistration addInterceptors(HandshakeInterceptor... interceptors);
/**
* Enable SockJS fallback options.
*/

View File

@ -17,133 +17,133 @@
-->
<xsd:schema xmlns="http://www.springframework.org/schema/websocket"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.springframework.org/schema/websocket"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.springframework.org/schema/websocket"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"
schemaLocation="http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/beans"
schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
<xsd:complexType name="mapping">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:complexType name="mapping">
<xsd:annotation>
<xsd:documentation><![CDATA[
An entry in the registered HandlerMapping that matches a path with a handler.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="path" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:attribute name="path" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
A path that maps a particular request to a handler.
Exact path mapping URIs (such as "/myPath") are supported as well as Ant-stype path patterns (such as /myPath/**).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="handler" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.WebSocketHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="handler" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.WebSocketHandler"><![CDATA[
The bean name of a WebSocketHandler to use for requests that match the path configuration.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="handshake-handler">
<xsd:attribute name="ref" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.server.HandshakeHandler"><![CDATA[
<xsd:complexType name="handshake-handler">
<xsd:attribute name="ref" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.server.HandshakeHandler"><![CDATA[
The bean name of a HandshakeHandler to use for processing WebSocket handshake requests.
If none specified, a DefaultHandshakeHandler will be configured by default.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="handshake-interceptors">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
<xsd:complexType name="handshake-interceptors">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
A list of HandshakeInterceptor beans definition and references.
A HandshakeInterceptor can be used to inspect the handshake request and response as well as to pass attributes to the target WebSocketHandler.
]]></xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
</xsd:annotation>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
A HandshakeInterceptor bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
A reference to a HandshakeInterceptor bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="sockjs-service">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService"><![CDATA[
<xsd:complexType name="sockjs-service">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService"><![CDATA[
Configures a DefaultSockJsService for processing HTTP requests from SockJS clients.
]]></xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="transport-handlers" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.sockjs.transport.TransportHandler"><![CDATA[
</xsd:annotation>
<xsd:sequence>
<xsd:element name="transport-handlers" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.sockjs.transport.TransportHandler"><![CDATA[
List of TransportHandler beans to be configured for the current handlers element.
One can choose not to register the default TransportHandlers and/or override those using
custom TransportHandlers.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
A TransportHandler bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to a TransportHandler bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether or not default TransportHandlers registrations should be added in addition to the ones provided within this element.
Default registrations include XhrPollingTransportHandler, XhrReceivingTransportHandler,
JsonpPollingTransportHandler, JsonpReceivingTransportHandler, XhrStreamingTransportHandler,
EventSourceTransportHandler, HtmlFileTransportHandler, and WebSocketTransportHandler.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
A unique name for the service, mainly for logging purposes.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-library-url" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-library-url" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
Transports with no native cross-domain communication (e.g. "eventsource",
"htmlfile") must get a simple page from the "foreign" domain in an invisible
iframe so that code in the iframe can run from a domain local to the SockJS
@ -161,73 +161,73 @@
above the SockJS mapping. In case of a prefix-based Servlet mapping one more
traversal may be needed.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="stream-bytes-limit" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="stream-bytes-limit" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
Minimum number of bytes that can be send over a single HTTP streaming request before it will be closed.
Defaults to 128K (i.e. 128 1024).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="session-cookie-needed" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="session-cookie-needed" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The "cookie_needed" value in the response from the SockJs "/info" endpoint.
This property indicates whether the use of a JSESSIONID cookie is required for the application to function correctly,
e.g. for load balancing or in Java Servlet containers for the use of an HTTP session.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-time" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-time" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The amount of time in milliseconds when the server has not sent any messages and after which the server
should send a heartbeat frame to the client in order to keep the connection from breaking.
The default value is 25,000 (25 seconds).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="disconnect-delay" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="disconnect-delay" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The amount of time in milliseconds before a client is considered disconnected after not having
a receiving connection, i.e. an active connection over which the server can send data to the client.
The default value is 5000.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="message-cache-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="message-cache-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The number of server-to-client messages that a session can cache while waiting for
the next HTTP polling request from the client.
The default size is 100.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="websocket-enabled" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="websocket-enabled" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
Some load balancers don't support websockets. Set this option to "false" to disable the WebSocket transport on the server side.
The default value is "true".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scheduler" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scheduler" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The bean name of a TaskScheduler; a new ThreadPoolTaskScheduler instance will be created if no value is provided.
This scheduler instance will be used for scheduling heart-beat messages.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="stomp-broker-relay">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
<xsd:complexType name="stomp-broker-relay">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
Configures a MessageHandler that handles messages by forwarding them to a STOMP broker.
This MessageHandler also opens a default "system" TCP connection to the message
broker that is used for sending messages that originate from the server application (as
@ -235,132 +235,132 @@
The "login", "password", "heartbeat-send-interval" and "heartbeat-receive-interval" attributes
are provided to configure this "system" connection.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
<xsd:attribute name="prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
Comma-separated list of destination prefixes supported by the broker being configured.
Destinations that do not match the given prefix(es) are ignored.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="relay-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="relay-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The STOMP message broker host.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="relay-port" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="relay-port" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The STOMP message broker port.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-login" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-login" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The login to use when creating connections to the STOMP broker on behalf of connected clients.
By default this is set to "guest".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-passcode" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-passcode" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The passcode to use when creating connections to the STOMP broker on behalf of connected clients.
By default this is set to "guest".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="system-login" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="system-login" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The login for the shared "system" connection used to send messages to
the STOMP broker from within the application, i.e. messages not associated
with a specific client session (e.g. REST/HTTP request handling method).
By default this is set to "guest".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="system-passcode" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="system-passcode" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The passcode for the shared "system" connection used to send messages to
the STOMP broker from within the application, i.e. messages not associated
with a specific client session (e.g. REST/HTTP request handling method).
By default this is set to "guest".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-send-interval" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-send-interval" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The interval, in milliseconds, at which the "system" connection will send heartbeats to the STOMP broker.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-receive-interval" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-receive-interval" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The interval, in milliseconds, at which the "system" connection expects to receive heartbeats from the STOMP broker.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
Whether or not the StompBrokerRelay should be automatically started as part of its SmartLifecycle,
i.e. at the time of an application context refresh.
Default value is "true".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="virtual-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="virtual-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The value of the "host" header to use in STOMP CONNECT frames sent to the STOMP broker.
This may be useful for example in a cloud environment where the actual host to which
the TCP connection is established is different from the host providing the cloud-based STOMP service.
By default this property is not set.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="simple-broker">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler"><![CDATA[
<xsd:complexType name="simple-broker">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler"><![CDATA[
Configures a SimpleBrokerMessageHandler that handles messages as a simple message broker implementation.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.SimpleBrokerMessageHandler"><![CDATA[
</xsd:annotation>
<xsd:attribute name="prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.SimpleBrokerMessageHandler"><![CDATA[
Comma-separated list of destination prefixes supported by the broker being configured.
Destinations that do not match the given prefix(es) are ignored.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="channel">
<xsd:sequence>
<xsd:element name="executor" type="channel-executor" minOccurs="0" maxOccurs="1"/>
<xsd:element name="interceptors" type="channel-interceptors" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="channel">
<xsd:sequence>
<xsd:element name="executor" type="channel-executor" minOccurs="0" maxOccurs="1"/>
<xsd:element name="interceptors" type="channel-interceptors" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="channel-executor">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
<xsd:complexType name="channel-executor">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Configuration for the ThreadPoolTaskExecutor that sends messages for the message channel.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="core-pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
</xsd:annotation>
<xsd:attribute name="core-pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Set the core pool size of the ThreadPoolExecutor.
NOTE: the core pool size is effectively the max pool size when an unbounded queue-capacity is configured (the default).
This is essentially the "Unbounded queues" strategy as explained in java.util.concurrent.ThreadPoolExecutor.
@ -369,73 +369,73 @@
In an an application where tasks do not block frequently,
the number should be closer to or equal to the number of available CPUs/cores.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Set the max pool size of the ThreadPoolExecutor.
NOTE: when an unbounded queue-capacity is configured (the default), the max pool size is effectively ignored.
See the "Unbounded queues" strategy in java.util.concurrent.ThreadPoolExecutor for more details.
By default this is set to Integer.MAX_VALUE.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="keep-alive-seconds" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="keep-alive-seconds" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Set the time limit for which threads may remain idle before being terminated.
If there are more than the core number of threads currently in the pool, after waiting this amount of time without
processing a task, excess threads will be terminated. This overrides any value set in the constructor.
By default this is set to 60.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="queue-capacity" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="queue-capacity" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Set the queue capacity for the ThreadPoolExecutor.
NOTE: when an unbounded queue-capacity is configured (the default) the core pool size is effectively the max pool size.
This is essentially the "Unbounded queues" strategy as explained in java.util.concurrent.ThreadPoolExecutor.
When this strategy is used, the max pool size is effectively ignored.
By default this is set to Integer.MAX_VALUE.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="channel-interceptors">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.support.ChannelInterceptor"><![CDATA[
<xsd:complexType name="channel-interceptors">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.support.ChannelInterceptor"><![CDATA[
List of ChannelInterceptor beans to be used with this channel.
Empty by default.
]]></xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
A ChannelInterceptor bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to a ChannelInterceptor bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<!-- Elements definitions -->
<!-- Elements definitions -->
<xsd:element name="handlers">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:element name="handlers">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures WebSocket support by registering a SimpleUrlHandlerMapping and mapping
paths to registered WebSocketHandlers.
@ -449,28 +449,28 @@
See EnableWebSocket Javadoc for
information on code-based alternatives to enabling WebSocket support.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="mapping" type="mapping" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="handshake-handler" type="handshake-handler" minOccurs="0" maxOccurs="1"/>
<xsd:element name="handshake-interceptors" type="handshake-interceptors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sockjs" type="sockjs-service" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="mapping" type="mapping" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="handshake-handler" type="handshake-handler" minOccurs="0" maxOccurs="1"/>
<xsd:element name="handshake-interceptors" type="handshake-interceptors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sockjs" type="sockjs-service" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation><![CDATA[
Order value for this SimpleUrlHandlerMapping.
Default value is 1.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="message-broker">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:element name="message-broker">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures broker-backed messaging over WebSocket using a higher-level messaging sub-protocol.
Registers a SimpleUrlHandlerMapping and maps paths to registered Controllers.
@ -478,19 +478,19 @@
See EnableWebSocketMessageBroker javadoc for information on code-based alternatives to enabling broker-backed messaging.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="transport" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="transport" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure options related to the processing of messages received from and sent to WebSocket clients.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="message-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="message-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure the maximum size for an incoming sub-protocol message.
For example a STOMP message may be received as multiple WebSocket messages
or multiple HTTP POST requests when SockJS fallback options are in use.
@ -509,11 +509,11 @@
Version 2 of the spec will but in the mean time existing client libraries
have already established a practice that servers must handle.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure a time limit (in milliseconds) for the maximum amount of a time
allowed when sending messages to a WebSocket session or writing to an
HTTP response when SockJS fallback option are in use.
@ -544,11 +544,11 @@
The default value is 10 seconds (i.e. 10 * 10000).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-buffer-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-buffer-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure the maximum amount of data to buffer when sending messages
to a WebSocket session, or an HTTP response when SockJS fallback
option are in use.
@ -576,97 +576,98 @@
sending messages; if the value is less than or equal to 0 then buffering
is effectively disabled.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="stomp-endpoint" minOccurs="1" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="stomp-endpoint" minOccurs="1" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
Registers STOMP over WebSocket endpoints.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="handshake-handler" type="handshake-handler" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sockjs" type="sockjs-service" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="path" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="handshake-handler" type="handshake-handler" minOccurs="0" maxOccurs="1"/>
<xsd:element name="handshake-interceptors" type="handshake-interceptors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sockjs" type="sockjs-service" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="path" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
A path that maps a particular message destination to a handler method.
Exact path mapping URIs (such as "/myPath") are supported as well as Ant-stype path patterns (such as /myPath/**).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:choice>
<xsd:element name="simple-broker" type="simple-broker"/>
<xsd:element name="stomp-broker-relay" type="stomp-broker-relay"/>
</xsd:choice>
<xsd:element name="message-converters" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:choice>
<xsd:element name="simple-broker" type="simple-broker"/>
<xsd:element name="stomp-broker-relay" type="stomp-broker-relay"/>
</xsd:choice>
<xsd:element name="message-converters" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure the message converters to use when extracting the payload of messages in annotated methods
and when sending messages (e.g. through the "broker" SimpMessagingTemplate.
MessageConverter registrations provided here will take precedence over MessageConverter types registered by default.
Also see the register-defaults attribute if you want to turn off default registrations entirely.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
A MessageConverter bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to an HttpMessageConverter bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether or not default MessageConverter registrations should be added in addition to the ones provided within this element.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="client-inbound-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="client-inbound-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The channel for receiving messages from clients (e.g. WebSocket clients).
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="client-outbound-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element name="client-outbound-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The channel for sending messages to clients (e.g. WebSocket clients).
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="broker-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element name="broker-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The channel for sending messages with translated user destinations.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="application-destination-prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="application-destination-prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Comma-separated list of prefixes to match to the destinations of handled messages.
Messages whose destination does not start with one of the configured prefixes are ignored.
@ -676,25 +677,25 @@
Prefixes without a trailing slash will have one appended automatically.
By default the list of prefixes is empty in which case all destinations match.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="user-destination-prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="user-destination-prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The prefix used to identify user destinations.
Any destinations that do not start with the given prefix are not be resolved.
The default value is "/user/".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation><![CDATA[
Order value for this SimpleUrlHandlerMapping.
Default value is 1.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>

View File

@ -17,134 +17,134 @@
-->
<xsd:schema xmlns="http://www.springframework.org/schema/websocket"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/websocket"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
targetNamespace="http://www.springframework.org/schema/websocket"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-4.1.xsd" />
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool.xsd" />
<xsd:complexType name="mapping">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:complexType name="mapping">
<xsd:annotation>
<xsd:documentation><![CDATA[
An entry in the registered HandlerMapping that matches a path with a handler.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="path" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:attribute name="path" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
A path that maps a particular request to a handler.
Exact path mapping URIs (such as "/myPath") are supported as well as Ant-stype path patterns (such as /myPath/**).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="handler" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.WebSocketHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="handler" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.WebSocketHandler"><![CDATA[
The bean name of a WebSocketHandler to use for requests that match the path configuration.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="handshake-handler">
<xsd:attribute name="ref" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.server.HandshakeHandler"><![CDATA[
<xsd:complexType name="handshake-handler">
<xsd:attribute name="ref" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.server.HandshakeHandler"><![CDATA[
The bean name of a HandshakeHandler to use for processing WebSocket handshake requests.
If none specified, a DefaultHandshakeHandler will be configured by default.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="handshake-interceptors">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
<xsd:complexType name="handshake-interceptors">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
A list of HandshakeInterceptor beans definition and references.
A HandshakeInterceptor can be used to inspect the handshake request and response as well as to pass attributes to the target WebSocketHandler.
]]></xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
</xsd:annotation>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
A HandshakeInterceptor bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.server.HandshakeInterceptor"><![CDATA[
A reference to a HandshakeInterceptor bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="sockjs-service">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService"><![CDATA[
<xsd:complexType name="sockjs-service">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService"><![CDATA[
Configures a DefaultSockJsService for processing HTTP requests from SockJS clients.
]]></xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="transport-handlers" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.sockjs.transport.TransportHandler"><![CDATA[
</xsd:annotation>
<xsd:sequence>
<xsd:element name="transport-handlers" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation source="org.springframework.web.socket.sockjs.transport.TransportHandler"><![CDATA[
List of TransportHandler beans to be configured for the current handlers element.
One can choose not to register the default TransportHandlers and/or override those using
custom TransportHandlers.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
A TransportHandler bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to a TransportHandler bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether or not default TransportHandlers registrations should be added in addition to the ones provided within this element.
Default registrations include XhrPollingTransportHandler, XhrReceivingTransportHandler,
JsonpPollingTransportHandler, JsonpReceivingTransportHandler, XhrStreamingTransportHandler,
EventSourceTransportHandler, HtmlFileTransportHandler, and WebSocketTransportHandler.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
A unique name for the service, mainly for logging purposes.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-library-url" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-library-url" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
Transports with no native cross-domain communication (e.g. "eventsource",
"htmlfile") must get a simple page from the "foreign" domain in an invisible
iframe so that code in the iframe can run from a domain local to the SockJS
@ -162,73 +162,73 @@
above the SockJS mapping. In case of a prefix-based Servlet mapping one more
traversal may be needed.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="stream-bytes-limit" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="stream-bytes-limit" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
Minimum number of bytes that can be send over a single HTTP streaming request before it will be closed.
Defaults to 128K (i.e. 128 1024).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="session-cookie-needed" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="session-cookie-needed" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The "cookie_needed" value in the response from the SockJs "/info" endpoint.
This property indicates whether the use of a JSESSIONID cookie is required for the application to function correctly,
e.g. for load balancing or in Java Servlet containers for the use of an HTTP session.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-time" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-time" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The amount of time in milliseconds when the server has not sent any messages and after which the server
should send a heartbeat frame to the client in order to keep the connection from breaking.
The default value is 25,000 (25 seconds).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="disconnect-delay" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="disconnect-delay" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The amount of time in milliseconds before a client is considered disconnected after not having
a receiving connection, i.e. an active connection over which the server can send data to the client.
The default value is 5000.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="message-cache-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="message-cache-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The number of server-to-client messages that a session can cache while waiting for
the next HTTP polling request from the client.
The default size is 100.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="websocket-enabled" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="websocket-enabled" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
Some load balancers don't support websockets. Set this option to "false" to disable the WebSocket transport on the server side.
The default value is "true".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scheduler" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scheduler" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.socket.sockjs.support.AbstractSockJsService"><![CDATA[
The bean name of a TaskScheduler; a new ThreadPoolTaskScheduler instance will be created if no value is provided.
This scheduler instance will be used for scheduling heart-beat messages.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="stomp-broker-relay">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
<xsd:complexType name="stomp-broker-relay">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
Configures a MessageHandler that handles messages by forwarding them to a STOMP broker.
This MessageHandler also opens a default "system" TCP connection to the message
broker that is used for sending messages that originate from the server application (as
@ -236,132 +236,132 @@
The "login", "password", "heartbeat-send-interval" and "heartbeat-receive-interval" attributes
are provided to configure this "system" connection.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
<xsd:attribute name="prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
Comma-separated list of destination prefixes supported by the broker being configured.
Destinations that do not match the given prefix(es) are ignored.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="relay-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="relay-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The STOMP message broker host.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="relay-port" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="relay-port" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The STOMP message broker port.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-login" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-login" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The login to use when creating connections to the STOMP broker on behalf of connected clients.
By default this is set to "guest".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-passcode" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-passcode" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The passcode to use when creating connections to the STOMP broker on behalf of connected clients.
By default this is set to "guest".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="system-login" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="system-login" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The login for the shared "system" connection used to send messages to
the STOMP broker from within the application, i.e. messages not associated
with a specific client session (e.g. REST/HTTP request handling method).
By default this is set to "guest".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="system-passcode" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="system-passcode" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The passcode for the shared "system" connection used to send messages to
the STOMP broker from within the application, i.e. messages not associated
with a specific client session (e.g. REST/HTTP request handling method).
By default this is set to "guest".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-send-interval" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-send-interval" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The interval, in milliseconds, at which the "system" connection will send heartbeats to the STOMP broker.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-receive-interval" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="heartbeat-receive-interval" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The interval, in milliseconds, at which the "system" connection expects to receive heartbeats from the STOMP broker.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
Whether or not the StompBrokerRelay should be automatically started as part of its SmartLifecycle,
i.e. at the time of an application context refresh.
Default value is "true".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="virtual-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="virtual-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler"><![CDATA[
The value of the "host" header to use in STOMP CONNECT frames sent to the STOMP broker.
This may be useful for example in a cloud environment where the actual host to which
the TCP connection is established is different from the host providing the cloud-based STOMP service.
By default this property is not set.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="simple-broker">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler"><![CDATA[
<xsd:complexType name="simple-broker">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler"><![CDATA[
Configures a SimpleBrokerMessageHandler that handles messages as a simple message broker implementation.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.SimpleBrokerMessageHandler"><![CDATA[
</xsd:annotation>
<xsd:attribute name="prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.simp.stomp.SimpleBrokerMessageHandler"><![CDATA[
Comma-separated list of destination prefixes supported by the broker being configured.
Destinations that do not match the given prefix(es) are ignored.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="channel">
<xsd:sequence>
<xsd:element name="executor" type="channel-executor" minOccurs="0" maxOccurs="1"/>
<xsd:element name="interceptors" type="channel-interceptors" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="channel">
<xsd:sequence>
<xsd:element name="executor" type="channel-executor" minOccurs="0" maxOccurs="1"/>
<xsd:element name="interceptors" type="channel-interceptors" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="channel-executor">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
<xsd:complexType name="channel-executor">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Configuration for the ThreadPoolTaskExecutor that sends messages for the message channel.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="core-pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
</xsd:annotation>
<xsd:attribute name="core-pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Set the core pool size of the ThreadPoolExecutor.
NOTE: the core pool size is effectively the max pool size when an unbounded queue-capacity is configured (the default).
This is essentially the "Unbounded queues" strategy as explained in java.util.concurrent.ThreadPoolExecutor.
@ -370,73 +370,73 @@
In an an application where tasks do not block frequently,
the number should be closer to or equal to the number of available CPUs/cores.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Set the max pool size of the ThreadPoolExecutor.
NOTE: when an unbounded queue-capacity is configured (the default), the max pool size is effectively ignored.
See the "Unbounded queues" strategy in java.util.concurrent.ThreadPoolExecutor for more details.
By default this is set to Integer.MAX_VALUE.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="keep-alive-seconds" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="keep-alive-seconds" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Set the time limit for which threads may remain idle before being terminated.
If there are more than the core number of threads currently in the pool, after waiting this amount of time without
processing a task, excess threads will be terminated. This overrides any value set in the constructor.
By default this is set to 60.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="queue-capacity" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="queue-capacity" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><![CDATA[
Set the queue capacity for the ThreadPoolExecutor.
NOTE: when an unbounded queue-capacity is configured (the default) the core pool size is effectively the max pool size.
This is essentially the "Unbounded queues" strategy as explained in java.util.concurrent.ThreadPoolExecutor.
When this strategy is used, the max pool size is effectively ignored.
By default this is set to Integer.MAX_VALUE.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="channel-interceptors">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.support.ChannelInterceptor"><![CDATA[
<xsd:complexType name="channel-interceptors">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.messaging.support.ChannelInterceptor"><![CDATA[
List of ChannelInterceptor beans to be used with this channel.
Empty by default.
]]></xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
A ChannelInterceptor bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to a ChannelInterceptor bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<!-- Elements definitions -->
<!-- Elements definitions -->
<xsd:element name="handlers">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:element name="handlers">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures WebSocket support by registering a SimpleUrlHandlerMapping and mapping
paths to registered WebSocketHandlers.
@ -450,28 +450,28 @@
See EnableWebSocket Javadoc for
information on code-based alternatives to enabling WebSocket support.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="mapping" type="mapping" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="handshake-handler" type="handshake-handler" minOccurs="0" maxOccurs="1"/>
<xsd:element name="handshake-interceptors" type="handshake-interceptors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sockjs" type="sockjs-service" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="mapping" type="mapping" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="handshake-handler" type="handshake-handler" minOccurs="0" maxOccurs="1"/>
<xsd:element name="handshake-interceptors" type="handshake-interceptors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sockjs" type="sockjs-service" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation><![CDATA[
Order value for this SimpleUrlHandlerMapping.
Default value is 1.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="message-broker">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:element name="message-broker">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures broker-backed messaging over WebSocket using a higher-level messaging sub-protocol.
Registers a SimpleUrlHandlerMapping and maps paths to registered Controllers.
@ -479,19 +479,19 @@
See EnableWebSocketMessageBroker javadoc for information on code-based alternatives to enabling broker-backed messaging.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="transport" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="transport" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure options related to the processing of messages received from and sent to WebSocket clients.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="message-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="message-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure the maximum size for an incoming sub-protocol message.
For example a STOMP message may be received as multiple WebSocket messages
or multiple HTTP POST requests when SockJS fallback options are in use.
@ -510,11 +510,11 @@
Version 2 of the spec will but in the mean time existing client libraries
have already established a practice that servers must handle.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure a time limit (in milliseconds) for the maximum amount of a time
allowed when sending messages to a WebSocket session or writing to an
HTTP response when SockJS fallback option are in use.
@ -545,11 +545,11 @@
The default value is 10 seconds (i.e. 10 * 10000).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-buffer-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-buffer-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure the maximum amount of data to buffer when sending messages
to a WebSocket session, or an HTTP response when SockJS fallback
option are in use.
@ -577,97 +577,98 @@
sending messages; if the value is less than or equal to 0 then buffering
is effectively disabled.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="stomp-endpoint" minOccurs="1" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="stomp-endpoint" minOccurs="1" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
Registers STOMP over WebSocket endpoints.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="handshake-handler" type="handshake-handler" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sockjs" type="sockjs-service" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="path" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="handshake-handler" type="handshake-handler" minOccurs="0" maxOccurs="1"/>
<xsd:element name="handshake-interceptors" type="handshake-interceptors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sockjs" type="sockjs-service" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="path" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
A path that maps a particular message destination to a handler method.
Exact path mapping URIs (such as "/myPath") are supported as well as Ant-stype path patterns (such as /myPath/**).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:choice>
<xsd:element name="simple-broker" type="simple-broker"/>
<xsd:element name="stomp-broker-relay" type="stomp-broker-relay"/>
</xsd:choice>
<xsd:element name="message-converters" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:choice>
<xsd:element name="simple-broker" type="simple-broker"/>
<xsd:element name="stomp-broker-relay" type="stomp-broker-relay"/>
</xsd:choice>
<xsd:element name="message-converters" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configure the message converters to use when extracting the payload of messages in annotated methods
and when sending messages (e.g. through the "broker" SimpMessagingTemplate.
MessageConverter registrations provided here will take precedence over MessageConverter types registered by default.
Also see the register-defaults attribute if you want to turn off default registrations entirely.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
A MessageConverter bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element ref="beans:ref">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to an HttpMessageConverter bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether or not default MessageConverter registrations should be added in addition to the ones provided within this element.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="client-inbound-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="client-inbound-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The channel for receiving messages from clients (e.g. WebSocket clients).
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="client-outbound-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element name="client-outbound-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The channel for sending messages to clients (e.g. WebSocket clients).
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="broker-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
<xsd:element name="broker-channel" type="channel" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The channel for sending messages with translated user destinations.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="application-destination-prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="application-destination-prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Comma-separated list of prefixes to match to the destinations of handled messages.
Messages whose destination does not start with one of the configured prefixes are ignored.
@ -677,17 +678,17 @@
Prefixes without a trailing slash will have one appended automatically.
By default the list of prefixes is empty in which case all destinations match.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="user-destination-prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="user-destination-prefix" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The prefix used to identify user destinations.
Any destinations that do not start with the given prefix are not be resolved.
The default value is "/user/".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="path-matcher" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
@ -715,14 +716,14 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation><![CDATA[
Order value for this SimpleUrlHandlerMapping.
Default value is 1.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>

View File

@ -41,14 +41,16 @@ import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.server.HandshakeFailureException;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.server.HandshakeHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
import org.springframework.web.socket.sockjs.SockJsService;
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
import org.springframework.web.socket.sockjs.transport.TransportHandler;
import org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService;
import org.springframework.web.socket.sockjs.transport.TransportType;
import org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService;
import org.springframework.web.socket.sockjs.transport.handler.EventSourceTransportHandler;
import org.springframework.web.socket.sockjs.transport.handler.HtmlFileTransportHandler;
@ -59,6 +61,7 @@ import org.springframework.web.socket.sockjs.transport.handler.XhrPollingTranspo
import org.springframework.web.socket.sockjs.transport.handler.XhrReceivingTransportHandler;
import org.springframework.web.socket.sockjs.transport.handler.XhrStreamingTransportHandler;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
@ -66,46 +69,46 @@ import static org.junit.Assert.*;
* See test configuration files websocket-config-handlers-*.xml.
*
* @author Brian Clozel
* @author Rossen Stoyanchev
*/
public class HandlersBeanDefinitionParserTests {
private GenericWebApplicationContext appContext;
@Before
public void setup() {
appContext = new GenericWebApplicationContext();
this.appContext = new GenericWebApplicationContext();
}
@Test
public void webSocketHandlers() {
loadBeanDefinitions("websocket-config-handlers.xml");
Map<String, HandlerMapping> handlersMap = appContext.getBeansOfType(HandlerMapping.class);
Map<String, HandlerMapping> handlersMap = this.appContext.getBeansOfType(HandlerMapping.class);
assertNotNull(handlersMap);
assertThat(handlersMap.values(), Matchers.hasSize(2));
assertThat(handlersMap.values(), hasSize(2));
for(HandlerMapping handlerMapping : handlersMap.values()) {
assertTrue(handlerMapping instanceof SimpleUrlHandlerMapping);
SimpleUrlHandlerMapping urlHandlerMapping = (SimpleUrlHandlerMapping) handlerMapping;
for (HandlerMapping hm : handlersMap.values()) {
assertTrue(hm instanceof SimpleUrlHandlerMapping);
SimpleUrlHandlerMapping shm = (SimpleUrlHandlerMapping) hm;
if(urlHandlerMapping.getUrlMap().keySet().contains("/foo")) {
assertThat(urlHandlerMapping.getUrlMap().keySet(),Matchers.contains("/foo","/bar"));
WebSocketHttpRequestHandler handler = (WebSocketHttpRequestHandler)
urlHandlerMapping.getUrlMap().get("/foo");
if (shm.getUrlMap().keySet().contains("/foo")) {
assertThat(shm.getUrlMap().keySet(), contains("/foo", "/bar"));
WebSocketHttpRequestHandler handler = (WebSocketHttpRequestHandler) shm.getUrlMap().get("/foo");
assertNotNull(handler);
checkDelegateHandlerType(handler.getWebSocketHandler(), FooWebSocketHandler.class);
HandshakeHandler handshakeHandler = (HandshakeHandler)
new DirectFieldAccessor(handler).getPropertyValue("handshakeHandler");
unwrapAndCheckDecoratedHandlerType(handler.getWebSocketHandler(), FooWebSocketHandler.class);
HandshakeHandler handshakeHandler = handler.getHandshakeHandler();
assertNotNull(handshakeHandler);
assertTrue(handshakeHandler instanceof DefaultHandshakeHandler);
}
else {
assertThat(urlHandlerMapping.getUrlMap().keySet(),Matchers.contains("/test"));
WebSocketHttpRequestHandler handler = (WebSocketHttpRequestHandler)
urlHandlerMapping.getUrlMap().get("/test");
assertThat(shm.getUrlMap().keySet(), contains("/test"));
WebSocketHttpRequestHandler handler = (WebSocketHttpRequestHandler) shm.getUrlMap().get("/test");
assertNotNull(handler);
checkDelegateHandlerType(handler.getWebSocketHandler(), TestWebSocketHandler.class);
HandshakeHandler handshakeHandler = (HandshakeHandler)
new DirectFieldAccessor(handler).getPropertyValue("handshakeHandler");
unwrapAndCheckDecoratedHandlerType(handler.getWebSocketHandler(), TestWebSocketHandler.class);
HandshakeHandler handshakeHandler = handler.getHandshakeHandler();
assertNotNull(handshakeHandler);
assertTrue(handshakeHandler instanceof DefaultHandshakeHandler);
}
@ -114,9 +117,10 @@ public class HandlersBeanDefinitionParserTests {
@Test
@SuppressWarnings("unchecked")
public void websocketHandlersAttributes() {
public void webSocketHandlersAttributes() {
loadBeanDefinitions("websocket-config-handlers-attributes.xml");
HandlerMapping handlerMapping = appContext.getBean(HandlerMapping.class);
HandlerMapping handlerMapping = this.appContext.getBean(HandlerMapping.class);
assertNotNull(handlerMapping);
assertTrue(handlerMapping instanceof SimpleUrlHandlerMapping);
@ -125,142 +129,161 @@ public class HandlersBeanDefinitionParserTests {
WebSocketHttpRequestHandler handler = (WebSocketHttpRequestHandler) urlHandlerMapping.getUrlMap().get("/foo");
assertNotNull(handler);
checkDelegateHandlerType(handler.getWebSocketHandler(), FooWebSocketHandler.class);
HandshakeHandler handshakeHandler = (HandshakeHandler)
new DirectFieldAccessor(handler).getPropertyValue("handshakeHandler");
unwrapAndCheckDecoratedHandlerType(handler.getWebSocketHandler(), FooWebSocketHandler.class);
HandshakeHandler handshakeHandler = handler.getHandshakeHandler();
assertNotNull(handshakeHandler);
assertTrue(handshakeHandler instanceof TestHandshakeHandler);
List<HandshakeInterceptor> handshakeInterceptorList = (List<HandshakeInterceptor>)
new DirectFieldAccessor(handler).getPropertyValue("interceptors");
assertNotNull(handshakeInterceptorList);
assertThat(handshakeInterceptorList, Matchers.contains(
Matchers.instanceOf(FooTestInterceptor.class), Matchers.instanceOf(BarTestInterceptor.class)));
List<HandshakeInterceptor> interceptors = handler.getHandshakeInterceptors();
assertThat(interceptors, contains(instanceOf(FooTestInterceptor.class), instanceOf(BarTestInterceptor.class)));
handler = (WebSocketHttpRequestHandler) urlHandlerMapping.getUrlMap().get("/test");
assertNotNull(handler);
checkDelegateHandlerType(handler.getWebSocketHandler(), TestWebSocketHandler.class);
handshakeHandler = (HandshakeHandler) new DirectFieldAccessor(handler).getPropertyValue("handshakeHandler");
unwrapAndCheckDecoratedHandlerType(handler.getWebSocketHandler(), TestWebSocketHandler.class);
handshakeHandler = handler.getHandshakeHandler();
assertNotNull(handshakeHandler);
assertTrue(handshakeHandler instanceof TestHandshakeHandler);
handshakeInterceptorList = (List<HandshakeInterceptor>)
new DirectFieldAccessor(handler).getPropertyValue("interceptors");
assertNotNull(handshakeInterceptorList);
assertThat(handshakeInterceptorList, Matchers.contains(
Matchers.instanceOf(FooTestInterceptor.class), Matchers.instanceOf(BarTestInterceptor.class)));
interceptors = handler.getHandshakeInterceptors();
assertThat(interceptors, contains(instanceOf(FooTestInterceptor.class), instanceOf(BarTestInterceptor.class)));
}
@Test
@SuppressWarnings("unchecked")
public void sockJsSupport() {
public void sockJs() {
loadBeanDefinitions("websocket-config-handlers-sockjs.xml");
SimpleUrlHandlerMapping handlerMapping = appContext.getBean(SimpleUrlHandlerMapping.class);
SimpleUrlHandlerMapping handlerMapping = this.appContext.getBean(SimpleUrlHandlerMapping.class);
assertNotNull(handlerMapping);
SockJsHttpRequestHandler testHandler = (SockJsHttpRequestHandler) handlerMapping.getUrlMap().get("/test/**");
assertNotNull(testHandler);
checkDelegateHandlerType(testHandler.getWebSocketHandler(), TestWebSocketHandler.class);
unwrapAndCheckDecoratedHandlerType(testHandler.getWebSocketHandler(), TestWebSocketHandler.class);
SockJsService testSockJsService = testHandler.getSockJsService();
SockJsHttpRequestHandler fooHandler = (SockJsHttpRequestHandler) handlerMapping.getUrlMap().get("/foo/**");
assertNotNull(fooHandler);
checkDelegateHandlerType(fooHandler.getWebSocketHandler(), FooWebSocketHandler.class);
unwrapAndCheckDecoratedHandlerType(fooHandler.getWebSocketHandler(), FooWebSocketHandler.class);
SockJsService sockJsService = fooHandler.getSockJsService();
assertNotNull(sockJsService);
assertEquals(testSockJsService, sockJsService);
assertThat(sockJsService, Matchers.instanceOf(DefaultSockJsService.class));
assertSame(testSockJsService, sockJsService);
assertThat(sockJsService, instanceOf(DefaultSockJsService.class));
DefaultSockJsService defaultSockJsService = (DefaultSockJsService) sockJsService;
assertThat(defaultSockJsService.getTaskScheduler(), Matchers.instanceOf(ThreadPoolTaskScheduler.class));
assertThat(defaultSockJsService.getTransportHandlers().values(), Matchers.containsInAnyOrder(
Matchers.instanceOf(XhrPollingTransportHandler.class),
Matchers.instanceOf(XhrReceivingTransportHandler.class),
Matchers.instanceOf(JsonpPollingTransportHandler.class),
Matchers.instanceOf(JsonpReceivingTransportHandler.class),
Matchers.instanceOf(XhrStreamingTransportHandler.class),
Matchers.instanceOf(EventSourceTransportHandler.class),
Matchers.instanceOf(HtmlFileTransportHandler.class),
Matchers.instanceOf(WebSocketTransportHandler.class)));
assertThat(defaultSockJsService.getTaskScheduler(), instanceOf(ThreadPoolTaskScheduler.class));
Map<TransportType, TransportHandler> transportHandlers = defaultSockJsService.getTransportHandlers();
assertThat(transportHandlers.values(),
containsInAnyOrder(
instanceOf(XhrPollingTransportHandler.class),
instanceOf(XhrReceivingTransportHandler.class),
instanceOf(JsonpPollingTransportHandler.class),
instanceOf(JsonpReceivingTransportHandler.class),
instanceOf(XhrStreamingTransportHandler.class),
instanceOf(EventSourceTransportHandler.class),
instanceOf(HtmlFileTransportHandler.class),
instanceOf(WebSocketTransportHandler.class)));
WebSocketTransportHandler handler = (WebSocketTransportHandler) transportHandlers.get(TransportType.WEBSOCKET);
assertEquals(TestHandshakeHandler.class, handler.getHandshakeHandler().getClass());
List<HandshakeInterceptor> interceptors = defaultSockJsService.getHandshakeInterceptors();
assertThat(interceptors, contains(instanceOf(FooTestInterceptor.class), instanceOf(BarTestInterceptor.class)));
}
@Test
@SuppressWarnings("unchecked")
public void sockJsAttributesSupport() {
public void sockJsAttributes() {
loadBeanDefinitions("websocket-config-handlers-sockjs-attributes.xml");
SimpleUrlHandlerMapping handlerMapping = appContext.getBean(SimpleUrlHandlerMapping.class);
assertNotNull(handlerMapping);
SockJsHttpRequestHandler handler = (SockJsHttpRequestHandler) handlerMapping.getUrlMap().get("/test/**");
assertNotNull(handler);
checkDelegateHandlerType(handler.getWebSocketHandler(), TestWebSocketHandler.class);
unwrapAndCheckDecoratedHandlerType(handler.getWebSocketHandler(), TestWebSocketHandler.class);
SockJsService sockJsService = handler.getSockJsService();
assertNotNull(sockJsService);
assertThat(sockJsService, Matchers.instanceOf(TransportHandlingSockJsService.class));
TransportHandlingSockJsService defaultSockJsService = (TransportHandlingSockJsService) sockJsService;
assertThat(defaultSockJsService.getTaskScheduler(), Matchers.instanceOf(TestTaskScheduler.class));
assertThat(defaultSockJsService.getTransportHandlers().values(), Matchers.containsInAnyOrder(
Matchers.instanceOf(XhrPollingTransportHandler.class),
Matchers.instanceOf(XhrStreamingTransportHandler.class)));
assertThat(sockJsService, instanceOf(TransportHandlingSockJsService.class));
TransportHandlingSockJsService transportService = (TransportHandlingSockJsService) sockJsService;
assertThat(transportService.getTaskScheduler(), instanceOf(TestTaskScheduler.class));
assertThat(transportService.getTransportHandlers().values(),
containsInAnyOrder(
instanceOf(XhrPollingTransportHandler.class),
instanceOf(XhrStreamingTransportHandler.class)));
assertEquals("testSockJsService", defaultSockJsService.getName());
assertFalse(defaultSockJsService.isWebSocketEnabled());
assertFalse(defaultSockJsService.isSessionCookieNeeded());
assertEquals(2048, defaultSockJsService.getStreamBytesLimit());
assertEquals(256, defaultSockJsService.getDisconnectDelay());
assertEquals(1024, defaultSockJsService.getHttpMessageCacheSize());
assertEquals(20, defaultSockJsService.getHeartbeatTime());
assertEquals("testSockJsService", transportService.getName());
assertFalse(transportService.isWebSocketEnabled());
assertFalse(transportService.isSessionCookieNeeded());
assertEquals(2048, transportService.getStreamBytesLimit());
assertEquals(256, transportService.getDisconnectDelay());
assertEquals(1024, transportService.getHttpMessageCacheSize());
assertEquals(20, transportService.getHeartbeatTime());
}
private void loadBeanDefinitions(String fileName) {
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(appContext);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.appContext);
ClassPathResource resource = new ClassPathResource(fileName, HandlersBeanDefinitionParserTests.class);
reader.loadBeanDefinitions(resource);
appContext.refresh();
this.appContext.refresh();
}
private void checkDelegateHandlerType(WebSocketHandler handler, Class<?> handlerClass) {
do {
handler = (WebSocketHandler) new DirectFieldAccessor(handler).getPropertyValue("delegate");
private static void unwrapAndCheckDecoratedHandlerType(WebSocketHandler handler, Class<?> handlerClass) {
if (handler instanceof WebSocketHandlerDecorator) {
handler = ((WebSocketHandlerDecorator) handler).getLastHandler();
}
while (new DirectFieldAccessor(handler).isReadableProperty("delegate"));
assertTrue(handlerClass.isInstance(handler));
}
}
class TestWebSocketHandler implements WebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {}
public void afterConnectionEstablished(WebSocketSession session) {
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {}
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {}
public void handleTransportError(WebSocketSession session, Throwable exception) {
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {}
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
}
@Override
public boolean supportsPartialMessages() { return false; }
}
class FooWebSocketHandler extends TestWebSocketHandler { }
class TestHandshakeHandler implements HandshakeHandler {
@Override
public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws HandshakeFailureException {
public boolean supportsPartialMessages() {
return false;
}
}
class TestChannelInterceptor extends ChannelInterceptorAdapter { }
class FooWebSocketHandler extends TestWebSocketHandler {
}
class TestHandshakeHandler implements HandshakeHandler {
@Override
public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) {
return false;
}
}
class TestChannelInterceptor extends ChannelInterceptorAdapter {
}
class FooTestInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
WebSocketHandler wsHandler, Map<String, Object> attributes) {
return false;
}
@ -270,25 +293,40 @@ class FooTestInterceptor implements HandshakeInterceptor {
}
}
class BarTestInterceptor extends FooTestInterceptor {}
class BarTestInterceptor extends FooTestInterceptor {
}
@SuppressWarnings({ "unchecked", "rawtypes" })
class TestTaskScheduler implements TaskScheduler {
@Override
public ScheduledFuture schedule(Runnable task, Trigger trigger) { return null; }
@Override
public ScheduledFuture schedule(Runnable task, Date startTime) { return null; }
public ScheduledFuture schedule(Runnable task, Trigger trigger) {
return null;
}
@Override
public ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period) { return null; }
public ScheduledFuture schedule(Runnable task, Date startTime) {
return null;
}
@Override
public ScheduledFuture scheduleAtFixedRate(Runnable task, long period) { return null; }
public ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period) {
return null;
}
@Override
public ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay) { return null; }
public ScheduledFuture scheduleAtFixedRate(Runnable task, long period) {
return null;
}
@Override
public ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay) { return null; }
public ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
return null;
}
@Override
public ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay) {
return null;
}
}

View File

@ -16,6 +16,8 @@
package org.springframework.web.socket.config;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.*;
import java.util.ArrayList;
@ -60,6 +62,7 @@ import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.messaging.StompSubProtocolHandler;
import org.springframework.web.socket.messaging.SubProtocolWebSocketHandler;
import org.springframework.web.socket.server.HandshakeHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
import org.springframework.web.socket.sockjs.transport.TransportType;
@ -72,24 +75,25 @@ import org.springframework.web.socket.sockjs.transport.handler.WebSocketTranspor
*
* @author Brian Clozel
* @author Artem Bilan
* @author Rossen Stoyanchev
*/
public class MessageBrokerBeanDefinitionParserTests {
private GenericWebApplicationContext appContext;
@Before
public void setup() {
this.appContext = new GenericWebApplicationContext();
}
@Test
public void simpleBroker() {
loadBeanDefinitions("websocket-config-broker-simple.xml");
HandlerMapping hm = this.appContext.getBean(HandlerMapping.class);
assertNotNull(hm);
assertThat(hm, Matchers.instanceOf(SimpleUrlHandlerMapping.class));
SimpleUrlHandlerMapping suhm = (SimpleUrlHandlerMapping) hm;
assertThat(suhm.getUrlMap().keySet(), Matchers.hasSize(4));
assertThat(suhm.getUrlMap().values(), Matchers.hasSize(4));
@ -99,11 +103,11 @@ public class MessageBrokerBeanDefinitionParserTests {
assertThat(httpRequestHandler, Matchers.instanceOf(WebSocketHttpRequestHandler.class));
WebSocketHttpRequestHandler wsHttpRequestHandler = (WebSocketHttpRequestHandler) httpRequestHandler;
HandshakeHandler handshakeHandler = (HandshakeHandler)
new DirectFieldAccessor(wsHttpRequestHandler).getPropertyValue("handshakeHandler");
HandshakeHandler handshakeHandler = wsHttpRequestHandler.getHandshakeHandler();
assertNotNull(handshakeHandler);
assertTrue(handshakeHandler instanceof TestHandshakeHandler);
List<HandshakeInterceptor> interceptors = wsHttpRequestHandler.getHandshakeInterceptors();
assertThat(interceptors, contains(instanceOf(FooTestInterceptor.class), instanceOf(BarTestInterceptor.class)));
WebSocketHandler wsHandler = unwrapWebSocketHandler(wsHttpRequestHandler.getWebSocketHandler());
assertNotNull(wsHandler);
@ -114,8 +118,7 @@ public class MessageBrokerBeanDefinitionParserTests {
assertEquals(25 * 1000, subProtocolWsHandler.getSendTimeLimit());
assertEquals(1024 * 1024, subProtocolWsHandler.getSendBufferSizeLimit());
StompSubProtocolHandler stompHandler =
(StompSubProtocolHandler) subProtocolWsHandler.getProtocolHandlerMap().get("v12.stomp");
StompSubProtocolHandler stompHandler = (StompSubProtocolHandler) subProtocolWsHandler.getProtocolHandlerMap().get("v12.stomp");
assertNotNull(stompHandler);
assertEquals(128 * 1024, stompHandler.getMessageSizeLimit());
@ -142,6 +145,9 @@ public class MessageBrokerBeanDefinitionParserTests {
assertEquals(Runtime.getRuntime().availableProcessors(), scheduler.getScheduledThreadPoolExecutor().getCorePoolSize());
assertTrue(scheduler.getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy());
interceptors = defaultSockJsService.getHandshakeInterceptors();
assertThat(interceptors, contains(instanceOf(FooTestInterceptor.class), instanceOf(BarTestInterceptor.class)));
UserSessionRegistry userSessionRegistry = this.appContext.getBean(UserSessionRegistry.class);
assertNotNull(userSessionRegistry);
@ -170,8 +176,7 @@ public class MessageBrokerBeanDefinitionParserTests {
testChannel("clientOutboundChannel", subscriberTypes, 0);
testExecutor("clientOutboundChannel", Runtime.getRuntime().availableProcessors() * 2, Integer.MAX_VALUE, 60);
subscriberTypes = Arrays.<Class<? extends MessageHandler>>asList(
SimpleBrokerMessageHandler.class, UserDestinationMessageHandler.class);
subscriberTypes = Arrays.<Class<? extends MessageHandler>>asList(SimpleBrokerMessageHandler.class, UserDestinationMessageHandler.class);
testChannel("brokerChannel", subscriberTypes, 0);
try {
this.appContext.getBean("brokerChannelExecutor", ThreadPoolTaskExecutor.class);

View File

@ -35,13 +35,14 @@ import org.springframework.web.util.UrlPathHelper;
import static org.junit.Assert.*;
/**
* Test fixture for {@link org.springframework.web.socket.config.annotation.WebMvcStompEndpointRegistry}.
* Test fixture for
* {@link org.springframework.web.socket.config.annotation.WebMvcStompEndpointRegistry}.
*
* @author Rossen Stoyanchev
*/
public class WebMvcStompEndpointRegistryTests {
private WebMvcStompEndpointRegistry registry;
private WebMvcStompEndpointRegistry endpointRegistry;
private SubProtocolWebSocketHandler webSocketHandler;
@ -50,22 +51,18 @@ public class WebMvcStompEndpointRegistryTests {
@Before
public void setup() {
SubscribableChannel inChannel = Mockito.mock(SubscribableChannel.class);
SubscribableChannel outChannel = Mockito.mock(SubscribableChannel.class);
this.webSocketHandler = new SubProtocolWebSocketHandler(inChannel, outChannel);
this.userSessionRegistry = new DefaultUserSessionRegistry();
this.registry = new WebMvcStompEndpointRegistry(this.webSocketHandler,
this.endpointRegistry = new WebMvcStompEndpointRegistry(this.webSocketHandler,
new WebSocketTransportRegistration(), this.userSessionRegistry, Mockito.mock(TaskScheduler.class));
}
@Test
public void stompProtocolHandler() {
this.registry.addEndpoint("/stomp");
this.endpointRegistry.addEndpoint("/stomp");
Map<String, SubProtocolHandler> protocolHandlers = webSocketHandler.getProtocolHandlerMap();
assertEquals(3, protocolHandlers.size());
@ -79,16 +76,15 @@ public class WebMvcStompEndpointRegistryTests {
@Test
public void handlerMapping() {
SimpleUrlHandlerMapping hm = (SimpleUrlHandlerMapping) this.registry.getHandlerMapping();
SimpleUrlHandlerMapping hm = (SimpleUrlHandlerMapping) this.endpointRegistry.getHandlerMapping();
assertEquals(0, hm.getUrlMap().size());
UrlPathHelper pathHelper = new UrlPathHelper();
this.registry.setUrlPathHelper(pathHelper);
this.registry.addEndpoint("/stompOverWebSocket");
this.registry.addEndpoint("/stompOverSockJS").withSockJS();
this.endpointRegistry.setUrlPathHelper(pathHelper);
this.endpointRegistry.addEndpoint("/stompOverWebSocket");
this.endpointRegistry.addEndpoint("/stompOverSockJS").withSockJS();
hm = (SimpleUrlHandlerMapping) this.registry.getHandlerMapping();
hm = (SimpleUrlHandlerMapping) this.endpointRegistry.getHandlerMapping();
assertEquals(2, hm.getUrlMap().size());
assertNotNull(hm.getUrlMap().get("/stompOverWebSocket"));
assertNotNull(hm.getUrlMap().get("/stompOverSockJS/**"));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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,47 +22,51 @@ import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.messaging.support.ExecutorSubscribableChannel;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.util.MultiValueMap;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.socket.messaging.SubProtocolWebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
import org.springframework.web.socket.sockjs.transport.TransportHandler;
import org.springframework.web.socket.sockjs.transport.TransportType;
import org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService;
import org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler;
import static org.junit.Assert.*;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
/**
* Test fixture for {@link org.springframework.web.socket.config.annotation.WebMvcStompWebSocketEndpointRegistration}.
* Test fixture for
* {@link org.springframework.web.socket.config.annotation.WebMvcStompWebSocketEndpointRegistration}.
*
* @author Rossen Stoyanchev
*/
public class WebMvcStompEndpointRegistrationTests {
public class WebMvcStompWebSocketEndpointRegistrationTests {
private SubProtocolWebSocketHandler wsHandler;
private SubProtocolWebSocketHandler handler;
private TaskScheduler scheduler;
@Before
public void setup() {
this.wsHandler = new SubProtocolWebSocketHandler(
new ExecutorSubscribableChannel(), new ExecutorSubscribableChannel());
this.scheduler = Mockito.mock(TaskScheduler.class);
this.handler = new SubProtocolWebSocketHandler(mock(MessageChannel.class), mock(SubscribableChannel.class));
this.scheduler = mock(TaskScheduler.class);
}
@Test
public void minimalRegistration() {
WebMvcStompWebSocketEndpointRegistration registration = new WebMvcStompWebSocketEndpointRegistration(
new String[] {"/foo"}, this.wsHandler, this.scheduler);
WebMvcStompWebSocketEndpointRegistration registration =
new WebMvcStompWebSocketEndpointRegistration(new String[] {"/foo"}, this.handler, this.scheduler);
MultiValueMap<HttpRequestHandler, String> mappings = registration.getMappings();
assertEquals(1, mappings.size());
@ -73,14 +77,15 @@ public class WebMvcStompEndpointRegistrationTests {
}
@Test
public void customHandshakeHandler() {
public void handshakeHandlerAndInterceptors() {
WebMvcStompWebSocketEndpointRegistration registration =
new WebMvcStompWebSocketEndpointRegistration(new String[] {"/foo"}, this.handler, this.scheduler);
DefaultHandshakeHandler handshakeHandler = new DefaultHandshakeHandler();
WebMvcStompWebSocketEndpointRegistration registration = new WebMvcStompWebSocketEndpointRegistration(
new String[] {"/foo"}, this.wsHandler, this.scheduler);
HttpSessionHandshakeInterceptor interceptor = new HttpSessionHandshakeInterceptor();
registration.setHandshakeHandler(handshakeHandler);
registration.addInterceptors(interceptor);
MultiValueMap<HttpRequestHandler, String> mappings = registration.getMappings();
assertEquals(1, mappings.size());
@ -91,17 +96,19 @@ public class WebMvcStompEndpointRegistrationTests {
WebSocketHttpRequestHandler requestHandler = (WebSocketHttpRequestHandler) entry.getKey();
assertNotNull(requestHandler.getWebSocketHandler());
assertSame(handshakeHandler, requestHandler.getHandshakeHandler());
assertEquals(Arrays.asList(interceptor), requestHandler.getHandshakeInterceptors());
}
@Test
public void customHandshakeHandlerPassedToSockJsService() {
public void handshakeHandlerAndInterceptorsWithSockJsService() {
WebMvcStompWebSocketEndpointRegistration registration =
new WebMvcStompWebSocketEndpointRegistration(new String[] {"/foo"}, this.handler, this.scheduler);
DefaultHandshakeHandler handshakeHandler = new DefaultHandshakeHandler();
WebMvcStompWebSocketEndpointRegistration registration = new WebMvcStompWebSocketEndpointRegistration(
new String[] {"/foo"}, this.wsHandler, this.scheduler);
HttpSessionHandshakeInterceptor interceptor = new HttpSessionHandshakeInterceptor();
registration.setHandshakeHandler(handshakeHandler);
registration.addInterceptors(interceptor);
registration.withSockJS();
MultiValueMap<HttpRequestHandler, String> mappings = registration.getMappings();
@ -116,9 +123,10 @@ public class WebMvcStompEndpointRegistrationTests {
DefaultSockJsService sockJsService = (DefaultSockJsService) requestHandler.getSockJsService();
assertNotNull(sockJsService);
WebSocketTransportHandler transportHandler =
(WebSocketTransportHandler) sockJsService.getTransportHandlers().get(TransportType.WEBSOCKET);
Map<TransportType, TransportHandler> handlers = sockJsService.getTransportHandlers();
WebSocketTransportHandler transportHandler = (WebSocketTransportHandler) handlers.get(TransportType.WEBSOCKET);
assertSame(handshakeHandler, transportHandler.getHandshakeHandler());
assertEquals(Arrays.asList(interceptor), sockJsService.getHandshakeInterceptors());
}
}

View File

@ -38,7 +38,8 @@ import org.springframework.web.socket.sockjs.transport.handler.WebSocketTranspor
import static org.junit.Assert.*;
/**
* Test fixture for {@link org.springframework.web.socket.config.annotation.AbstractWebSocketHandlerRegistration}.
* Test fixture for
* {@link org.springframework.web.socket.config.annotation.AbstractWebSocketHandlerRegistration}.
*
* @author Rossen Stoyanchev
*/
@ -57,99 +58,93 @@ public class WebSocketHandlerRegistrationTests {
@Test
public void minimal() {
WebSocketHandler wsHandler = new TextWebSocketHandler();
this.registration.addHandler(wsHandler, "/foo", "/bar");
WebSocketHandler handler = new TextWebSocketHandler();
this.registration.addHandler(handler, "/foo", "/bar");
List<Mapping> mappings = this.registration.getMappings();
assertEquals(2, mappings.size());
Mapping m1 = mappings.get(0);
assertEquals(wsHandler, m1.webSocketHandler);
assertEquals(handler, m1.webSocketHandler);
assertEquals("/foo", m1.path);
Mapping m2 = mappings.get(1);
assertEquals(wsHandler, m2.webSocketHandler);
assertEquals(handler, m2.webSocketHandler);
assertEquals("/bar", m2.path);
}
@Test
public void interceptors() {
WebSocketHandler wsHandler = new TextWebSocketHandler();
WebSocketHandler handler = new TextWebSocketHandler();
HttpSessionHandshakeInterceptor interceptor = new HttpSessionHandshakeInterceptor();
this.registration.addHandler(wsHandler, "/foo").addInterceptors(interceptor);
this.registration.addHandler(handler, "/foo").addInterceptors(interceptor);
List<Mapping> mappings = this.registration.getMappings();
assertEquals(1, mappings.size());
Mapping m1 = mappings.get(0);
assertEquals(wsHandler, m1.webSocketHandler);
assertEquals("/foo", m1.path);
assertArrayEquals(new HandshakeInterceptor[] { interceptor }, m1.interceptors);
Mapping mapping = mappings.get(0);
assertEquals(handler, mapping.webSocketHandler);
assertEquals("/foo", mapping.path);
assertArrayEquals(new HandshakeInterceptor[] {interceptor}, mapping.interceptors);
}
@Test
public void interceptorsPassedToSockJsRegistration() {
WebSocketHandler wsHandler = new TextWebSocketHandler();
WebSocketHandler handler = new TextWebSocketHandler();
HttpSessionHandshakeInterceptor interceptor = new HttpSessionHandshakeInterceptor();
this.registration.addHandler(wsHandler, "/foo").addInterceptors(interceptor).withSockJS();
this.registration.addHandler(handler, "/foo").addInterceptors(interceptor).withSockJS();
List<Mapping> mappings = this.registration.getMappings();
assertEquals(1, mappings.size());
Mapping m1 = mappings.get(0);
assertEquals(wsHandler, m1.webSocketHandler);
assertEquals("/foo/**", m1.path);
assertNotNull(m1.sockJsService);
assertEquals(Arrays.asList(interceptor), m1.sockJsService.getHandshakeInterceptors());
Mapping mapping = mappings.get(0);
assertEquals(handler, mapping.webSocketHandler);
assertEquals("/foo/**", mapping.path);
assertNotNull(mapping.sockJsService);
assertEquals(Arrays.asList(interceptor), mapping.sockJsService.getHandshakeInterceptors());
}
@Test
public void handshakeHandler() {
WebSocketHandler wsHandler = new TextWebSocketHandler();
WebSocketHandler handler = new TextWebSocketHandler();
HandshakeHandler handshakeHandler = new DefaultHandshakeHandler();
this.registration.addHandler(wsHandler, "/foo").setHandshakeHandler(handshakeHandler);
this.registration.addHandler(handler, "/foo").setHandshakeHandler(handshakeHandler);
List<Mapping> mappings = this.registration.getMappings();
assertEquals(1, mappings.size());
Mapping m1 = mappings.get(0);
assertEquals(wsHandler, m1.webSocketHandler);
assertEquals("/foo", m1.path);
assertSame(handshakeHandler, m1.handshakeHandler);
Mapping mapping = mappings.get(0);
assertEquals(handler, mapping.webSocketHandler);
assertEquals("/foo", mapping.path);
assertSame(handshakeHandler, mapping.handshakeHandler);
}
@Test
public void handshakeHandlerPassedToSockJsRegistration() {
WebSocketHandler wsHandler = new TextWebSocketHandler();
WebSocketHandler handler = new TextWebSocketHandler();
HandshakeHandler handshakeHandler = new DefaultHandshakeHandler();
this.registration.addHandler(wsHandler, "/foo").setHandshakeHandler(handshakeHandler).withSockJS();
this.registration.addHandler(handler, "/foo").setHandshakeHandler(handshakeHandler).withSockJS();
List<Mapping> mappings = this.registration.getMappings();
assertEquals(1, mappings.size());
Mapping m1 = mappings.get(0);
assertEquals(wsHandler, m1.webSocketHandler);
assertEquals("/foo/**", m1.path);
assertNotNull(m1.sockJsService);
Mapping mapping = mappings.get(0);
assertEquals(handler, mapping.webSocketHandler);
assertEquals("/foo/**", mapping.path);
assertNotNull(mapping.sockJsService);
WebSocketTransportHandler transportHandler =
(WebSocketTransportHandler) m1.sockJsService.getTransportHandlers().get(TransportType.WEBSOCKET);
(WebSocketTransportHandler) mapping.sockJsService.getTransportHandlers().get(TransportType.WEBSOCKET);
assertSame(handshakeHandler, transportHandler.getHandshakeHandler());
}
private static class TestWebSocketHandlerRegistration extends AbstractWebSocketHandlerRegistration<List<Mapping>> {
public TestWebSocketHandlerRegistration(TaskScheduler sockJsTaskScheduler) {
super(sockJsTaskScheduler);
}
@ -167,15 +162,13 @@ public class WebSocketHandlerRegistrationTests {
}
@Override
protected void addWebSocketHandlerMapping(List<Mapping> mappings,
WebSocketHandler wsHandler, HandshakeHandler handshakeHandler,
HandshakeInterceptor[] interceptors, String path) {
protected void addWebSocketHandlerMapping(List<Mapping> mappings, WebSocketHandler handler,
HandshakeHandler handshakeHandler, HandshakeInterceptor[] interceptors, String path) {
mappings.add(new Mapping(wsHandler, path, handshakeHandler, interceptors));
mappings.add(new Mapping(handler, path, handshakeHandler, interceptors));
}
}
private static class Mapping {
private final WebSocketHandler webSocketHandler;

View File

@ -74,7 +74,6 @@ public class WebSocketMessageBrokerConfigurationSupportTests {
@Test
public void handlerMapping() {
SimpleUrlHandlerMapping hm = (SimpleUrlHandlerMapping) this.config.getBean(HandlerMapping.class);
assertEquals(1, hm.getOrder());
@ -85,7 +84,6 @@ public class WebSocketMessageBrokerConfigurationSupportTests {
@Test
public void clientInboundChannelSendMessage() throws Exception {
TestChannel channel = this.config.getBean("clientInboundChannel", TestChannel.class);
SubProtocolWebSocketHandler webSocketHandler = this.config.getBean(SubProtocolWebSocketHandler.class);

View File

@ -1,19 +1,19 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker>
<websocket:message-broker>
<websocket:stomp-endpoint path="/foo" />
<websocket:stomp-endpoint path="/foo" />
<websocket:simple-broker />
<websocket:simple-broker />
<websocket:message-converters register-defaults="false">
<bean class="org.springframework.messaging.converter.StringMessageConverter"/>
</websocket:message-converters>
<websocket:message-converters register-defaults="false">
<bean class="org.springframework.messaging.converter.StringMessageConverter"/>
</websocket:message-converters>
</websocket:message-broker>
</websocket:message-broker>
</beans>

View File

@ -1,19 +1,19 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker>
<websocket:message-broker>
<websocket:stomp-endpoint path="/foo" />
<websocket:stomp-endpoint path="/foo" />
<websocket:simple-broker />
<websocket:simple-broker />
<websocket:message-converters>
<bean class="org.springframework.messaging.converter.StringMessageConverter"/>
</websocket:message-converters>
<websocket:message-converters>
<bean class="org.springframework.messaging.converter.StringMessageConverter"/>
</websocket:message-converters>
</websocket:message-broker>
</websocket:message-broker>
</beans>

View File

@ -1,30 +1,30 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker>
<websocket:stomp-endpoint path="/foo"/>
<websocket:simple-broker prefix="/topic"/>
<websocket:client-inbound-channel>
<websocket:interceptors>
<ref bean="myInterceptor"/>
</websocket:interceptors>
</websocket:client-inbound-channel>
<websocket:client-outbound-channel>
<websocket:interceptors>
<ref bean="myInterceptor"/>
</websocket:interceptors>
</websocket:client-outbound-channel>
<websocket:broker-channel>
<websocket:interceptors>
<ref bean="myInterceptor"/>
</websocket:interceptors>
</websocket:broker-channel>
</websocket:message-broker>
<websocket:message-broker>
<websocket:stomp-endpoint path="/foo"/>
<websocket:simple-broker prefix="/topic"/>
<websocket:client-inbound-channel>
<websocket:interceptors>
<ref bean="myInterceptor"/>
</websocket:interceptors>
</websocket:client-inbound-channel>
<websocket:client-outbound-channel>
<websocket:interceptors>
<ref bean="myInterceptor"/>
</websocket:interceptors>
</websocket:client-outbound-channel>
<websocket:broker-channel>
<websocket:interceptors>
<ref bean="myInterceptor"/>
</websocket:interceptors>
</websocket:broker-channel>
</websocket:message-broker>
<bean id="myInterceptor" class="org.springframework.web.socket.config.TestChannelInterceptor"/>
<bean id="myInterceptor" class="org.springframework.web.socket.config.TestChannelInterceptor"/>
</beans>

View File

@ -1,34 +1,34 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker application-destination-prefix="/app" user-destination-prefix="/personal">
<websocket:stomp-endpoint path="/foo,/bar">
<websocket:handshake-handler ref="myHandler"/>
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic"/>
<websocket:client-inbound-channel>
<websocket:executor core-pool-size="100" max-pool-size="200" keep-alive-seconds="600"/>
<websocket:interceptors>
<ref bean="myInterceptor"/>
</websocket:interceptors>
</websocket:client-inbound-channel>
<websocket:client-outbound-channel>
<websocket:executor core-pool-size="101" max-pool-size="201" keep-alive-seconds="601"/>
<websocket:interceptors>
<ref bean="myInterceptor"/>
<bean class="org.springframework.web.socket.config.TestChannelInterceptor"/>
</websocket:interceptors>
</websocket:client-outbound-channel>
<websocket:broker-channel>
<websocket:executor core-pool-size="102" max-pool-size="202" keep-alive-seconds="602"/>
</websocket:broker-channel>
</websocket:message-broker>
<websocket:message-broker application-destination-prefix="/app" user-destination-prefix="/personal">
<websocket:stomp-endpoint path="/foo,/bar">
<websocket:handshake-handler ref="myHandler"/>
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic"/>
<websocket:client-inbound-channel>
<websocket:executor core-pool-size="100" max-pool-size="200" keep-alive-seconds="600"/>
<websocket:interceptors>
<ref bean="myInterceptor"/>
</websocket:interceptors>
</websocket:client-inbound-channel>
<websocket:client-outbound-channel>
<websocket:executor core-pool-size="101" max-pool-size="201" keep-alive-seconds="601"/>
<websocket:interceptors>
<ref bean="myInterceptor"/>
<bean class="org.springframework.web.socket.config.TestChannelInterceptor"/>
</websocket:interceptors>
</websocket:client-outbound-channel>
<websocket:broker-channel>
<websocket:executor core-pool-size="102" max-pool-size="202" keep-alive-seconds="602"/>
</websocket:broker-channel>
</websocket:message-broker>
<bean id="myHandler" class="org.springframework.web.socket.config.TestHandshakeHandler"/>
<bean id="myHandler" class="org.springframework.web.socket.config.TestHandshakeHandler"/>
<bean id="myInterceptor" class="org.springframework.web.socket.config.TestChannelInterceptor"/>
<bean id="myInterceptor" class="org.springframework.web.socket.config.TestChannelInterceptor"/>
</beans>

View File

@ -1,20 +1,20 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker order="2">
<websocket:stomp-endpoint path="/foo">
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:stomp-broker-relay prefix="/topic,/queue" relay-host="relayhost" relay-port="1234"
client-login="clientlogin" client-passcode="clientpass"
system-login="syslogin" system-passcode="syspass"
heartbeat-send-interval="5000" heartbeat-receive-interval="5000"
virtual-host="spring.io"/>
</websocket:message-broker>
<websocket:message-broker order="2">
<websocket:stomp-endpoint path="/foo">
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:stomp-broker-relay prefix="/topic,/queue" relay-host="relayhost" relay-port="1234"
client-login="clientlogin" client-passcode="clientpass"
system-login="syslogin" system-passcode="syspass"
heartbeat-send-interval="5000" heartbeat-receive-interval="5000"
virtual-host="spring.io"/>
</websocket:message-broker>
<bean id="myHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="myHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
</beans>

View File

@ -1,33 +1,42 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker application-destination-prefix="/app"
<websocket:message-broker application-destination-prefix="/app"
user-destination-prefix="/personal"
path-matcher="pathMatcher">
<!-- message-size=128*1024, send-buffer-size=1024*1024 -->
<websocket:transport message-size="131072" send-timeout="25000" send-buffer-size="1048576" />
<!-- message-size=128*1024, send-buffer-size=1024*1024 -->
<websocket:transport message-size="131072" send-timeout="25000" send-buffer-size="1048576" />
<websocket:stomp-endpoint path=" /foo,/bar">
<websocket:handshake-handler ref="myHandler"/>
</websocket:stomp-endpoint>
<websocket:stomp-endpoint path=" /foo,/bar">
<websocket:handshake-handler ref="myHandler"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.config.FooTestInterceptor"/>
<ref bean="barTestInterceptor"/>
</websocket:handshake-interceptors>
</websocket:stomp-endpoint>
<websocket:stomp-endpoint path="/test,/sockjs">
<websocket:handshake-handler ref="myHandler"/>
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:stomp-endpoint path="/test,/sockjs">
<websocket:handshake-handler ref="myHandler"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.config.FooTestInterceptor"/>
<ref bean="barTestInterceptor"/>
</websocket:handshake-interceptors>
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic, /queue"/>
<websocket:simple-broker prefix="/topic, /queue"/>
</websocket:message-broker>
</websocket:message-broker>
<bean id="pathMatcher" class="org.springframework.util.AntPathMatcher">
<property name="pathSeparator" value="." />
</bean>
<bean id="myHandler" class="org.springframework.web.socket.config.TestHandshakeHandler"/>
<bean id="myHandler" class="org.springframework.web.socket.config.TestHandshakeHandler"/>
<bean id="barTestInterceptor" class="org.springframework.web.socket.config.BarTestInterceptor"/>
</beans>

View File

@ -1,24 +1,24 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:handlers order="2">
<websocket:mapping path="/foo" handler="fooHandler"/>
<websocket:mapping path="/test" handler="testHandler"/>
<websocket:handshake-handler ref="testHandshakeHandler"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.config.FooTestInterceptor"/>
<ref bean="barTestInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
<websocket:handlers order="2">
<websocket:mapping path="/foo" handler="fooHandler"/>
<websocket:mapping path="/test" handler="testHandler"/>
<websocket:handshake-handler ref="testHandshakeHandler"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.config.FooTestInterceptor"/>
<ref bean="barTestInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
<bean id="testHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="fooHandler" class="org.springframework.web.socket.config.FooWebSocketHandler"/>
<bean id="testHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="fooHandler" class="org.springframework.web.socket.config.FooWebSocketHandler"/>
<bean id="barTestInterceptor" class="org.springframework.web.socket.config.BarTestInterceptor"/>
<bean id="testHandshakeHandler" class="org.springframework.web.socket.config.TestHandshakeHandler"/>
<bean id="barTestInterceptor" class="org.springframework.web.socket.config.BarTestInterceptor"/>
<bean id="testHandshakeHandler" class="org.springframework.web.socket.config.TestHandshakeHandler"/>
</beans>

View File

@ -1,29 +1,24 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:handlers >
<websocket:mapping path="/test" handler="testHandler"/>
<websocket:sockjs name="testSockJsService" scheduler="testTaskScheduler" websocket-enabled="false"
session-cookie-needed="false" stream-bytes-limit="2048" disconnect-delay="256"
message-cache-size="1024" heartbeat-time="20">
<websocket:transport-handlers register-defaults="false">
<bean class="org.springframework.web.socket.sockjs.transport.handler.XhrPollingTransportHandler"/>
<ref bean="xhrStreamingTransportHandler"/>
</websocket:transport-handlers>
</websocket:sockjs>
</websocket:handlers>
<websocket:handlers >
<websocket:mapping path="/test" handler="testHandler"/>
<websocket:sockjs name="testSockJsService" scheduler="testTaskScheduler" websocket-enabled="false"
session-cookie-needed="false" stream-bytes-limit="2048" disconnect-delay="256"
message-cache-size="1024" heartbeat-time="20">
<websocket:transport-handlers register-defaults="false">
<bean class="org.springframework.web.socket.sockjs.transport.handler.XhrPollingTransportHandler"/>
<ref bean="xhrStreamingTransportHandler"/>
</websocket:transport-handlers>
</websocket:sockjs>
</websocket:handlers>
<bean id="testHandler"
class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="xhrStreamingTransportHandler"
class="org.springframework.web.socket.sockjs.transport.handler.XhrStreamingTransportHandler"/>
<bean id="testTaskScheduler"
class="org.springframework.web.socket.config.TestTaskScheduler"/>
<bean id="testHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="testTaskScheduler" class="org.springframework.web.socket.config.TestTaskScheduler"/>
<bean id="xhrStreamingTransportHandler" class="org.springframework.web.socket.sockjs.transport.handler.XhrStreamingTransportHandler"/>
</beans>

View File

@ -1,17 +1,24 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:handlers>
<websocket:mapping path="/test" handler="testHandler"/>
<websocket:mapping path="/foo/" handler="fooHandler"/>
<websocket:sockjs/>
</websocket:handlers>
<websocket:handlers>
<websocket:mapping path="/test" handler="testHandler"/>
<websocket:mapping path="/foo/" handler="fooHandler"/>
<websocket:handshake-handler ref="testHandshakeHandler"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.config.FooTestInterceptor"/>
<ref bean="barTestInterceptor"/>
</websocket:handshake-interceptors>
<websocket:sockjs/>
</websocket:handlers>
<bean id="testHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="fooHandler" class="org.springframework.web.socket.config.FooWebSocketHandler"/>
<bean id="testHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="fooHandler" class="org.springframework.web.socket.config.FooWebSocketHandler"/>
<bean id="testHandshakeHandler" class="org.springframework.web.socket.config.TestHandshakeHandler"/>
<bean id="barTestInterceptor" class="org.springframework.web.socket.config.BarTestInterceptor"/>
</beans>

View File

@ -1,19 +1,19 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:handlers>
<websocket:mapping path="/foo,/bar" handler="fooHandler"/>
</websocket:handlers>
<websocket:handlers>
<websocket:mapping path="/foo,/bar" handler="fooHandler"/>
</websocket:handlers>
<websocket:handlers>
<websocket:mapping path="/test" handler="testHandler"/>
</websocket:handlers>
<websocket:handlers>
<websocket:mapping path="/test" handler="testHandler"/>
</websocket:handlers>
<bean id="testHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="fooHandler" class="org.springframework.web.socket.config.FooWebSocketHandler"/>
<bean id="testHandler" class="org.springframework.web.socket.config.TestWebSocketHandler"/>
<bean id="fooHandler" class="org.springframework.web.socket.config.FooWebSocketHandler"/>
</beans>