Skip to content

Commit e8c8d2a

Browse files
committed
Refactor WebSocket int. tests to work w/ Jetty 9.3
Recent builds of Jetty 9.3 require that Jetty's own ServletContext implementation be supplied to WebSocketServerFactory's init() method. Otherwise, the Jetty server will fail to start with the exception message: "Not running on Jetty, WebSocket support unavailable". This commit refactors AbstractWebSocketIntegrationTests, AbstractSockJsIntegrationTests, and all WebSocketTestServer implementations in order to support this new requirement. Specifically: - WebSocketTestServer defines a new getServletContext() method; TomcatWebSocketTestServer, UndertowTestServer, and JettyWebSocketTestServer have all been updated to return the ServletContext created by the embedded server. - The setup() methods in AbstractWebSocketIntegrationTests and AbstractSockJsIntegrationTests have been updated so that the WebApplicationContext is supplied the appropriate ServletContext, after deployConfig() has been invoked on the WebSocketTestServer but before the WebApplicationContext is refreshed. Issue: SPR-13162
1 parent 8b50750 commit e8c8d2a

File tree

8 files changed

+93
-47
lines changed

8 files changed

+93
-47
lines changed

spring-websocket/src/test/java/org/springframework/web/socket/AbstractWebSocketIntegrationTests.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121

