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/11/11 10:04:44 UTC
[wicket] branch master updated: WICKET-6930: This commit adds: 1)
allow to skip sending empty WS messages 2) pass page class as a kind of
context that can be used to send a web socket to different pages + example
of updating a component in a given page (not dependent on page ID)
This is an automated email from the ASF dual-hosted git repository.
reiern70 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/master by this push:
new f707376 WICKET-6930: This commit adds: 1) allow to skip sending empty WS messages 2) pass page class as a kind of context that can be used to send a web socket to different pages + example of updating a component in a given page (not dependent on page ID)
f707376 is described below
commit f7073760881dbac26e7c94a6f9a67d09bb599cf6
Author: ernestosemedy <ba...@semedy.com>
AuthorDate: Thu May 20 12:00:23 2021 +0300
WICKET-6930: This commit adds: 1) allow to skip sending empty WS messages 2) pass page class as a kind of context that can be used to send a web socket to different pages + example of updating a component in a given page (not dependent on page ID)
---
.../org/apache/wicket/page/PartialPageUpdate.java | 8 +
.../apache/wicket/examples/websocket/HomePage.html | 1 +
.../examples/websocket/JSR356Application.java | 12 +-
.../wicket/examples/websocket/JSR356Session.java | 66 ++++++++
.../websocket/WebSocketBehaviorDemoPage.java | 2 -
.../WebSocketMultiTabResourceDemoPage.java | 2 -
.../WebSocketPushUpdateProgressDemoPage.html | 8 +
...va => WebSocketPushUpdateProgressDemoPage.java} | 15 +-
.../websocket/WebSocketResourceDemoPage.java | 2 -
.../ProgressBarTogglePanel.html} | 30 ++--
.../websocket/progress/ProgressBarTogglePanel.java | 111 +++++++++++++
.../websocket/progress/ProgressUpdater.java | 177 +++++++++++++++++++++
.../ws/api/AbstractWebSocketConnection.java | 2 +-
.../ws/api/AbstractWebSocketProcessor.java | 33 ++--
.../protocol/ws/api/BaseWebSocketBehavior.java | 12 ++
.../protocol/ws/api/WebSocketPushBroadcaster.java | 68 ++++++++
.../protocol/ws/api/WebSocketRequestHandler.java | 17 +-
.../api/registry/{IKey.java => AbstractKey.java} | 21 ++-
.../wicket/protocol/ws/api/registry/IKey.java | 8 +-
.../api/registry/IWebSocketConnectionRegistry.java | 26 ++-
.../wicket/protocol/ws/api/registry/PageIdKey.java | 13 +-
.../protocol/ws/api/registry/ResourceNameKey.java | 8 +-
.../ws/api/registry/ResourceNameTokenKey.java | 9 +-
.../SimpleWebSocketConnectionRegistry.java | 26 +++
.../ws/api/res/js/wicket-websocket-jquery.js | 4 +
.../ws/api/res/js/wicket-websocket-setup.js.tmpl | 2 +-
.../ws/util/tester/TestWebSocketProcessor.java | 17 +-
.../util/tester/WebSocketTesterBehaviorTest.java | 2 +-
.../ws/javax/JavaxWebSocketConnection.java | 2 +-
.../wicket/protocol/ws/javax/WicketEndpoint.java | 1 -
30 files changed, 633 insertions(+), 72 deletions(-)
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java
index d9c3ca3..2c8e282 100644
--- a/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java
+++ b/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java
@@ -150,6 +150,14 @@ public abstract class PartialPageUpdate
}
/**
+ * @return returns true if and only if nothing has being added to partial update.
+ */
+ public boolean isEmpty()
+ {
+ return prependJavaScripts.isEmpty() && appendJavaScripts.isEmpty() && domReadyJavaScripts.isEmpty() && markupIdToComponent.isEmpty();
+ }
+
+ /**
* Serializes this object to the response.
*
* @param response
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..0207e52 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 server-side initiated 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..e178f7c 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
@@ -16,12 +16,15 @@
*/
package org.apache.wicket.examples.websocket;
+import org.apache.wicket.Session;
import org.apache.wicket.examples.WicketExampleApplication;
import org.apache.wicket.examples.websocket.charts.ChartWebSocketResource;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.https.HttpsConfig;
import org.apache.wicket.protocol.https.HttpsMapper;
import org.apache.wicket.protocol.ws.WebSocketSettings;
+import org.apache.wicket.request.Request;
+import org.apache.wicket.request.Response;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -50,6 +53,7 @@ public class JSR356Application extends WicketExampleApplication
setRootRequestMapper(new HttpsMapper(getRootRequestMapper(), new HttpsConfig(8080, 8443)));
mountPage("/behavior", WebSocketBehaviorDemoPage.class);
+ mountPage("/push", WebSocketPushUpdateProgressDemoPage.class);
mountPage("/resource", WebSocketResourceDemoPage.class);
mountPage("/resource-multi-tab", WebSocketMultiTabResourceDemoPage.class);
@@ -69,7 +73,13 @@ public class JSR356Application extends WicketExampleApplication
getCspSettings().blocking().disabled();
}
- @Override
+ @Override
+ public Session newSession(Request request, Response response)
+ {
+ return new JSR356Session(request);
+ }
+
+ @Override
protected void onDestroy() {
scheduledExecutorService.shutdownNow();
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Session.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Session.java
new file mode 100644
index 0000000..71910a2
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Session.java
@@ -0,0 +1,66 @@
+/*
+ * 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 java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.wicket.examples.websocket.progress.ProgressUpdater;
+import org.apache.wicket.protocol.http.WebSession;
+import org.apache.wicket.request.Request;
+
+public class JSR356Session extends WebSession
+{
+ private ProgressUpdater.ProgressUpdateTask progressUpdateTask;
+
+ public JSR356Session(Request request)
+ {
+ super(request);
+ }
+
+ public ProgressUpdater.ProgressUpdateTask getProgressUpdateTask()
+ {
+ return progressUpdateTask;
+ }
+
+ private synchronized void startTask() {
+ if (progressUpdateTask != null && progressUpdateTask.isRunning())
+ {
+ return;
+ }
+
+ JSR356Application application = JSR356Application.get();
+ ScheduledExecutorService service = application.getScheduledExecutorService();
+ progressUpdateTask = ProgressUpdater.start(application, getId(), service);
+ }
+
+ public synchronized void startOrCancelTask() {
+ if (progressUpdateTask != null && progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled())
+ {
+ progressUpdateTask.cancel();
+ }
+ else
+ {
+ startTask();
+ }
+ }
+
+ public static JSR356Session get() {
+ return (JSR356Session)WebSession.get();
+ }
+}
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketBehaviorDemoPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketBehaviorDemoPage.java
index 8d038aa..c6bff98 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketBehaviorDemoPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketBehaviorDemoPage.java
@@ -25,7 +25,6 @@ import org.apache.wicket.examples.websocket.charts.ChartUpdater;
import org.apache.wicket.examples.websocket.charts.WebSocketChart;
import org.apache.wicket.extensions.ajax.AjaxDownloadBehavior;
import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.protocol.https.RequireHttps;
import org.apache.wicket.protocol.ws.api.WebSocketBehavior;
import org.apache.wicket.protocol.ws.api.WebSocketRequestHandler;
import org.apache.wicket.protocol.ws.api.message.ConnectedMessage;
@@ -36,7 +35,6 @@ import org.apache.wicket.request.resource.ResourceStreamResource;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.StringResourceStream;
-@RequireHttps
public class WebSocketBehaviorDemoPage extends WicketExamplePage
{
private static final long serialVersionUID = 1L;
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketMultiTabResourceDemoPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketMultiTabResourceDemoPage.java
index 03ec5d6..534906c 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketMultiTabResourceDemoPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketMultiTabResourceDemoPage.java
@@ -19,12 +19,10 @@ package org.apache.wicket.examples.websocket;
import org.apache.wicket.examples.WicketExamplePage;
import org.apache.wicket.examples.websocket.charts.ChartWebSocketResource;
import org.apache.wicket.examples.websocket.charts.WebSocketChart;
-import org.apache.wicket.protocol.https.RequireHttps;
import org.apache.wicket.protocol.ws.api.BaseWebSocketBehavior;
import java.util.UUID;
-@RequireHttps
public class WebSocketMultiTabResourceDemoPage extends WicketExamplePage
{
public WebSocketMultiTabResourceDemoPage()
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/WebSocketResourceDemoPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java
similarity index 63%
copy from wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketResourceDemoPage.java
copy to wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java
index d8aef4d..a61ed66 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketResourceDemoPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java
@@ -17,18 +17,13 @@
package org.apache.wicket.examples.websocket;
import org.apache.wicket.examples.WicketExamplePage;
-import org.apache.wicket.examples.websocket.charts.ChartWebSocketResource;
-import org.apache.wicket.examples.websocket.charts.WebSocketChart;
-import org.apache.wicket.protocol.https.RequireHttps;
-import org.apache.wicket.protocol.ws.api.BaseWebSocketBehavior;
+import org.apache.wicket.examples.websocket.progress.ProgressBarTogglePanel;
+import org.apache.wicket.examples.websocket.progress.ProgressUpdater;
-@RequireHttps
-public class WebSocketResourceDemoPage extends WicketExamplePage
+public class WebSocketPushUpdateProgressDemoPage extends WicketExamplePage implements ProgressUpdater.ITaskProgressListener
{
- public WebSocketResourceDemoPage()
+ public WebSocketPushUpdateProgressDemoPage()
{
- WebSocketChart chartPanel = new WebSocketChart("chartPanel");
- chartPanel.add(new BaseWebSocketBehavior(ChartWebSocketResource.NAME));
- add(chartPanel);
+ add(new ProgressBarTogglePanel("progressPanel"));
}
}
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketResourceDemoPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketResourceDemoPage.java
index d8aef4d..079bff9 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketResourceDemoPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketResourceDemoPage.java
@@ -19,10 +19,8 @@ package org.apache.wicket.examples.websocket;
import org.apache.wicket.examples.WicketExamplePage;
import org.apache.wicket.examples.websocket.charts.ChartWebSocketResource;
import org.apache.wicket.examples.websocket.charts.WebSocketChart;
-import org.apache.wicket.protocol.https.RequireHttps;
import org.apache.wicket.protocol.ws.api.BaseWebSocketBehavior;
-@RequireHttps
public class WebSocketResourceDemoPage extends WicketExamplePage
{
public WebSocketResourceDemoPage()
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..dc7078e
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.java
@@ -0,0 +1,111 @@
+/*
+ * 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.examples.websocket.JSR356Session;
+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;
+
+
+ public ProgressBarTogglePanel(String id)
+ {
+ super(id);
+
+ setOutputMarkupId(true);
+
+ add(new WebSocketBehavior()
+ {
+ });
+
+ add(new AjaxLink<Void>("hideShowProgress")
+ {
+ @Override
+ public void onClick(AjaxRequestTarget target)
+ {
+ showProgress = !showProgress;
+ target.add(ProgressBarTogglePanel.this);
+ }
+ }.setBody((IModel<String>) () -> showProgress ? "Hide progress" : "Show progress"));
+
+ add(new AjaxLink<Void>("cancelRestartTask")
+ {
+ @Override
+ public void onClick(AjaxRequestTarget target)
+ {
+ JSR356Session.get().startOrCancelTask();
+ target.add(ProgressBarTogglePanel.this);
+ }
+ }.setBody((IModel<String>) () -> {
+ ProgressUpdater.ProgressUpdateTask progressUpdateTask = JSR356Session.get().getProgressUpdateTask();
+ return progressUpdateTask != null && progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled()
+ ? "Cancel task" :
+ "Restart task";
+ }));
+
+ add(new Label("progressBar", (IModel<String>) () -> {
+ ProgressUpdater.ProgressUpdateTask progressUpdateTask = JSR356Session.get().getProgressUpdateTask();
+ return progressUpdateTask != null && progressUpdateTask.isRunning()
+ ? "Background Task is " + progress + "% completed"
+ : "No task is running";
+ })
+ {
+ @Override
+ protected void onConfigure()
+ {
+ super.onConfigure();
+ setVisible(showProgress);
+ }
+ });
+ }
+
+
+ @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);
+ }
+ else if (wsEvent.getMessage() instanceof ProgressUpdater.TaskCanceled)
+ {
+ // task was canceled
+ 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..48f9848
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressUpdater.java
@@ -0,0 +1,177 @@
+/*
+ * 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.WicketRuntimeException;
+import org.apache.wicket.application.IClassResolver;
+import org.apache.wicket.page.IManageablePage;
+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;
+import org.apache.wicket.protocol.ws.api.registry.PageIdKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A helper class that uses the web connection to push components updates to the client.
+ */
+public class ProgressUpdater
+{
+ /**
+ * Marks a page as a listener to task progress.
+ */
+ public interface ITaskProgressListener {
+
+ }
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ProgressUpdater.class);
+
+ public static ProgressUpdateTask start(Application application, String session, ScheduledExecutorService scheduledExecutorService)
+ {
+ // create an asynchronous task that will write the data to the client
+ ProgressUpdateTask progressUpdateTask = new ProgressUpdateTask(application, session);
+ scheduledExecutorService.schedule(progressUpdateTask, 1, TimeUnit.SECONDS);
+ return progressUpdateTask;
+ }
+
+ /**
+ * Signal task was canceled.
+ */
+ public static class TaskCanceled implements IWebSocketPushMessage
+ {
+ }
+
+ /**
+ * 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 volatile boolean canceled = false;
+ private volatile boolean running = false;
+
+ private ProgressUpdateTask(Application application, String sessionId)
+ {
+ this.applicationName = application.getName();
+ this.sessionId = sessionId;
+ }
+
+ @Override
+ public void run()
+ {
+ running = true;
+ Application application = Application.get(applicationName);
+ WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application);
+
+ int progress = 0;
+
+ while (progress <= 100)
+ {
+ try
+ {
+ WebSocketPushBroadcaster broadcaster =
+ new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry());
+
+ if (canceled)
+ {
+ canceled = false;
+ running = false;
+ broadcaster.broadcastAllMatchingFilter(application, (sessionId, key) ->
+ ProgressUpdateTask.this.sessionId.equals(sessionId) && key instanceof PageIdKey
+ && ITaskProgressListener.class.isAssignableFrom(getPageClass(application, key)),
+ new TaskCanceled());
+ return;
+ }
+ broadcaster.broadcastAllMatchingFilter(application, (sessionId, key) ->
+ ProgressUpdateTask.this.sessionId.equals(sessionId) && key instanceof PageIdKey &&
+ ITaskProgressListener.class.isAssignableFrom(getPageClass(application, 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)
+ {
+ LOGGER.error("unexpected exception", e);
+ break;
+ }
+ }
+ running = false;
+ }
+
+ protected Class<?> getPageClass(Application application, IKey iKey) {
+ try {
+ return application.getApplicationSettings().getClassResolver().resolveClass(iKey.getContext());
+ } catch (ClassNotFoundException e) {
+ throw new WicketRuntimeException(e);
+ }
+ }
+
+ public boolean isRunning() {
+ return running;
+ }
+
+ public boolean isCanceled() {
+ return canceled;
+ }
+
+ public void cancel() {
+ this.canceled = true;
+ this.running = false;
+ }
+ }
+}
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketConnection.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketConnection.java
index 8726d56..3cd0f62 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketConnection.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketConnection.java
@@ -50,7 +50,7 @@ public abstract class AbstractWebSocketConnection implements IWebSocketConnectio
@Override
public void sendMessage(IWebSocketPushMessage message)
{
- webSocketProcessor.broadcastMessage(message);
+ webSocketProcessor.broadcastMessage(message, this);
}
@Override
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
index 19982fa..f2a3a93 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
@@ -81,9 +81,11 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
* A pageId indicating that the endpoint is WebSocketResource
*/
static final int NO_PAGE_ID = -1;
+ static final String NO_PAGE_CLASS = "_NO_PAGE";
private final WebRequest webRequest;
private final int pageId;
+ private final String context;
private final String resourceName;
private final String connectionToken;
private final Url baseUrl;
@@ -112,6 +114,7 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
}
this.sessionId = httpSession.getId();
String pageId = request.getParameter("pageId");
+ this.context = request.getParameter("context");
this.resourceName = request.getParameter("resourceName");
this.connectionToken = request.getParameter("connectionToken");
if (Strings.isEmpty(pageId) && Strings.isEmpty(resourceName))
@@ -181,7 +184,7 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
}
}
- broadcastMessage(new ConnectedMessage(getApplication(), getSessionId(), key));
+ broadcastMessage(new ConnectedMessage(getApplication(), getSessionId(), key), connection);
}
@Override
@@ -203,6 +206,13 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
}
}
+ public final void broadcastMessage(final IWebSocketMessage message)
+ {
+ IKey key = getRegistryKey();
+ IWebSocketConnection connection = connectionRegistry.getConnection(application, sessionId, key);
+ broadcastMessage(message, connection);
+ }
+
/**
* Exports the Wicket thread locals and broadcasts the received message from the client to all
* interested components and behaviors in the page with id {@code #pageId}
@@ -215,11 +225,8 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
* @param message
* the message to broadcast
*/
- public final void broadcastMessage(final IWebSocketMessage message)
+ public final void broadcastMessage(final IWebSocketMessage message, IWebSocketConnection connection)
{
- IKey key = getRegistryKey();
- IWebSocketConnection connection = connectionRegistry.getConnection(application, sessionId, key);
-
if (connection != null && (connection.isOpen() || isSpecialMessage(message)))
{
Application oldApplication = ThreadContext.getApplication();
@@ -249,8 +256,8 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
if (session == null)
{
- connectionRegistry.removeConnection(application, sessionId, key);
- LOG.debug("No Session could be found for session id '{}' and key '{}'!", sessionId, key);
+ connectionRegistry.removeConnection(application, sessionId, connection.getKey());
+ LOG.debug("No Session could be found for session id '{}' and key '{}'!", sessionId, connection.getKey());
return;
}
@@ -261,7 +268,7 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
{
WebSocketRequestHandler requestHandler = webSocketSettings.newWebSocketRequestHandler(page, connection);
- WebSocketPayload payload = createEventPayload(message, requestHandler);
+ WebSocketPayload<?> payload = createEventPayload(message, requestHandler);
if (!(message instanceof ConnectedMessage || isSpecialMessage(message))) {
requestCycle.scheduleRequestHandlerAfterCurrent(requestHandler);
@@ -356,9 +363,9 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
return sessionId;
}
- private WebSocketPayload createEventPayload(IWebSocketMessage message, WebSocketRequestHandler handler)
+ private WebSocketPayload<?> createEventPayload(IWebSocketMessage message, WebSocketRequestHandler handler)
{
- final WebSocketPayload payload;
+ final WebSocketPayload<?> payload;
if (message instanceof TextMessage)
{
payload = new WebSocketTextPayload((TextMessage) message, handler);
@@ -399,15 +406,15 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
IKey key;
if (Strings.isEmpty(resourceName))
{
- key = new PageIdKey(pageId);
+ key = new PageIdKey(pageId, context);
}
else
{
if (Strings.isEmpty(connectionToken))
{
- key = new ResourceNameKey(resourceName);
+ key = new ResourceNameKey(resourceName, context);
} else {
- key = new ResourceNameTokenKey(resourceName, connectionToken);
+ key = new ResourceNameTokenKey(resourceName, connectionToken, context);
}
}
return key;
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/BaseWebSocketBehavior.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/BaseWebSocketBehavior.java
index b773ef3..420393e 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/BaseWebSocketBehavior.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/BaseWebSocketBehavior.java
@@ -121,9 +121,21 @@ public class BaseWebSocketBehavior extends Behavior
return webSocketSetupTemplate.asString(parameters);
}
+ /**
+ * Override to return a context. By default, this is the page class name.
+ *
+ * @param component the {@link org.apache.wicket.Component}
+ * @return the context for this websocket behavior.
+ */
+ protected String getContext(Component component) {
+ return component.getPage().getClass().getName();
+ }
+
private Map<String, Object> getParameters(Component component) {
Map<String, Object> variables = Generics.newHashMap();
+ variables.put("context", getContext(component));
+
// set falsy JS values for the non-used parameter
if (Strings.isEmpty(resourceName))
{
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketPushBroadcaster.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketPushBroadcaster.java
index db653d2..c5f6d78 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketPushBroadcaster.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketPushBroadcaster.java
@@ -109,6 +109,74 @@ public class WebSocketPushBroadcaster
process(application, wsConnections, message);
}
+ /**
+ * Processes the given message in all pages in a given session that have active Web Socket connections.
+ * The message is sent as an event to the Page and components of the session allowing the components
+ * to be updated.
+ *
+ * This method can be invoked from any thread, even a non-wicket thread. By default all processing
+ * is done in the caller thread. Use
+ * {@link WebSocketSettings#setWebSocketPushMessageExecutor(org.apache.wicket.protocol.ws.concurrent.Executor)}
+ * to move processing to background threads.
+ *
+ * If some connections are not in valid state they are silently ignored.
+ *
+ * @param application
+ * The wicket application
+ *
+ * @param sessionId
+ * The session ID
+ * @param message
+ * The push message event
+ */
+ public void broadcastAllInSession(Application application, String sessionId, IWebSocketPushMessage message)
+ {
+ Args.notNull(application, "application");
+ Args.notNull(message, "message");
+ Args.notNull(sessionId, "sessionId");
+
+ Collection<IWebSocketConnection> wsConnections = registry.getConnections(application, sessionId);
+ if (wsConnections == null || wsConnections.isEmpty())
+ {
+ return;
+ }
+ process(application, wsConnections, message);
+ }
+
+ /**
+ * Processes the given message in all pages in a given session that have active Web Socket connections and match
+ * the given filter. The message is sent as an event to the Page and components of the session allowing the components
+ * to be updated.
+ *
+ * This method can be invoked from any thread, even a non-wicket thread. By default all processing
+ * is done in the caller thread. Use
+ * {@link WebSocketSettings#setWebSocketPushMessageExecutor(org.apache.wicket.protocol.ws.concurrent.Executor)}
+ * to move processing to background threads.
+ *
+ * If some connections are not in valid state they are silently ignored.
+ *
+ * @param application
+ * The wicket application
+ *
+ * @param connectionsFilter
+ * the {@link org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry.IConnectionsFilter}
+ * @param message
+ * The push message event
+ */
+ public void broadcastAllMatchingFilter(Application application, IWebSocketConnectionRegistry.IConnectionsFilter connectionsFilter, IWebSocketPushMessage message)
+ {
+ Args.notNull(application, "application");
+ Args.notNull(message, "message");
+ Args.notNull(connectionsFilter, "connectionsFilter");
+
+ Collection<IWebSocketConnection> wsConnections = registry.getConnections(application, connectionsFilter);
+ if (wsConnections == null || wsConnections.isEmpty())
+ {
+ return;
+ }
+ process(application, wsConnections, message);
+ }
+
private void process(final Application application, final Collection<IWebSocketConnection> wsConnections,
final IWebSocketPushMessage message)
{
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 7df3735..7ce1f62 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
@@ -97,7 +97,17 @@ public class WebSocketRequestHandler extends AbstractPartialPageRequestHandler i
}
}
-
+ /**
+ * @return if <code>true</code> then EMPTY partial updates will se send. If <code>false</code> then EMPTY
+ * partial updates will be skipped. A possible use case is: a page receives and a push event but no one is
+ * listening to it, and nothing is added to {@link org.apache.wicket.protocol.ws.api.WebSocketRequestHandler}
+ * thus no real push to client is needed. For compatibilities this is set to true. Thus EMPTY updates are sent
+ * by default.
+ */
+ protected boolean shouldPushWhenEmpty()
+ {
+ return true;
+ }
protected PartialPageUpdate getUpdate() {
if (update == null) {
@@ -129,7 +139,10 @@ public class WebSocketRequestHandler extends AbstractPartialPageRequestHandler i
{
if (update != null)
{
- update.writeTo(requestCycle.getResponse(), "UTF-8");
+ if (shouldPushWhenEmpty() || !update.isEmpty())
+ {
+ update.writeTo(requestCycle.getResponse(), "UTF-8");
+ }
}
}
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IKey.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/AbstractKey.java
similarity index 78%
copy from wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IKey.java
copy to wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/AbstractKey.java
index b0774dc..afe2eaf 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IKey.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/AbstractKey.java
@@ -16,11 +16,18 @@
*/
package org.apache.wicket.protocol.ws.api.registry;
-import org.apache.wicket.util.io.IClusterable;
+public class AbstractKey implements IKey
+{
-/**
- * A marker interface for keys that are used to find a web socket
- * connection in {@link IWebSocketConnectionRegistry}
- */
-public interface IKey extends IClusterable
-{}
+ private final String context;
+
+ public AbstractKey(String context)
+ {
+ this.context = context;
+ }
+
+ @Override
+ public String getContext() {
+ return context;
+ }
+}
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IKey.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IKey.java
index b0774dc..25a5196 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IKey.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IKey.java
@@ -23,4 +23,10 @@ import org.apache.wicket.util.io.IClusterable;
* connection in {@link IWebSocketConnectionRegistry}
*/
public interface IKey extends IClusterable
-{}
+{
+ /**
+ * @return return a context for the key. This could be, for instance, a page class name or a resource class name.
+ * I.e. something that allow to discriminate keys along different pages.
+ */
+ String getContext();
+}
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IWebSocketConnectionRegistry.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IWebSocketConnectionRegistry.java
index 2782a93..7665608 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IWebSocketConnectionRegistry.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IWebSocketConnectionRegistry.java
@@ -29,6 +29,18 @@ import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
public interface IWebSocketConnectionRegistry
{
/**
+ * Interface allowing to filter web-sockets connections. This could be used for use cases like the
+ * following: you need to deliver messages to all page instances satisfying certain conditions (e.g.
+ * they contain some progress reporting component).
+ */
+ interface IConnectionsFilter
+ {
+
+ boolean accept(String sessionId, IKey key);
+
+ }
+
+ /**
* @param application
* the web application to look in
* @param sessionId
@@ -44,12 +56,24 @@ public interface IWebSocketConnectionRegistry
* the web application to look in
* @param sessionId
* the http session id
- * @return collection of web socket connection used by a client with the given session id
+ * @return collection of web socket connections used by a client with the given session id
*/
Collection<IWebSocketConnection> getConnections(Application application, String sessionId);
/**
+ *
+ * @param application
+ * the web application to look in
+ * @param connectionsFilter
+ * the {@link org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry.IConnectionsFilter}
+ *
+ * @return collection of web socket connections that match certain filter
+ */
+ Collection<IWebSocketConnection> getConnections(Application application, IConnectionsFilter connectionsFilter);
+
+
+ /**
* @param application
* the web application to look in
* @return collection of web socket connection used by any client connected to specified application
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/PageIdKey.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/PageIdKey.java
index 84eee23..2aa7de0 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/PageIdKey.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/PageIdKey.java
@@ -16,20 +16,29 @@
*/
package org.apache.wicket.protocol.ws.api.registry;
+import org.apache.wicket.Session;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.util.lang.Args;
/**
* A key based on page's id
*/
-public class PageIdKey implements IKey
+public class PageIdKey extends AbstractKey
{
private final Integer pageId;
public PageIdKey(Integer pageId)
{
- this.pageId = Args.notNull(pageId, "pageId");
+ this(pageId, null);
}
+ public PageIdKey(Integer pageId, String context)
+ {
+ super(context);
+ this.pageId = Args.notNull(pageId, "pageId");
+ }
+
@Override
public boolean equals(Object o)
{
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/ResourceNameKey.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/ResourceNameKey.java
index 4f45aed..c5f4bc4 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/ResourceNameKey.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/ResourceNameKey.java
@@ -21,12 +21,18 @@ import org.apache.wicket.util.lang.Args;
/**
* A key based on shared resource's name
*/
-public class ResourceNameKey implements IKey
+public class ResourceNameKey extends AbstractKey
{
private final String resourceName;
public ResourceNameKey(String resourceName)
{
+ this(resourceName, null);
+ }
+
+ public ResourceNameKey(String resourceName, String context)
+ {
+ super(context);
this.resourceName = Args.notNull(resourceName, "resourceName");
}
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/ResourceNameTokenKey.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/ResourceNameTokenKey.java
index be76c12..e4b890a 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/ResourceNameTokenKey.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/ResourceNameTokenKey.java
@@ -23,13 +23,20 @@ import org.apache.wicket.util.lang.Args;
/**
* A key based on shared resource's name and a token
*/
-public class ResourceNameTokenKey implements IKey
+public class ResourceNameTokenKey extends AbstractKey
{
private final String resourceName;
private final String connectionToken;
+
public ResourceNameTokenKey(String resourceName, String connectionToken)
{
+ this(resourceName, connectionToken, null);
+ }
+
+ public ResourceNameTokenKey(String resourceName, String connectionToken, String context)
+ {
+ super(context);
this.resourceName = Args.notNull(resourceName, "resourceName");
this.connectionToken = Args.notNull(connectionToken, "connectionToken");
}
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/SimpleWebSocketConnectionRegistry.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/SimpleWebSocketConnectionRegistry.java
index b5005aa..1a17590 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/SimpleWebSocketConnectionRegistry.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/SimpleWebSocketConnectionRegistry.java
@@ -19,6 +19,7 @@ package org.apache.wicket.protocol.ws.api.registry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import org.apache.wicket.Application;
@@ -79,6 +80,31 @@ public class SimpleWebSocketConnectionRegistry implements IWebSocketConnectionRe
return connections;
}
+ @Override
+ public Collection<IWebSocketConnection> getConnections(Application application, IConnectionsFilter connectionsFilter)
+ {
+ Args.notNull(application, "application");
+ Args.notNull(connectionsFilter, "connectionsFilter");
+
+ Collection<IWebSocketConnection> connections = new ArrayList<>();
+ ConcurrentMap<String, ConcurrentMap<IKey, IWebSocketConnection>> connectionsBySession = application.getMetaData(KEY);
+ if (connectionsBySession != null)
+ {
+ for (Map.Entry<String, ConcurrentMap<IKey, IWebSocketConnection>> connectionsByPage : connectionsBySession.entrySet())
+ {
+ for (Map.Entry<IKey, IWebSocketConnection> connectionEntry: connectionsByPage.getValue().entrySet())
+ {
+ if (connectionsFilter.accept(connectionsByPage.getKey(), connectionEntry.getKey()))
+ {
+ connections.add(connectionEntry.getValue());
+ }
+ }
+
+ }
+ }
+ return connections;
+ }
+
/**
* Returns a collection of currently active websockets. The connections might close at any time.
*
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js
index cd06ad5..93b7386 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js
@@ -81,6 +81,10 @@
}
}
+ if (WWS.context) {
+ url += '&context=' + encodeURIComponent(WWS.context);
+ }
+
url += '&wicket-ajax-baseurl=' + encodeURIComponent(WWS.baseUrl);
url += '&wicket-app-name=' + encodeURIComponent(WWS.appName);
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl
index 1533cbf..98e9bc8 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl
@@ -2,7 +2,7 @@
'use strict';
if (typeof(Wicket.WebSocket.appName) === "undefined") {
- jQuery.extend(Wicket.WebSocket, { pageId: ${pageId}, resourceName: '${resourceName}', connectionToken: '${connectionToken}',
+ jQuery.extend(Wicket.WebSocket, { pageId: ${pageId}, context: '${context}', resourceName: '${resourceName}', connectionToken: '${connectionToken}',
baseUrl: '${baseUrl}', contextPath: '${contextPath}', appName: '${applicationName}',
port: ${port}, securePort: ${securePort}, filterPrefix: '${filterPrefix}', sessionId: '${sessionId}' });
Wicket.WebSocket.createDefaultConnection();
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java
index cf88c30..6e70466 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java
@@ -67,9 +67,20 @@ abstract class TestWebSocketProcessor extends AbstractWebSocketProcessor
* @param resourceName
* the name of the shared resource that will handle the web socket messages
*/
+ public TestWebSocketProcessor(final WicketTester wicketTester, final String resourceName, Page page)
+ {
+ super(createRequest(wicketTester, resourceName, page), wicketTester.getApplication());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param resourceName
+ * the name of the shared resource that will handle the web socket messages
+ */
public TestWebSocketProcessor(final WicketTester wicketTester, final String resourceName)
{
- super(createRequest(wicketTester, resourceName), wicketTester.getApplication());
+ super(createRequest(wicketTester, resourceName, null), wicketTester.getApplication());
}
/**
@@ -84,6 +95,7 @@ abstract class TestWebSocketProcessor extends AbstractWebSocketProcessor
Args.notNull(page, "page");
MockHttpServletRequest request = createRequest(wicketTester);
request.addParameter("pageId", page.getId());
+ request.addParameter("context", page.getClass().getName());
return request;
}
@@ -94,11 +106,12 @@ abstract class TestWebSocketProcessor extends AbstractWebSocketProcessor
* the page that may have registered {@link org.apache.wicket.protocol.ws.api.WebSocketBehavior}
* @return a mock http request
*/
- private static HttpServletRequest createRequest(final WicketTester wicketTester, final String resourceName)
+ private static HttpServletRequest createRequest(final WicketTester wicketTester, final String resourceName, final Page page)
{
Args.notNull(resourceName, "resourceName");
MockHttpServletRequest request = createRequest(wicketTester);
request.addParameter("resourceName", resourceName);
+ request.addParameter("context", page != null ? page.getClass().getName() : "");
return request;
}
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 29ec707..912cec5 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
@@ -131,7 +131,7 @@ public class WebSocketTesterBehaviorTest
}
};
webSocketTester.broadcast(tester.getApplication(), tester.getHttpSession().getId(),
- new PageIdKey(page.getPageId()), broadcastMessage);
+ new PageIdKey(page.getPageId(), page.getClass().getName()), broadcastMessage);
assertTrue(messageReceived.get());
webSocketTester.destroy();
diff --git a/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java b/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java
index 236c64c..b9f6419 100644
--- a/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java
+++ b/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java
@@ -49,7 +49,7 @@ public class JavaxWebSocketConnection extends AbstractWebSocketConnection
public JavaxWebSocketConnection(Session session, AbstractWebSocketProcessor webSocketProcessor)
{
super(webSocketProcessor);
- this.session = Args.notNull(session, "connection");
+ this.session = Args.notNull(session, "session");
}
@Override
diff --git a/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java b/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java
index 98c64d0..b5b0b2b 100644
--- a/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java
+++ b/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java
@@ -123,7 +123,6 @@ public class WicketEndpoint extends Endpoint
{
String appName = null;
- @SuppressWarnings("unchecked")
Map<String, List<String>> parameters = session.getRequestParameterMap();
if (parameters != null)
{