You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by re...@apache.org on 2021/05/20 09:00:43 UTC

[wicket] 01/01: create demo page showing how to use push in order to update a component via web-sockets.

This is an automated email from the ASF dual-hosted git repository.

reiern70 pushed a commit to branch update-component-example
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit 0f580b978fa0c254c97954846d87c7330938077c
Author: ernestosemedy <ba...@semedy.com>
AuthorDate: Thu May 20 12:00:23 2021 +0300

    create demo page showing how to use push in order to update a component via web-sockets.
---
 .../apache/wicket/examples/websocket/HomePage.html |   1 +
 .../examples/websocket/JSR356Application.java      |   1 +
 .../WebSocketPushUpdateProgressDemoPage.html       |   8 ++
 .../WebSocketPushUpdateProgressDemoPage.java       |  30 ++++
 .../ProgressBarTogglePanel.html}                   |  30 ++--
 .../websocket/progress/ProgressBarTogglePanel.java | 133 ++++++++++++++++++
 .../websocket/progress/ProgressUpdater.java        | 155 +++++++++++++++++++++
 7 files changed, 338 insertions(+), 20 deletions(-)

diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/HomePage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/HomePage.html
index 3821f67..74b2062 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/HomePage.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/HomePage.html
@@ -29,6 +29,7 @@
 					<li><a href="WebSocketBehaviorDemoPage.html">demo with WebSocketBehavior</a></li>
 					<li><a href="WebSocketResourceDemoPage.html">demo with WebSocketResource</a></li>
 					<li><a href="WebSocketMultiTabResourceDemoPage.html">demo with WebSocketResource and multiple tabs</a></li>
+					<li><a href="WebSocketPushUpdateProgressDemoPage.html">Update a component via push notifications</a></li>
 				</ul>
 			</wicket:link>
 		</wicket:extend>
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java
index bb38205..31615ed 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java
@@ -50,6 +50,7 @@ public class JSR356Application extends WicketExampleApplication
 		setRootRequestMapper(new HttpsMapper(getRootRequestMapper(), new HttpsConfig(8080, 8443)));
 
 		mountPage("/behavior", WebSocketBehaviorDemoPage.class);
