Repository: wicket Updated Branches: refs/heads/master d2695345f -> 13d03307a
WICKET-5529 Add WebSocketBehavior/Resource#onPush() callback method Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/13d03307 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/13d03307 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/13d03307 Branch: refs/heads/master Commit: 13d03307aeb6a562922169803cf80ee5c804c3b1 Parents: d269534 Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Fri Mar 7 10:21:00 2014 +0200 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Fri Mar 7 10:21:00 2014 +0200 ---------------------------------------------------------------------- .../protocol/ws/api/WebSocketBehavior.java | 55 +++++++++++++++++++- .../ws/api/WebSocketRequestHandler.java | 17 +++++- .../protocol/ws/api/WebSocketResource.java | 51 ++++++++++++++++++ .../ws/util/tester/WebSocketTester.java | 43 ++++++++++++++- .../util/tester/WebSocketBehaviorTestPage.java | 20 +++++++ .../tester/WebSocketTesterBehaviorTest.java | 50 ++++++------------ 6 files changed, 197 insertions(+), 39 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/13d03307/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java ---------------------------------------------------------------------- diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java index d33957b..2f8c67c 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java @@ -22,10 +22,12 @@ import org.apache.wicket.protocol.ws.api.event.WebSocketBinaryPayload; import org.apache.wicket.protocol.ws.api.event.WebSocketClosedPayload; import org.apache.wicket.protocol.ws.api.event.WebSocketConnectedPayload; import org.apache.wicket.protocol.ws.api.event.WebSocketPayload; +import org.apache.wicket.protocol.ws.api.event.WebSocketPushPayload; import org.apache.wicket.protocol.ws.api.event.WebSocketTextPayload; import org.apache.wicket.protocol.ws.api.message.BinaryMessage; import org.apache.wicket.protocol.ws.api.message.ClosedMessage; import org.apache.wicket.protocol.ws.api.message.ConnectedMessage; +import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage; import org.apache.wicket.protocol.ws.api.message.TextMessage; /** @@ -71,25 +73,74 @@ public abstract class WebSocketBehavior extends BaseWebSocketBehavior } else if (wsPayload instanceof WebSocketClosedPayload) { - WebSocketClosedPayload connectedPayload = (WebSocketClosedPayload) wsPayload; - ClosedMessage message = connectedPayload.getMessage(); + WebSocketClosedPayload closedPayload = (WebSocketClosedPayload) wsPayload; + ClosedMessage message = closedPayload.getMessage(); onClose(message); } + else if (wsPayload instanceof WebSocketPushPayload) + { + WebSocketPushPayload pushPayload = (WebSocketPushPayload) wsPayload; + IWebSocketPushMessage message = pushPayload.getMessage(); + onPush(webSocketHandler, message); + } } } + /** + * A callback method called when there is a message pushed/broadcasted by the + * server, e.g. pushed by a backend service + * + * @param handler + * The request handler that can be used to send messages to the client + * @param message + * The message pushed/broadcasted by the server + */ + protected void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) + { + } + + /** + * A callback method called when a WebSocket client has connected to the endpoint + * handled by this WebSocketBehavior + * + * @param message + * the connect message with the info about the client + */ protected void onConnect(ConnectedMessage message) { } + /** + * A callback method called when a WebSocket client has closed the connection + * to the endpoint handled by this WebSocketBehavior + * + * @param message + * the close message with the info about the client + */ protected void onClose(ClosedMessage message) { } + /** + * A callback method called when there is a text message sent by the client + * + * @param handler + * The request handler that can be used to send messages back to the client + * @param message + * The text message sent by the client + */ protected void onMessage(WebSocketRequestHandler handler, TextMessage message) { } + /** + * A callback method called when there is a binary message sent by the client + * + * @param handler + * The request handler that can be used to send messages back to the client + * @param binaryMessage + * The binary message sent by the client + */ protected void onMessage(WebSocketRequestHandler handler, BinaryMessage binaryMessage) { } http://git-wip-us.apache.org/repos/asf/wicket/blob/13d03307/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java ---------------------------------------------------------------------- diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java index 8151480..1363866 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java @@ -18,6 +18,7 @@ package org.apache.wicket.protocol.ws.api; import java.io.IOException; import java.util.Collection; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; @@ -56,6 +57,12 @@ public class WebSocketRequestHandler implements AjaxRequestTarget, IWebSocketReq private final AbstractAjaxResponse ajaxResponse; + /** + * A flag indicating that there is data to be written to construct an <ajax-response> + * There is no need to push empty Ajax response if only #push() is used + */ + private final AtomicBoolean hasData = new AtomicBoolean(false); + private PageLogData logData; public WebSocketRequestHandler(final Component component, final IWebSocketConnection connection) @@ -119,6 +126,7 @@ public class WebSocketRequestHandler implements AjaxRequestTarget, IWebSocketReq @Override public void add(Component component, String markupId) { + hasData.set(true); ajaxResponse.add(component, markupId); } @@ -164,12 +172,14 @@ public class WebSocketRequestHandler implements AjaxRequestTarget, IWebSocketReq @Override public void appendJavaScript(CharSequence javascript) { + hasData.set(true); ajaxResponse.appendJavaScript(javascript); } @Override public void prependJavaScript(CharSequence javascript) { + hasData.set(true); ajaxResponse.prependJavaScript(javascript); } @@ -200,6 +210,7 @@ public class WebSocketRequestHandler implements AjaxRequestTarget, IWebSocketReq @Override public IHeaderResponse getHeaderResponse() { + hasData.set(true); return ajaxResponse.getHeaderResponse(); } @@ -256,7 +267,10 @@ public class WebSocketRequestHandler implements AjaxRequestTarget, IWebSocketReq @Override public void respond(IRequestCycle requestCycle) { - ajaxResponse.writeTo(requestCycle.getResponse(), "UTF-8"); + if (hasData.get()) + { + ajaxResponse.writeTo(requestCycle.getResponse(), "UTF-8"); + } } @Override @@ -268,5 +282,6 @@ public class WebSocketRequestHandler implements AjaxRequestTarget, IWebSocketReq } ajaxResponse.detach(requestCycle); + hasData.set(false); } } http://git-wip-us.apache.org/repos/asf/wicket/blob/13d03307/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java ---------------------------------------------------------------------- diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java index d17914c..1db09f9 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java @@ -20,10 +20,12 @@ import org.apache.wicket.protocol.ws.api.event.WebSocketBinaryPayload; import org.apache.wicket.protocol.ws.api.event.WebSocketClosedPayload; import org.apache.wicket.protocol.ws.api.event.WebSocketConnectedPayload; import org.apache.wicket.protocol.ws.api.event.WebSocketPayload; +import org.apache.wicket.protocol.ws.api.event.WebSocketPushPayload; import org.apache.wicket.protocol.ws.api.event.WebSocketTextPayload; import org.apache.wicket.protocol.ws.api.message.BinaryMessage; import org.apache.wicket.protocol.ws.api.message.ClosedMessage; import org.apache.wicket.protocol.ws.api.message.ConnectedMessage; +import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage; import org.apache.wicket.protocol.ws.api.message.TextMessage; import org.apache.wicket.request.resource.IResource; @@ -60,20 +62,69 @@ public abstract class WebSocketResource implements IResource ClosedMessage message = connectedPayload.getMessage(); onClose(message); } + else if (payload instanceof WebSocketPushPayload) + { + WebSocketPushPayload pushPayload = (WebSocketPushPayload) payload; + IWebSocketPushMessage message = pushPayload.getMessage(); + onPush(webSocketHandler, message); + } + } + + /** + * A callback method called when there is a message pushed/broadcasted by the + * server, e.g. pushed by a backend service + * + * @param handler + * The request handler that can be used to send messages to the client + * @param message + * The message pushed/broadcasted by the server + */ + protected void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) + { } + /** + * A callback method called when a WebSocket client has connected to the endpoint + * handled by this WebSocketBehavior + * + * @param message + * the connect message with the info about the client + */ protected void onConnect(ConnectedMessage message) { } + /** + * A callback method called when a WebSocket client has closed the connection + * to the endpoint handled by this WebSocketBehavior + * + * @param message + * the close message with the info about the client + */ protected void onClose(ClosedMessage message) { } + /** + * A callback method called when there is a text message sent by the client + * + * @param handler + * The request handler that can be used to send messages back to the client + * @param message + * The text message sent by the client + */ protected void onMessage(WebSocketRequestHandler handler, TextMessage message) { } + /** + * A callback method called when there is a binary message sent by the client + * + * @param handler + * The request handler that can be used to send messages back to the client + * @param binaryMessage + * The binary message sent by the client + */ protected void onMessage(WebSocketRequestHandler handler, BinaryMessage binaryMessage) { } http://git-wip-us.apache.org/repos/asf/wicket/blob/13d03307/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTester.java ---------------------------------------------------------------------- diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTester.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTester.java index 4f8a9b5..69aa114 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTester.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTester.java @@ -16,9 +16,15 @@ */ package org.apache.wicket.protocol.ws.util.tester; +import org.apache.wicket.Application; import org.apache.wicket.Page; import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.protocol.ws.WebSocketSettings; import org.apache.wicket.protocol.ws.api.IWebSocketProcessor; +import org.apache.wicket.protocol.ws.api.WebSocketPushBroadcaster; +import org.apache.wicket.protocol.ws.api.message.ConnectedMessage; +import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage; +import org.apache.wicket.protocol.ws.api.registry.IKey; import org.apache.wicket.util.lang.Args; import org.apache.wicket.util.tester.WicketTester; @@ -124,9 +130,44 @@ public class WebSocketTester socketProcessor.onMessage(message, offset, length); } + /** + * Broadcasts/pushes a message to specific web socket connection + * + * @param application + * The application where the web socket connection is registered + * @param sessionId + * The id of the http session with which the web socket connection is registered + * @param key + * The key with which the web socket connection is registered + * @param message + * The message to broadcast/push + */ + public void broadcast(Application application, String sessionId, IKey key, IWebSocketPushMessage message) + { + WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application); + WebSocketPushBroadcaster broadcaster = new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry()); + ConnectedMessage wsMessage = new ConnectedMessage(application, sessionId, key); + broadcaster.broadcast(wsMessage, message); + } + + /** + * Broadcasts/pushes a message to all active web socket connections + * + * @param application + * The application where the web socket connection is registered + * @param message + * The message to broadcast/push + */ + public void broadcastAll(Application application, IWebSocketPushMessage message) + { + WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application); + WebSocketPushBroadcaster broadcaster = new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry()); + broadcaster.broadcastAll(application, message); + } + public void destroy() { - socketProcessor.onClose(0, "Closed by WicketTester"); + socketProcessor.onClose(0, "Closed by WebSocketTester"); } /** http://git-wip-us.apache.org/repos/asf/wicket/blob/13d03307/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketBehaviorTestPage.java ---------------------------------------------------------------------- diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketBehaviorTestPage.java b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketBehaviorTestPage.java index affe977..6394850 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketBehaviorTestPage.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketBehaviorTestPage.java @@ -22,10 +22,12 @@ import org.apache.wicket.markup.IMarkupResourceStreamProvider; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.protocol.ws.api.WebSocketBehavior; import org.apache.wicket.protocol.ws.api.message.BinaryMessage; +import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage; import org.apache.wicket.protocol.ws.api.message.TextMessage; import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.resource.StringResourceStream; import org.apache.wicket.util.string.Strings; +import org.hamcrest.CoreMatchers; import org.junit.Assert; /** @@ -75,6 +77,24 @@ class WebSocketBehaviorTestPage extends WebPage implements IMarkupResourceStream }); } + WebSocketBehaviorTestPage(final WebSocketTesterBehaviorTest.BroadcastMessage expectedMessage) + { + add(new WebSocketBehavior() + { + @Override + protected void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) + { + Assert.assertThat(message, CoreMatchers.instanceOf(WebSocketTesterBehaviorTest.BroadcastMessage.class)); + WebSocketTesterBehaviorTest.BroadcastMessage broadcastMessage = (WebSocketTesterBehaviorTest.BroadcastMessage) message; + Assert.assertSame(expectedMessage, broadcastMessage); + + String pushedMessage = broadcastMessage.getText().toUpperCase(); + + handler.push(pushedMessage); + } + }); + } + @Override public IResourceStream getMarkupResourceStream(MarkupContainer container, Class<?> containerClass) { http://git-wip-us.apache.org/repos/asf/wicket/blob/13d03307/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java ---------------------------------------------------------------------- diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java index 64ca565..c6516cb 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java @@ -19,11 +19,6 @@ package org.apache.wicket.protocol.ws.util.tester; import java.io.UnsupportedEncodingException; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.wicket.event.IEvent; -import org.apache.wicket.protocol.ws.WebSocketSettings; -import org.apache.wicket.protocol.ws.api.WebSocketPushBroadcaster; -import org.apache.wicket.protocol.ws.api.event.WebSocketPushPayload; -import org.apache.wicket.protocol.ws.api.message.ConnectedMessage; import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage; import org.apache.wicket.protocol.ws.api.registry.PageIdKey; import org.apache.wicket.util.string.Strings; @@ -95,7 +90,8 @@ public class WebSocketTesterBehaviorTest extends Assert WebSocketBehaviorTestPage page = new WebSocketBehaviorTestPage(expectedMessage, offset, length); tester.startPage(page); - WebSocketTester webSocketTester = new WebSocketTester(tester, page) { + WebSocketTester webSocketTester = new WebSocketTester(tester, page) + { @Override protected void onOutMessage(byte[] message, int off, int len) { @@ -122,46 +118,30 @@ public class WebSocketTesterBehaviorTest extends Assert @Test public void serverSideBroadcast() { - final String message = "Broadcasted Message"; - + final String expectedMessage = "Broadcasted Message"; + final BroadcastMessage broadcastMessage = new BroadcastMessage(expectedMessage); final AtomicBoolean messageReceived = new AtomicBoolean(false); - WebSocketBehaviorTestPage page = new WebSocketBehaviorTestPage() + WebSocketBehaviorTestPage page = new WebSocketBehaviorTestPage(broadcastMessage); + tester.startPage(page); + + WebSocketTester webSocketTester = new WebSocketTester(tester, page) { @Override - public void onEvent(IEvent<?> event) + protected void onOutMessage(String message) { - super.onEvent(event); - - if (event.getPayload() instanceof WebSocketPushPayload) - { - WebSocketPushPayload payload = (WebSocketPushPayload) event.getPayload(); - - if (payload.getMessage() instanceof BroadcastMessage) - { - BroadcastMessage broadcastMessage = (BroadcastMessage) payload.getMessage(); - if (message.equals(broadcastMessage.getText())) - { - messageReceived.set(true); - } - } - } + assertEquals(expectedMessage.toUpperCase(), message); + messageReceived.set(true); } }; - tester.startPage(page); - tester.getSession().bind(); - - new WebSocketTester(tester, page); - WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(tester.getApplication()); - WebSocketPushBroadcaster broadcaster = new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry()); - ConnectedMessage wsMessage = new ConnectedMessage(tester.getApplication(), - tester.getHttpSession().getId(), new PageIdKey(page.getPageId())); - broadcaster.broadcast(wsMessage, new BroadcastMessage(message)); + webSocketTester.broadcast(tester.getApplication(), tester.getHttpSession().getId(), + new PageIdKey(page.getPageId()), broadcastMessage); assertEquals(true, messageReceived.get()); + webSocketTester.destroy(); } - private static class BroadcastMessage implements IWebSocketPushMessage + static class BroadcastMessage implements IWebSocketPushMessage { private final String message;
