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 
&lt;ajax-response&gt;
+        * 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;
 

Reply via email to