Browse Source

Update WebSocket client SmartLifecycle support

Before this change WebSocketConnectionManager delegated SmartLifecycle
methods to the client instance it contained. After this change
WebSocketClient implementations are expected to implement Lifecycle
(rather than SmartLifecycle).

The need for this is even more evident with SockJsClient, which is a
WebSocketClient implementation and contains a WebSocketTransport that
in turn contains the actual WebSocketClient. In this case
WebSocketConnectionManager as the top level container is the obvious
place to configure autostartup while Lifecycle events can be
propagated all the way down to the root WebSocketClient.
pull/588/merge
Rossen Stoyanchev 12 years ago
parent
commit
d73c1d5693
  1. 8
      spring-websocket/src/main/java/org/springframework/web/socket/client/ConnectionManagerSupport.java
  2. 14
      spring-websocket/src/main/java/org/springframework/web/socket/client/WebSocketConnectionManager.java
  3. 37
      spring-websocket/src/main/java/org/springframework/web/socket/client/jetty/JettyWebSocketClient.java
  4. 68
      spring-websocket/src/test/java/org/springframework/web/socket/client/WebSocketConnectionManagerTests.java

8
spring-websocket/src/main/java/org/springframework/web/socket/client/ConnectionManagerSupport.java

@ -42,7 +42,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle { @@ -42,7 +42,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle {
private boolean autoStartup = false;
private boolean isRunning = false;
private boolean running = false;
private int phase = Integer.MAX_VALUE;
@ -104,7 +104,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle { @@ -104,7 +104,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle {
@Override
public boolean isRunning() {
synchronized (this.lifecycleMonitor) {
return this.isRunning;
return this.running;
}
}
@ -125,7 +125,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle { @@ -125,7 +125,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle {
if (logger.isInfoEnabled()) {
logger.info("Starting " + this.getClass().getSimpleName());
}
this.isRunning = true;
this.running = true;
openConnection();
}
}
@ -146,7 +146,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle { @@ -146,7 +146,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle {
logger.error("Failed to stop WebSocket connection", e);
}
finally {
this.isRunning = false;
this.running = false;
}
}
}

14
spring-websocket/src/main/java/org/springframework/web/socket/client/WebSocketConnectionManager.java

@ -1,5 +1,5 @@ @@ -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.
@ -18,6 +18,7 @@ package org.springframework.web.socket.client; @@ -18,6 +18,7 @@ package org.springframework.web.socket.client;
import java.util.List;
import org.springframework.context.Lifecycle;
import org.springframework.context.SmartLifecycle;
import org.springframework.http.HttpHeaders;
import org.springframework.util.concurrent.ListenableFuture;
@ -46,8 +47,6 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport { @@ -46,8 +47,6 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport {
private WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
private final boolean syncClientLifecycle;
public WebSocketConnectionManager(WebSocketClient client,
WebSocketHandler webSocketHandler, String uriTemplate, Object... uriVariables) {
@ -55,7 +54,6 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport { @@ -55,7 +54,6 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport {
super(uriTemplate, uriVariables);
this.client = client;
this.webSocketHandler = decorateWebSocketHandler(webSocketHandler);
this.syncClientLifecycle = ((client instanceof SmartLifecycle) && !((SmartLifecycle) client).isRunning());
}
@ -116,16 +114,16 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport { @@ -116,16 +114,16 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport {
@Override
public void startInternal() {
if (this.syncClientLifecycle) {
((SmartLifecycle) this.client).start();
if (this.client instanceof Lifecycle && !((Lifecycle) client).isRunning()) {
((Lifecycle) client).start();
}
super.startInternal();
}
@Override
public void stopInternal() throws Exception {
if (this.syncClientLifecycle) {
((SmartLifecycle) this.client).stop();
if (this.client instanceof Lifecycle && ((Lifecycle) client).isRunning()) {
((Lifecycle) client).stop();
}
super.stopInternal();
}

37
spring-websocket/src/main/java/org/springframework/web/socket/client/jetty/JettyWebSocketClient.java

@ -26,7 +26,7 @@ import java.util.concurrent.Future; @@ -26,7 +26,7 @@ import java.util.concurrent.Future;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.Lifecycle;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
@ -47,17 +47,18 @@ import org.springframework.web.util.UriComponentsBuilder; @@ -47,17 +47,18 @@ import org.springframework.web.util.UriComponentsBuilder;
* Initiates WebSocket requests to a WebSocket server programmatically
* through the Jetty WebSocket API.
*
* <p>As of 4.1 this class implements {@link Lifecycle} rather than
* {@link org.springframework.context.SmartLifecycle}. Use
* {@link org.springframework.web.socket.client.WebSocketConnectionManager
* WebSocketConnectionManager} instead to auto-start a WebSocket connection.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
public class JettyWebSocketClient extends AbstractWebSocketClient implements SmartLifecycle {
public class JettyWebSocketClient extends AbstractWebSocketClient implements Lifecycle {
private final org.eclipse.jetty.websocket.client.WebSocketClient client;
private boolean autoStartup = true;
private int phase = Integer.MAX_VALUE;
private final Object lifecycleMonitor = new Object();
private AsyncListenableTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
@ -98,24 +99,6 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Sma @@ -98,24 +99,6 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Sma
return this.taskExecutor;
}
public void setAutoStartup(boolean autoStartup) {
this.autoStartup = autoStartup;
}
@Override
public boolean isAutoStartup() {
return this.autoStartup;
}
public void setPhase(int phase) {
this.phase = phase;
}
@Override
public int getPhase() {
return this.phase;
}
@Override
public boolean isRunning() {
synchronized (this.lifecycleMonitor) {
@ -157,12 +140,6 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Sma @@ -157,12 +140,6 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Sma
}
}
@Override
public void stop(Runnable callback) {
this.stop();
callback.run();
}
@Override
public ListenableFuture<WebSocketSession> doHandshake(WebSocketHandler webSocketHandler,
String uriTemplate, Object... uriVars) {

68
spring-websocket/src/test/java/org/springframework/web/socket/client/WebSocketConnectionManagerTests.java

@ -1,5 +1,5 @@ @@ -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.
@ -19,17 +19,16 @@ package org.springframework.web.socket.client; @@ -19,17 +19,16 @@ package org.springframework.web.socket.client;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import org.junit.Test;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.Lifecycle;
import org.springframework.http.HttpHeaders;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.WebSocketHttpHeaders;
import org.springframework.web.util.UriComponentsBuilder;
@ -43,13 +42,13 @@ import static org.junit.Assert.*; @@ -43,13 +42,13 @@ import static org.junit.Assert.*;
*/
public class WebSocketConnectionManagerTests {
@Test
public void openConnection() throws Exception {
List<String> subprotocols = Arrays.asList("abc");
TestLifecycleWebSocketClient client = new TestLifecycleWebSocketClient(false);
WebSocketHandler handler = new AbstractWebSocketHandler() {
};
WebSocketHandler handler = new TextWebSocketHandler();
WebSocketConnectionManager manager = new WebSocketConnectionManager(client, handler , "/path/{id}", "123");
manager.setSubProtocols(subprotocols);
@ -68,10 +67,9 @@ public class WebSocketConnectionManagerTests { @@ -68,10 +67,9 @@ public class WebSocketConnectionManagerTests {
}
@Test
public void syncClientLifecycle() throws Exception {
public void clientLifecycle() throws Exception {
TestLifecycleWebSocketClient client = new TestLifecycleWebSocketClient(false);
WebSocketHandler handler = new AbstractWebSocketHandler() {
};
WebSocketHandler handler = new TextWebSocketHandler();
WebSocketConnectionManager manager = new WebSocketConnectionManager(client, handler , "/a");
manager.startInternal();
@ -81,23 +79,8 @@ public class WebSocketConnectionManagerTests { @@ -81,23 +79,8 @@ public class WebSocketConnectionManagerTests {
assertFalse(client.isRunning());
}
@Test
public void dontSyncClientLifecycle() throws Exception {
TestLifecycleWebSocketClient client = new TestLifecycleWebSocketClient(true);
WebSocketHandler handler = new AbstractWebSocketHandler() {
};
WebSocketConnectionManager manager = new WebSocketConnectionManager(client, handler , "/a");
manager.startInternal();
assertTrue(client.isRunning());
manager.stopInternal();
assertTrue(client.isRunning());
}
private static class TestLifecycleWebSocketClient implements WebSocketClient, SmartLifecycle {
private static class TestLifecycleWebSocketClient implements WebSocketClient, Lifecycle {
private boolean running;
@ -128,42 +111,17 @@ public class WebSocketConnectionManagerTests { @@ -128,42 +111,17 @@ public class WebSocketConnectionManagerTests {
}
@Override
public int getPhase() {
return 0;
}
@Override
public boolean isAutoStartup() {
return false;
}
@Override
public void stop(Runnable callback) {
this.running = false;
}
@Override
public ListenableFuture<WebSocketSession> doHandshake(WebSocketHandler webSocketHandler,
String uriTemplate, Object... uriVars) {
public ListenableFuture<WebSocketSession> doHandshake(WebSocketHandler handler, String uriTemplate, Object... uriVars) {
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).buildAndExpand(uriVars).encode().toUri();
return doHandshake(webSocketHandler, null, uri);
return doHandshake(handler, null, uri);
}
@Override
public ListenableFuture<WebSocketSession> doHandshake(WebSocketHandler webSocketHandler,
WebSocketHttpHeaders headers, URI uri) {
this.webSocketHandler = webSocketHandler;
public ListenableFuture<WebSocketSession> doHandshake(WebSocketHandler handler, WebSocketHttpHeaders headers, URI uri) {
this.webSocketHandler = handler;
this.headers = headers;
this.uri = uri;
return new ListenableFutureTask<WebSocketSession>(new Callable<WebSocketSession>() {
@Override
public WebSocketSession call() throws Exception {
return null;
}
});
return new ListenableFutureTask<>(() -> null);
}
}

Loading…
Cancel
Save