You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2014/03/07 09:22:22 UTC

git commit: WICKET-5529 Add WebSocketBehavior/Resource#onPush() callback method

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 <mg...@apache.org>
Authored: Fri Mar 7 10:21:00 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
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;