2222
import org.apache.commons.logging.Log;
2323
import org.apache.commons.logging.LogFactory;
24+
2425
import org.junit.After;
2526
import org.junit.Before;
2627
import org.junit.Rule;
@@ -43,6 +44,7 @@
4344
* Base class for WebSocket integration tests.
4445
*
4546
* @author Rossen Stoyanchev
47+
* @author Sam Brannen
4648
*/
4749
public abstract class AbstractWebSocketIntegrationTests {
4850

@@ -85,6 +87,10 @@ public void setup() throws Exception {
8587

8688
this.server.setup();
8789
this.server.deployConfig(this.wac);
90+
// Set ServletContext in WebApplicationContext after deployment but before
91+
// starting the server.
92+
this.wac.setServletContext(this.server.getServletContext());
93+
this.wac.refresh();
8894
this.server.start();
8995
}
9096

spring-websocket/src/test/java/org/springframework/web/socket/JettyWebSocketTestServer.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,8 +17,10 @@
1717
package org.springframework.web.socket;
1818

1919
import java.util.EnumSet;
20+
2021
import javax.servlet.DispatcherType;
2122
import javax.servlet.Filter;
23+
import javax.servlet.ServletContext;
2224

2325
import org.eclipse.jetty.server.Server;
2426
import org.eclipse.jetty.servlet.FilterHolder;
@@ -34,13 +36,16 @@
3436
* Jetty based {@link WebSocketTestServer}.
3537
*
3638
* @author Rossen Stoyanchev
39+
* @author Sam Brannen
3740
*/
3841
public class JettyWebSocketTestServer implements WebSocketTestServer {
3942

4043
private Server jettyServer;
4144

4245
private int port = -1;
4346

47+
private ServletContextHandler contextHandler;
48+
4449

4550
@Override
4651
public void setup() {
@@ -54,21 +59,26 @@ public int getPort() {
5459
}
5560

5661
@Override
57-
public void deployConfig(WebApplicationContext cxt, Filter... filters) {
62+
public void deployConfig(WebApplicationContext wac, Filter... filters) {
5863
Assert.state(this.port != -1, "setup() was never called.");
59-
ServletContextHandler contextHandler = new ServletContextHandler();
60-
ServletHolder servletHolder = new ServletHolder(new DispatcherServlet(cxt));
61-
contextHandler.addServlet(servletHolder, "/");
64+
ServletHolder servletHolder = new ServletHolder(new DispatcherServlet(wac));
65+
this.contextHandler = new ServletContextHandler();
66+
this.contextHandler.addServlet(servletHolder, "/");
6267
for (Filter filter : filters) {
63-
contextHandler.addFilter(new FilterHolder(filter), "/*", getDispatcherTypes());
68+
this.contextHandler.addFilter(new FilterHolder(filter), "/*", getDispatcherTypes());
6469
}
65-
this.jettyServer.setHandler(contextHandler);
70+
this.jettyServer.setHandler(this.contextHandler);
6671
}
6772

6873
private EnumSet<DispatcherType> getDispatcherTypes() {
6974
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC);
7075
}
7176

77+
@Override
78+
public ServletContext getServletContext() {
79+
return this.contextHandler.getServletContext();
80+
}
81+
7282
@Override
7383
public void undeployConfig() {
7484
// Stopping jetty will undeploy the servlet

spring-websocket/src/test/java/org/springframework/web/socket/TomcatWebSocketTestServer.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.IOException;
2121

2222
import javax.servlet.Filter;
23+
import javax.servlet.ServletContext;
2324

2425
import org.apache.catalina.Context;
2526
import org.apache.catalina.LifecycleEvent;
@@ -40,6 +41,7 @@
4041
* Tomcat based {@link WebSocketTestServer}.
4142
*
4243
* @author Rossen Stoyanchev
44+
* @author Sam Brannen
4345
*/
4446
public class TomcatWebSocketTestServer implements WebSocketTestServer {
4547

@@ -106,6 +108,11 @@ public void deployConfig(WebApplicationContext wac, Filter... filters) {
106108
}
107109
}
108110

111+
@Override
112+
public ServletContext getServletContext() {
113+
return this.context.getServletContext();
114+
}
115+
109116
@Override
110117
public void undeployConfig() {
111118
if (this.context != null) {

spring-websocket/src/test/java/org/springframework/web/socket/UndertowTestServer.java

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,12 +16,6 @@
1616

1717
package org.springframework.web.socket;
1818

19-
import java.io.IOException;
20-
import javax.servlet.DispatcherType;
21-
import javax.servlet.Filter;
22-
import javax.servlet.Servlet;
23-
import javax.servlet.ServletException;
24-
2519
import io.undertow.Undertow;
2620
import io.undertow.server.HttpHandler;
2721
import io.undertow.servlet.api.DeploymentInfo;
@@ -30,21 +24,31 @@
3024
import io.undertow.servlet.api.InstanceFactory;
3125
import io.undertow.servlet.api.InstanceHandle;
3226
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
33-
import org.xnio.ByteBufferSlicePool;
34-
import org.xnio.OptionMap;
35-
import org.xnio.Xnio;
27+
28+
import java.io.IOException;
29+
30+
import javax.servlet.DispatcherType;
31+
import javax.servlet.Filter;
32+
import javax.servlet.Servlet;
33+
import javax.servlet.ServletContext;
34+
import javax.servlet.ServletException;
3635

3736
import org.springframework.util.Assert;
3837
import org.springframework.util.SocketUtils;
3938
import org.springframework.web.context.WebApplicationContext;
4039
import org.springframework.web.servlet.DispatcherServlet;
4140

41+
import org.xnio.ByteBufferSlicePool;
42+
import org.xnio.OptionMap;
43+
import org.xnio.Xnio;
44+
4245
import static io.undertow.servlet.Servlets.*;
4346

4447
/**
4548
* Undertow-based {@link WebSocketTestServer}.
4649
*
4750
* @author Rossen Stoyanchev
51+
* @author Sam Brannen
4852
*/
4953
public class UndertowTestServer implements WebSocketTestServer {
5054

@@ -66,9 +70,9 @@ public int getPort() {
6670
}
6771

6872
@Override
69-
public void deployConfig(WebApplicationContext cxt, Filter... filters) {
73+
public void deployConfig(WebApplicationContext wac, Filter... filters) {
7074
Assert.state(this.port != -1, "setup() was never called");
71-
DispatcherServletInstanceFactory servletFactory = new DispatcherServletInstanceFactory(cxt);
75+
DispatcherServletInstanceFactory servletFactory = new DispatcherServletInstanceFactory(wac);
7276
// manually building WebSocketDeploymentInfo in order to avoid class cast exceptions
7377
// with tomcat's implementation when using undertow 1.1.0+
7478
WebSocketDeploymentInfo info = new WebSocketDeploymentInfo();
@@ -104,6 +108,11 @@ public void deployConfig(WebApplicationContext cxt, Filter... filters) {
104108
}
105109
}
106110

111+
@Override
112+
public ServletContext getServletContext() {
113+
return this.manager.getDeployment().getServletContext();
114+
}
115+
107116
@Override
108117
public void undeployConfig() {
109118
this.manager.undeploy();

spring-websocket/src/test/java/org/springframework/web/socket/WebSocketTestServer.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,13 +17,15 @@
1717
package org.springframework.web.socket;
1818

1919
import javax.servlet.Filter;
20+
import javax.servlet.ServletContext;
2021

2122
import org.springframework.web.context.WebApplicationContext;
2223

2324
/**
2425
* Contract for a test server to use for WebSocket integration tests.
2526
*
2627
* @author Rossen Stoyanchev
28+
* @author Sam Brannen
2729
*/
2830
public interface WebSocketTestServer {
2931

@@ -33,6 +35,16 @@ public interface WebSocketTestServer {
3335

3436
void deployConfig(WebApplicationContext cxt, Filter... filters);
3537

38+
/**
39+
* Get the {@link ServletContext} created by the underlying server.
40+
*
41+
* <p>The {@code ServletContext} is only guaranteed to be available
42+
* after {@link #deployConfig} has been invoked.
43+
*
44+
* @since 4.2
45+
*/
46+
ServletContext getServletContext();
47+
3648
void undeployConfig();
3749

3850
void start() throws Exception;

spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/AbstractSockJsIntegrationTests.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.util.concurrent.CountDownLatch;
2727
import java.util.concurrent.LinkedBlockingQueue;
2828
import java.util.concurrent.TimeUnit;
29+
import java.util.function.Supplier;
30+
2931
import javax.servlet.Filter;
3032
import javax.servlet.FilterChain;
3133
import javax.servlet.FilterConfig;
@@ -37,8 +39,10 @@
3739

3840
import org.apache.commons.logging.Log;
3941
import org.apache.commons.logging.LogFactory;
42+
4043
import org.junit.After;
4144
import org.junit.Before;
45+
import org.junit.BeforeClass;
4246
import org.junit.Rule;
4347
import org.junit.Test;
4448
import org.junit.rules.TestName;
@@ -47,6 +51,8 @@
4751
import org.springframework.context.annotation.Bean;
4852
import org.springframework.context.annotation.Configuration;
4953
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
54+
import org.springframework.tests.Assume;
55+
import org.springframework.tests.TestGroup;
5056
import org.springframework.util.concurrent.ListenableFutureCallback;
5157
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
5258
import org.springframework.web.socket.TextMessage;
@@ -63,11 +69,12 @@
6369
import static org.junit.Assert.*;
6470

6571
/**
66-
* Integration tests using the
67-
* {@link org.springframework.web.socket.sockjs.client.SockJsClient}.
72+
* Abstract base class for integration tests using the
73+
* {@link org.springframework.web.socket.sockjs.client.SockJsClient SockJsClient}
6874
* against actual SockJS server endpoints.
6975
*
7076
* @author Rossen Stoyanchev
77+
* @author Sam Brannen
7178
*/
7279
public abstract class AbstractSockJsIntegrationTests {
7380

@@ -88,6 +95,12 @@ public abstract class AbstractSockJsIntegrationTests {
8895
private String baseUrl;
8996

9097

98+
@BeforeClass
99+
public static void performanceTestGroupAssumption() throws Exception {
100+
Assume.group(TestGroup.PERFORMANCE);
101+
}
102+
103+
91104
@Before
92105
public void setup() throws Exception {
93106
logger.debug("Setting up '" + this.testName.getMethodName() + "'");
@@ -97,6 +110,10 @@ public void setup() throws Exception {
97110
this.server = createWebSocketTestServer();
98111
this.server.setup();
99112
this.server.deployConfig(this.wac, this.errorFilter);
113+
// Set ServletContext in WebApplicationContext after deployment but before
114+
// starting the server.
115+
this.wac.setServletContext(this.server.getServletContext());
116+
this.wac.refresh();
100117
this.server.start();
101118
this.baseUrl = "http://localhost:" + this.server.getPort();
102119
}
@@ -142,8 +159,6 @@ protected void initSockJsClient(Transport... transports) {
142159
this.sockJsClient.start();
143160
}
144161

145-
// Temporarily @Ignore failures caused by suspected Jetty bug
146-
147162
@Test
148163
public void echoWebSocket() throws Exception {
149164
testEcho(100, createWebSocketTransport());
@@ -217,9 +232,7 @@ public void fallbackAfterConnectTimeout() throws Exception {
217232
this.errorFilter.sleepDelayMap.put("/xhr_streaming", 10000L);
218233
this.errorFilter.responseStatusMap.put("/xhr_streaming", 503);
219234
initSockJsClient(createXhrTransport());
220-
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
221-
scheduler.afterPropertiesSet();
222-
this.sockJsClient.setConnectTimeoutScheduler(scheduler);
235+
this.sockJsClient.setConnectTimeoutScheduler(this.wac.getBean(ThreadPoolTaskScheduler.class));
223236
WebSocketSession clientSession = sockJsClient.doHandshake(clientHandler, this.baseUrl + "/echo").get();
224237
assertEquals("Fallback didn't occur", XhrClientSockJsSession.class, clientSession.getClass());
225238
TextMessage message = new TextMessage("message1");
@@ -283,14 +296,11 @@ public TestServerHandler testServerHandler() {
283296
}
284297
}
285298

286-
private static interface Condition {
287-
boolean match();
288-
}
289299

290-
private static void awaitEvent(Condition condition, long timeToWait, String description) {
300+
private static void awaitEvent(Supplier<Boolean> condition, long timeToWait, String description) {
291301
long timeToSleep = 200;
292302
for (int i = 0 ; i < Math.floor(timeToWait / timeToSleep); i++) {
293-
if (condition.match()) {
303+
if (condition.get()) {
294304
return;
295305
}
296306
try {

spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/JettySockJsIntegrationTests.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,11 +17,9 @@
1717
package org.springframework.web.socket.sockjs.client;
1818

1919
import org.eclipse.jetty.client.HttpClient;
20-
import org.junit.BeforeClass;
20+
2121
import org.springframework.context.annotation.Bean;
2222
import org.springframework.context.annotation.Configuration;
23-
import org.springframework.tests.Assume;
24-
import org.springframework.tests.TestGroup;
2523
import org.springframework.web.socket.JettyWebSocketTestServer;
2624
import org.springframework.web.socket.client.jetty.JettyWebSocketClient;
2725
import org.springframework.web.socket.server.RequestUpgradeStrategy;
@@ -34,11 +32,6 @@
3432
*/
3533
public class JettySockJsIntegrationTests extends AbstractSockJsIntegrationTests {
3634

37-
@BeforeClass
38-
public static void setUpOnce() throws Exception {
39-
Assume.group(TestGroup.PERFORMANCE);
40-
}
41-
4235
@Override
4336
protected Class<?> upgradeStrategyConfigClass() {
4437
return JettyTestConfig.class;
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
log4j.appender.console=org.apache.log4j.ConsoleAppender
22
log4j.appender.console.layout=org.apache.log4j.PatternLayout
3-
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c][%t] - %m%n
3+
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%-5p] [%c] - %m%n
44

55
log4j.rootCategory=WARN, console
6-
log4j.logger.org.springframework.web=DEBUG
7-
log4j.logger.org.springframework.web.socket=TRACE
8-
log4j.logger.org.springframework.messaging=DEBUG
9-
6+
log4j.logger.org.springframework.web=WARN
7+
log4j.logger.org.springframework.web.socket=WARN
8+
log4j.logger.org.springframework.messaging=WARN

0 commit comments

Comments
 (0)