diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/AbstractWebSocketIntegrationTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/AbstractWebSocketIntegrationTests.java index 8b6d0b9316..7067ef25db 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/AbstractWebSocketIntegrationTests.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/AbstractWebSocketIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -43,6 +44,7 @@ import org.springframework.web.socket.server.support.DefaultHandshakeHandler; * Base class for WebSocket integration tests. * * @author Rossen Stoyanchev + * @author Sam Brannen */ public abstract class AbstractWebSocketIntegrationTests { @@ -85,6 +87,10 @@ public abstract class AbstractWebSocketIntegrationTests { this.server.setup(); this.server.deployConfig(this.wac); + // Set ServletContext in WebApplicationContext after deployment but before + // starting the server. + this.wac.setServletContext(this.server.getServletContext()); + this.wac.refresh(); this.server.start(); } diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/JettyWebSocketTestServer.java b/spring-websocket/src/test/java/org/springframework/web/socket/JettyWebSocketTestServer.java index 4f83b57662..876ad17c4c 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/JettyWebSocketTestServer.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/JettyWebSocketTestServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,10 @@ package org.springframework.web.socket; import java.util.EnumSet; + import javax.servlet.DispatcherType; import javax.servlet.Filter; +import javax.servlet.ServletContext; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; @@ -34,6 +36,7 @@ import org.springframework.web.servlet.DispatcherServlet; * Jetty based {@link WebSocketTestServer}. * * @author Rossen Stoyanchev + * @author Sam Brannen */ public class JettyWebSocketTestServer implements WebSocketTestServer { @@ -41,6 +44,8 @@ public class JettyWebSocketTestServer implements WebSocketTestServer { private int port = -1; + private ServletContextHandler contextHandler; + @Override public void setup() { @@ -54,21 +59,26 @@ public class JettyWebSocketTestServer implements WebSocketTestServer { } @Override - public void deployConfig(WebApplicationContext cxt, Filter... filters) { + public void deployConfig(WebApplicationContext wac, Filter... filters) { Assert.state(this.port != -1, "setup() was never called."); - ServletContextHandler contextHandler = new ServletContextHandler(); - ServletHolder servletHolder = new ServletHolder(new DispatcherServlet(cxt)); - contextHandler.addServlet(servletHolder, "/"); + ServletHolder servletHolder = new ServletHolder(new DispatcherServlet(wac)); + this.contextHandler = new ServletContextHandler(); + this.contextHandler.addServlet(servletHolder, "/"); for (Filter filter : filters) { - contextHandler.addFilter(new FilterHolder(filter), "/*", getDispatcherTypes()); + this.contextHandler.addFilter(new FilterHolder(filter), "/*", getDispatcherTypes()); } - this.jettyServer.setHandler(contextHandler); + this.jettyServer.setHandler(this.contextHandler); } private EnumSet getDispatcherTypes() { return EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC); } + @Override + public ServletContext getServletContext() { + return this.contextHandler.getServletContext(); + } + @Override public void undeployConfig() { // Stopping jetty will undeploy the servlet diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/TomcatWebSocketTestServer.java b/spring-websocket/src/test/java/org/springframework/web/socket/TomcatWebSocketTestServer.java index 4adc6aae77..0c4aa05d53 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/TomcatWebSocketTestServer.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/TomcatWebSocketTestServer.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import javax.servlet.Filter; +import javax.servlet.ServletContext; import org.apache.catalina.Context; import org.apache.catalina.LifecycleEvent; @@ -40,6 +41,7 @@ import org.springframework.web.servlet.DispatcherServlet; * Tomcat based {@link WebSocketTestServer}. * * @author Rossen Stoyanchev + * @author Sam Brannen */ public class TomcatWebSocketTestServer implements WebSocketTestServer { @@ -106,6 +108,11 @@ public class TomcatWebSocketTestServer implements WebSocketTestServer { } } + @Override + public ServletContext getServletContext() { + return this.context.getServletContext(); + } + @Override public void undeployConfig() { if (this.context != null) { diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/UndertowTestServer.java b/spring-websocket/src/test/java/org/springframework/web/socket/UndertowTestServer.java index d7caa7874e..7e2d009670 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/UndertowTestServer.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/UndertowTestServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,6 @@ package org.springframework.web.socket; -import java.io.IOException; -import javax.servlet.DispatcherType; -import javax.servlet.Filter; -import javax.servlet.Servlet; -import javax.servlet.ServletException; - import io.undertow.Undertow; import io.undertow.server.HttpHandler; import io.undertow.servlet.api.DeploymentInfo; @@ -30,21 +24,31 @@ import io.undertow.servlet.api.FilterInfo; import io.undertow.servlet.api.InstanceFactory; import io.undertow.servlet.api.InstanceHandle; import io.undertow.websockets.jsr.WebSocketDeploymentInfo; -import org.xnio.ByteBufferSlicePool; -import org.xnio.OptionMap; -import org.xnio.Xnio; + +import java.io.IOException; + +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; import org.springframework.util.Assert; import org.springframework.util.SocketUtils; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; +import org.xnio.ByteBufferSlicePool; +import org.xnio.OptionMap; +import org.xnio.Xnio; + import static io.undertow.servlet.Servlets.*; /** * Undertow-based {@link WebSocketTestServer}. * * @author Rossen Stoyanchev + * @author Sam Brannen */ public class UndertowTestServer implements WebSocketTestServer { @@ -66,9 +70,9 @@ public class UndertowTestServer implements WebSocketTestServer { } @Override - public void deployConfig(WebApplicationContext cxt, Filter... filters) { + public void deployConfig(WebApplicationContext wac, Filter... filters) { Assert.state(this.port != -1, "setup() was never called"); - DispatcherServletInstanceFactory servletFactory = new DispatcherServletInstanceFactory(cxt); + DispatcherServletInstanceFactory servletFactory = new DispatcherServletInstanceFactory(wac); // manually building WebSocketDeploymentInfo in order to avoid class cast exceptions // with tomcat's implementation when using undertow 1.1.0+ WebSocketDeploymentInfo info = new WebSocketDeploymentInfo(); @@ -104,6 +108,11 @@ public class UndertowTestServer implements WebSocketTestServer { } } + @Override + public ServletContext getServletContext() { + return this.manager.getDeployment().getServletContext(); + } + @Override public void undeployConfig() { this.manager.undeploy(); diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/WebSocketTestServer.java b/spring-websocket/src/test/java/org/springframework/web/socket/WebSocketTestServer.java index 5711168a62..4f91850d15 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/WebSocketTestServer.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/WebSocketTestServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.springframework.web.socket; import javax.servlet.Filter; +import javax.servlet.ServletContext; import org.springframework.web.context.WebApplicationContext; @@ -24,6 +25,7 @@ import org.springframework.web.context.WebApplicationContext; * Contract for a test server to use for WebSocket integration tests. * * @author Rossen Stoyanchev + * @author Sam Brannen */ public interface WebSocketTestServer { @@ -33,6 +35,16 @@ public interface WebSocketTestServer { void deployConfig(WebApplicationContext cxt, Filter... filters); + /** + * Get the {@link ServletContext} created by the underlying server. + * + *

The {@code ServletContext} is only guaranteed to be available + * after {@link #deployConfig} has been invoked. + * + * @since 4.2 + */ + ServletContext getServletContext(); + void undeployConfig(); void start() throws Exception; diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/AbstractSockJsIntegrationTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/AbstractSockJsIntegrationTests.java index 4c1d9d9bb0..2333760242 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/AbstractSockJsIntegrationTests.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/AbstractSockJsIntegrationTests.java @@ -26,6 +26,8 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -37,8 +39,10 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.junit.After; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; @@ -47,6 +51,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.tests.Assume; +import org.springframework.tests.TestGroup; import org.springframework.util.concurrent.ListenableFutureCallback; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.socket.TextMessage; @@ -63,11 +69,12 @@ import org.springframework.web.socket.server.support.DefaultHandshakeHandler; import static org.junit.Assert.*; /** - * Integration tests using the - * {@link org.springframework.web.socket.sockjs.client.SockJsClient}. + * Abstract base class for integration tests using the + * {@link org.springframework.web.socket.sockjs.client.SockJsClient SockJsClient} * against actual SockJS server endpoints. * * @author Rossen Stoyanchev + * @author Sam Brannen */ public abstract class AbstractSockJsIntegrationTests { @@ -88,6 +95,12 @@ public abstract class AbstractSockJsIntegrationTests { private String baseUrl; + @BeforeClass + public static void performanceTestGroupAssumption() throws Exception { + Assume.group(TestGroup.PERFORMANCE); + } + + @Before public void setup() throws Exception { logger.debug("Setting up '" + this.testName.getMethodName() + "'"); @@ -97,6 +110,10 @@ public abstract class AbstractSockJsIntegrationTests { this.server = createWebSocketTestServer(); this.server.setup(); this.server.deployConfig(this.wac, this.errorFilter); + // Set ServletContext in WebApplicationContext after deployment but before + // starting the server. + this.wac.setServletContext(this.server.getServletContext()); + this.wac.refresh(); this.server.start(); this.baseUrl = "http://localhost:" + this.server.getPort(); } @@ -142,8 +159,6 @@ public abstract class AbstractSockJsIntegrationTests { this.sockJsClient.start(); } - // Temporarily @Ignore failures caused by suspected Jetty bug - @Test public void echoWebSocket() throws Exception { testEcho(100, createWebSocketTransport()); @@ -217,9 +232,7 @@ public abstract class AbstractSockJsIntegrationTests { this.errorFilter.sleepDelayMap.put("/xhr_streaming", 10000L); this.errorFilter.responseStatusMap.put("/xhr_streaming", 503); initSockJsClient(createXhrTransport()); - ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); - scheduler.afterPropertiesSet(); - this.sockJsClient.setConnectTimeoutScheduler(scheduler); + this.sockJsClient.setConnectTimeoutScheduler(this.wac.getBean(ThreadPoolTaskScheduler.class)); WebSocketSession clientSession = sockJsClient.doHandshake(clientHandler, this.baseUrl + "/echo").get(); assertEquals("Fallback didn't occur", XhrClientSockJsSession.class, clientSession.getClass()); TextMessage message = new TextMessage("message1"); @@ -283,14 +296,11 @@ public abstract class AbstractSockJsIntegrationTests { } } - private static interface Condition { - boolean match(); - } - private static void awaitEvent(Condition condition, long timeToWait, String description) { + private static void awaitEvent(Supplier condition, long timeToWait, String description) { long timeToSleep = 200; for (int i = 0 ; i < Math.floor(timeToWait / timeToSleep); i++) { - if (condition.match()) { + if (condition.get()) { return; } try { diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/JettySockJsIntegrationTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/JettySockJsIntegrationTests.java index c18767aaa2..59bce8e9fa 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/JettySockJsIntegrationTests.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/JettySockJsIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,9 @@ package org.springframework.web.socket.sockjs.client; import org.eclipse.jetty.client.HttpClient; -import org.junit.BeforeClass; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.tests.Assume; -import org.springframework.tests.TestGroup; import org.springframework.web.socket.JettyWebSocketTestServer; import org.springframework.web.socket.client.jetty.JettyWebSocketClient; import org.springframework.web.socket.server.RequestUpgradeStrategy; @@ -34,11 +32,6 @@ import org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy; */ public class JettySockJsIntegrationTests extends AbstractSockJsIntegrationTests { - @BeforeClass - public static void setUpOnce() throws Exception { - Assume.group(TestGroup.PERFORMANCE); - } - @Override protected Class upgradeStrategyConfigClass() { return JettyTestConfig.class; diff --git a/spring-websocket/src/test/resources/log4j.properties b/spring-websocket/src/test/resources/log4j.properties index 0b8d9ec5f6..17f0648403 100644 --- a/spring-websocket/src/test/resources/log4j.properties +++ b/spring-websocket/src/test/resources/log4j.properties @@ -1,9 +1,8 @@ log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c][%t] - %m%n +log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%-5p] [%c] - %m%n log4j.rootCategory=WARN, console -log4j.logger.org.springframework.web=DEBUG -log4j.logger.org.springframework.web.socket=TRACE -log4j.logger.org.springframework.messaging=DEBUG - +log4j.logger.org.springframework.web=WARN +log4j.logger.org.springframework.web.socket=WARN +log4j.logger.org.springframework.messaging=WARN