+		mountPage("/progress", WebSocketPushUpdateProgressDemoPage.class);
 		mountPage("/resource", WebSocketResourceDemoPage.class);
 		mountPage("/resource-multi-tab", WebSocketMultiTabResourceDemoPage.class);
 
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.html
new file mode 100644
index 0000000..55210d3
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.html
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+<body>
+<wicket:extend>
+    <div wicket:id="progressPanel"></div>
+</wicket:extend>
+</body>
+</html>
\ No newline at end of file
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java
new file mode 100644
index 0000000..01d16b2
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.examples.websocket;
+
+import org.apache.wicket.examples.WicketExamplePage;
+import org.apache.wicket.examples.websocket.progress.ProgressBarTogglePanel;
+import org.apache.wicket.protocol.https.RequireHttps;
+
+@RequireHttps
+public class WebSocketPushUpdateProgressDemoPage extends WicketExamplePage
+{
+	public WebSocketPushUpdateProgressDemoPage()
+	{
+		add(new ProgressBarTogglePanel("progressPanel"));
+	}
+}
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/HomePage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.html
similarity index 56%
copy from wicket-examples/src/main/java/org/apache/wicket/examples/websocket/HomePage.html
copy to wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.html
index 3821f67..971f7f2 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/HomePage.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.html
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" ?>
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -15,22 +15,12 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE html>
-<html xmlns:wicket="http://wicket.apache.org">
-	<head>
-		<meta charset="utf-8" />
-        <title>Apache Wicket Native WebSocket demos</title>
-	</head>
-	<body>
-		<wicket:extend>
-
-			<wicket:link>
-				<ul>
-					<li><a href="WebSocketBehaviorDemoPage.html">demo with WebSocketBehavior</a></li>
-					<li><a href="WebSocketResourceDemoPage.html">demo with WebSocketResource</a></li>
-					<li><a href="WebSocketMultiTabResourceDemoPage.html">demo with WebSocketResource and multiple tabs</a></li>
-				</ul>
-			</wicket:link>
-		</wicket:extend>
-	</body>
-</html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+<body>
+<wicket:panel>
+    <div><a wicket:id="hideShowProgress"></a></div>
+    <div><a wicket:id="cancelRestartTask"></a></div>
+    <div wicket:id="progressBar"></div>
+</wicket:panel>
+</body>
+</html>
\ No newline at end of file
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.java
new file mode 100644
index 0000000..3fd364a
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.examples.websocket.progress;
+
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.examples.websocket.JSR356Application;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.protocol.ws.api.WebSocketBehavior;
+import org.apache.wicket.protocol.ws.api.event.WebSocketPushPayload;
+import org.apache.wicket.protocol.ws.api.message.ConnectedMessage;
+
+public class ProgressBarTogglePanel extends Panel
+{
+
+    private int progress = 0;
+    private boolean showProgress = true;
+    private ProgressUpdater.ProgressUpdateTask progressUpdateTask;
+
+    public ProgressBarTogglePanel(String id)
+    {
+        super(id);
+
+        setOutputMarkupId(true);
+
+        add(new WebSocketBehavior()
+        {
+            @Override
+            protected void onConnect(ConnectedMessage message) {
+                progressUpdateTask = ProgressBarTogglePanel.startProgressTask(message);
+            }
+        });
+
+        add(new AjaxLink<Void>("hideShowProgress")
+        {
+            @Override
+            public void onClick(AjaxRequestTarget target)
+            {
+                showProgress = !showProgress;
+                target.add(ProgressBarTogglePanel.this);
+            }
+        }.setBody(new IModel<String>()
+        {
+            @Override
+            public String getObject()
+            {
+                return showProgress ? "Hide progress" : "Show progress";
+            }
+        }));
+
+        add(new AjaxLink<Void>("cancelRestartTask")
+        {
+            @Override
+            public void onClick(AjaxRequestTarget target)
+            {
+                if (progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled())
+                {
+                    progressUpdateTask.cancel();
+                }
+                else
+                {
+                    ScheduledExecutorService service = JSR356Application.get().getScheduledExecutorService();
+                    ProgressUpdater.restart(progressUpdateTask, service);
+                }
+                target.add(ProgressBarTogglePanel.this);
+            }
+        }.setBody(new IModel<String>()
+        {
+            @Override
+            public String getObject()
+            {
+                return progressUpdateTask != null && progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled() ? "Cancel task" : "Restart task";
+            }
+        }));
+
+        add(new Label("progressBar", new IModel<String>()
+        {
+            @Override
+            public String getObject()
+            {
+                return progressUpdateTask != null && progressUpdateTask.isRunning() ? "Background Task is " + progress + "% completed" : "No task is running";
+            }
+        })
+        {
+            @Override
+            protected void onConfigure()
+            {
+                super.onConfigure();
+                setVisible(showProgress);
+            }
+        });
+    }
+
+    public static ProgressUpdater.ProgressUpdateTask startProgressTask(ConnectedMessage message)
+    {
+        ScheduledExecutorService service = JSR356Application.get().getScheduledExecutorService();
+        return ProgressUpdater.start(message, service);
+    }
+
+    @Override
+    public void onEvent(IEvent<?> event)
+    {
+        if (event.getPayload() instanceof WebSocketPushPayload)
+        {
+            WebSocketPushPayload wsEvent = (WebSocketPushPayload) event.getPayload();
+            if (wsEvent.getMessage() instanceof ProgressUpdater.ProgressUpdate)
+            {
+                ProgressUpdater.ProgressUpdate progressUpdate = (ProgressUpdater.ProgressUpdate)wsEvent.getMessage();
+                progress = progressUpdate.getProgress();
+                wsEvent.getHandler().add(this);
+            }
+        }
+    }
+}
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressUpdater.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressUpdater.java
new file mode 100644
index 0000000..e681f92
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressUpdater.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.examples.websocket.progress;
+
+import java.io.Serializable;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.protocol.ws.WebSocketSettings;
+import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
+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.protocol.ws.api.registry.IWebSocketConnectionRegistry;
+
+/**
+ * A helper class that uses the web connection to push components updates to the client.
+ */
+public class ProgressUpdater
+{
+	public static ProgressUpdateTask start(ConnectedMessage message, ScheduledExecutorService scheduledExecutorService)
+	{
+		// create an asynchronous task that will write the data to the client
+		ProgressUpdateTask progressUpdateTask = new ProgressUpdateTask(message.getApplication(), message.getSessionId(), message.getKey());
+        scheduledExecutorService.schedule(progressUpdateTask, 1, TimeUnit.SECONDS);
+		return progressUpdateTask;
+	}
+
+	public static void restart(ProgressUpdateTask progressUpdateTask, ScheduledExecutorService scheduledExecutorService) {
+		scheduledExecutorService.schedule(progressUpdateTask, 1, TimeUnit.SECONDS);
+	}
+
+	/**
+	 * A push message used to update progress.
+	 */
+	public static class ProgressUpdate implements IWebSocketPushMessage
+	{
+
+		private final int progress;
+
+		public ProgressUpdate(int progress)
+		{
+			this.progress = progress;
+		}
+
+		public int getProgress()
+		{
+			return progress;
+		}
+	}
+
+	/**
+	 * A task that sends data to the client by pushing it to the web socket connection
+	 */
+	public static class ProgressUpdateTask implements Runnable, Serializable
+	{
+		/**
+		 * The following fields are needed to be able to lookup the IWebSocketConnection from
+		 * IWebSocketConnectionRegistry
+		 */
+		private final String applicationName;
+		private final String sessionId;
+		private final IKey key;
+
+		private boolean canceled = false;
+		private boolean running = false;
+
+		private ProgressUpdateTask(Application application, String sessionId, IKey key)
+		{
+			this.applicationName = application.getName();
+			this.sessionId = sessionId;
+			this.key = key;
+		}
+
+		@Override
+		public void run()
+		{
+			running = true;
+			Application application = Application.get(applicationName);
+			WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application);
+			IWebSocketConnectionRegistry webSocketConnectionRegistry = webSocketSettings.getConnectionRegistry();
+
+			int progress = 0;
+
+			while (progress <= 100)
+			{
+				IWebSocketConnection connection = webSocketConnectionRegistry.getConnection(application, sessionId, key);
+				try
+				{
+					if (connection == null || !connection.isOpen())
+					{
+						running = false;
+						// stop if the web socket connection is closed
+						return;
+					}
+
+					if (canceled)
+					{
+						canceled = false;
+						running = false;
+						return;
+					}
+
+					WebSocketPushBroadcaster broadcaster =
+							new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry());
+					broadcaster.broadcast(new ConnectedMessage(application, sessionId, key), new ProgressUpdate(progress));
+
+					// sleep for a while to simulate work
+					TimeUnit.SECONDS.sleep(1);
+					progress++;
+				}
+				catch (InterruptedException x)
+				{
+					Thread.currentThread().interrupt();
+					break;
+				}
+				catch (Exception e)
+				{
+					e.printStackTrace();
+					break;
+				}
+			}
+			running = false;
+		}
+
+		public boolean isRunning() {
+			return running;
+		}
+
+		public boolean isCanceled() {
+			return canceled;
+		}
+
+		public void cancel() {
+			this.canceled = true;
+			this.running = false;
+		}
+	}
+}