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 <[email protected]> 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; + } + } +}
