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

reiern70 pushed a commit to branch WICKET-6930-websocket-improvements
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit c48a23a903426eb329b45a690a464fde751b1405
Author: reiern70 <[email protected]>
AuthorDate: Sun Nov 7 11:38:39 2021 +0300

    WICKET-6930: pass page class as a kind of context
---
 .../examples/websocket/JSR356Application.java      | 11 +++-
 .../wicket/examples/websocket/JSR356Session.java   | 51 +++++++++++++++++
 .../WebSocketPushUpdateProgressDemoPage.java       |  3 +-
 .../websocket/progress/ProgressBarTogglePanel.java | 36 ++++--------
 .../websocket/progress/ProgressUpdater.java        | 36 ++++++------
 .../ws/api/AbstractWebSocketConnection.java        |  2 +-
 .../ws/api/AbstractWebSocketProcessor.java         | 25 +++++---
 .../protocol/ws/api/BaseWebSocketBehavior.java     |  2 +
 .../protocol/ws/api/WebSocketPushBroadcaster.java  | 66 ++++++++++++++++++++++
 .../api/registry/IWebSocketConnectionRegistry.java | 25 +++++++-
 .../wicket/protocol/ws/api/registry/PageIdKey.java | 24 ++++++++
 .../SimpleWebSocketConnectionRegistry.java         | 26 +++++++++
 .../ws/api/res/js/wicket-websocket-jquery.js       |  1 +
 .../ws/api/res/js/wicket-websocket-setup.js.tmpl   |  2 +-
 .../ws/util/tester/TestWebSocketProcessor.java     |  1 +
 .../util/tester/WebSocketTesterBehaviorTest.java   |  2 +-
 .../ws/javax/JavaxWebSocketConnection.java         |  2 +-
 .../wicket/protocol/ws/javax/WicketEndpoint.java   |  2 +
 18 files changed, 259 insertions(+), 58 deletions(-)

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 98a9779..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;
@@ -70,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..e45ecde
--- /dev/null
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Session.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+    }
+
+    public synchronized void startTask() {
+        if (progressUpdateTask != null && progressUpdateTask.isRunning()) {
+            return;
+        }
+        ScheduledExecutorService service = 
JSR356Application.get().getScheduledExecutorService();
+        progressUpdateTask = ProgressUpdater.start(getApplication(), getId(), 
service);
+    }
+
+    public static JSR356Session getInstance() {
+        return (JSR356Session)get();
+    }
+}
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
index 01d16b2..bbf923d 100644
--- 
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
@@ -18,10 +18,11 @@ package org.apache.wicket.examples.websocket;
 
 import org.apache.wicket.examples.WicketExamplePage;
 import org.apache.wicket.examples.websocket.progress.ProgressBarTogglePanel;
+import org.apache.wicket.examples.websocket.progress.ProgressUpdater;
 import org.apache.wicket.protocol.https.RequireHttps;
 
 @RequireHttps
-public class WebSocketPushUpdateProgressDemoPage extends WicketExamplePage
+public class WebSocketPushUpdateProgressDemoPage extends WicketExamplePage 
implements ProgressUpdater.ITaskProgressListener
 {
        public WebSocketPushUpdateProgressDemoPage()
        {
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
index 03e7733..71e389c 100644
--- 
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
@@ -22,6 +22,7 @@ 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;
@@ -34,7 +35,7 @@ public class ProgressBarTogglePanel extends Panel
 
     private int progress = 0;
     private boolean showProgress = true;
-    private ProgressUpdater.ProgressUpdateTask progressUpdateTask;
+
 
     public ProgressBarTogglePanel(String id)
     {
@@ -46,7 +47,7 @@ public class ProgressBarTogglePanel extends Panel
         {
             @Override
             protected void onConnect(ConnectedMessage message) {
-                progressUpdateTask = 
ProgressBarTogglePanel.startProgressTask(message);
+
             }
         });
 
@@ -65,33 +66,25 @@ public class ProgressBarTogglePanel extends Panel
             @Override
             public void onClick(AjaxRequestTarget target)
             {
-                if (progressUpdateTask.isRunning() && 
!progressUpdateTask.isCanceled())
+                ProgressUpdater.ProgressUpdateTask progressUpdateTask = 
JSR356Session.getInstance().getProgressUpdateTask();
+                if (progressUpdateTask != null && 
progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled())
                 {
                     progressUpdateTask.cancel();
                 }
                 else
                 {
-                    ScheduledExecutorService service = 
JSR356Application.get().getScheduledExecutorService();
-                    ProgressUpdater.restart(progressUpdateTask, service);
+                    JSR356Session.getInstance().startTask();
                 }
                 target.add(ProgressBarTogglePanel.this);
             }
-        }.setBody(new IModel<String>()
-        {
-            @Override
-            public String getObject()
-            {
-                return progressUpdateTask != null && 
progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled() ? "Cancel 
task" : "Restart task";
-            }
+        }.setBody((IModel<String>) () -> {
+            ProgressUpdater.ProgressUpdateTask progressUpdateTask = 
JSR356Session.getInstance().getProgressUpdateTask();
+            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";
-            }
+        add(new Label("progressBar", (IModel<String>) () -> {
+            ProgressUpdater.ProgressUpdateTask progressUpdateTask = 
JSR356Session.getInstance().getProgressUpdateTask();
+            return progressUpdateTask != null && 
progressUpdateTask.isRunning() ? "Background Task is " + progress + "% 
completed" : "No task is running";
         })
         {
             @Override
@@ -103,11 +96,6 @@ public class ProgressBarTogglePanel extends Panel
         });
     }
 
-    public static ProgressUpdater.ProgressUpdateTask 
startProgressTask(ConnectedMessage message)
-    {
-        ScheduledExecutorService service = 
JSR356Application.get().getScheduledExecutorService();
-        return ProgressUpdater.start(message, service);
-    }
 
     @Override
     public void onEvent(IEvent<?> event)
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
index 60a3e94..aa928cb 100644
--- 
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
@@ -28,6 +28,7 @@ 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;
 
@@ -36,20 +37,23 @@ import org.slf4j.LoggerFactory;
  */
 public class ProgressUpdater
 {
+       /**
+        * Marks a page as listening to task progress.
+        */
+       public interface ITaskProgressListener {
+
+       }
+
        private static final Logger LOGGER = 
LoggerFactory.getLogger(ProgressUpdater.class);
 
-       public static ProgressUpdateTask start(ConnectedMessage message, 
ScheduledExecutorService scheduledExecutorService)
+       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(message.getApplication(), message.getSessionId(), 
message.getKey());
+               ProgressUpdateTask progressUpdateTask = new 
ProgressUpdateTask(application, session);
                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.
         */
@@ -80,16 +84,14 @@ public class ProgressUpdater
                 */
                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)
+               private ProgressUpdateTask(Application application, String 
sessionId)
                {
                        this.applicationName = application.getName();
                        this.sessionId = sessionId;
-                       this.key = key;
                }
 
                @Override
@@ -98,22 +100,13 @@ public class ProgressUpdater
                        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;
@@ -123,7 +116,12 @@ public class ProgressUpdater
 
                                        WebSocketPushBroadcaster broadcaster =
                                                        new 
WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry());
-                                       broadcaster.broadcast(new 
ConnectedMessage(application, sessionId, key), new ProgressUpdate(progress));
+                                       
broadcaster.broadcastAllMatchingFilter(application,  new 
IWebSocketConnectionRegistry.IConnectionsFilter() {
+                                               @Override
+                                               public boolean 
acceptConnection(String sessionId, IKey key) {
+                                                       return 
ProgressUpdateTask.this.sessionId.equals(sessionId) && key instanceof PageIdKey 
&& ITaskProgressListener.class.isAssignableFrom(((PageIdKey) 
key).getPageClass());
+                                               }
+                                       }, new ProgressUpdate(progress));
 
                                        // sleep for a while to simulate work
                                        TimeUnit.SECONDS.sleep(1);
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 82cd21a..d6d35b0 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 pageClass;
        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");
+               String pageClass = request.getParameter("pageClass");
                this.resourceName = request.getParameter("resourceName");
                this.connectionToken = request.getParameter("connectionToken");
                if (Strings.isEmpty(pageId) && Strings.isEmpty(resourceName))
@@ -121,10 +124,12 @@ public abstract class AbstractWebSocketProcessor 
implements IWebSocketProcessor
                if (Strings.isEmpty(pageId) == false)
                {
                        this.pageId = Integer.parseInt(pageId, 10);
+                       this.pageClass = pageClass;
                }
                else
                {
                        this.pageId = NO_PAGE_ID;
+                       this.pageClass = NO_PAGE_CLASS;
                }
 
                String baseUrl = 
request.getParameter(WebRequest.PARAM_AJAX_BASE_URL);
@@ -181,7 +186,7 @@ public abstract class AbstractWebSocketProcessor implements 
IWebSocketProcessor
                        }
                }
 
-               broadcastMessage(new ConnectedMessage(getApplication(), 
getSessionId(), key));
+               broadcastMessage(new ConnectedMessage(getApplication(), 
getSessionId(), key), connection);
        }
 
        @Override
@@ -203,6 +208,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 +227,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 +258,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;
                                }
 
@@ -399,7 +408,7 @@ public abstract class AbstractWebSocketProcessor implements 
IWebSocketProcessor
                IKey key;
                if (Strings.isEmpty(resourceName))
                {
-                       key = new PageIdKey(pageId);
+                       key = new PageIdKey(pageId, pageClass);
                }
                else
                {
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 c0a1f18..7ff8d80 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
@@ -128,6 +128,7 @@ public class BaseWebSocketBehavior extends Behavior
                {
                        int pageId = component.getPage().getPageId();
                        variables.put("pageId", pageId);
+                       variables.put("pageClass", 
component.getPage().getClass().getName());
                        variables.put("resourceName", "");
                        variables.put("connectionToken", "");
                }
@@ -136,6 +137,7 @@ public class BaseWebSocketBehavior extends Behavior
                        variables.put("resourceName", resourceName);
                        variables.put("connectionToken", connectionToken);
                        variables.put("pageId", false);
+                       variables.put("pageClass", "");
                }
 
                WebSocketSettings webSocketSettings = 
WebSocketSettings.Holder.get(component.getApplication());
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..fc37a7f 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,72 @@ 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");
+
+               Collection<IWebSocketConnection> wsConnections = 
registry.getConnections(application, sessionId);
+               if (wsConnections == null)
+               {
+                       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");
+
+               Collection<IWebSocketConnection> wsConnections = 
registry.getConnections(application, connectionsFilter);
+               if (wsConnections == null)
+               {
+                       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/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..c4de9a5 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,17 @@ import 
org.apache.wicket.protocol.ws.api.IWebSocketConnection;
 public interface IWebSocketConnectionRegistry
 {
        /**
+        * Interface allowing to filter web-sockets connection. This could be 
used for use cases like the
+        * following: you
+        */
+       interface IConnectionsFilter
+       {
+
+               boolean acceptConnection(String sessionId, IKey key);
+
+       }
+
+       /**
         * @param application
         *      the web application to look in
         * @param sessionId
@@ -44,12 +55,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..ba50ed2 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,6 +16,9 @@
  */
 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;
 
 /**
@@ -25,9 +28,30 @@ public class PageIdKey implements IKey
 {
        private final Integer pageId;
 
+       private Class<? extends IManageablePage> pageClass;
+
        public PageIdKey(Integer pageId)
        {
+               this(pageId, null);
+       }
+
+       public PageIdKey(Integer pageId, String pageClass)
+       {
                this.pageId = Args.notNull(pageId, "pageId");
+               Args.notNull(pageClass, "pageClass");
+               try {
+                       this.pageClass = 
(Class<IManageablePage>)Thread.currentThread().getContextClassLoader().loadClass(pageClass);
+               } catch (ClassNotFoundException e) {
+                       //throw new WicketRuntimeException(e);
+               }
+       }
+
+       /**
+        * @return returns the page class.
+        */
+       public Class<? extends IManageablePage> getPageClass()
+       {
+               return pageClass;
        }
 
        @Override
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..e176a15 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.acceptConnection(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..e398207 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
@@ -74,6 +74,7 @@
 
                                if (WWS.pageId !== false) {
                                        url += '?pageId=' + 
encodeURIComponent(WWS.pageId);
+                                       url += '&pageClass=' + 
encodeURIComponent(WWS.pageClass);
                                } else if (WWS.resourceName) {
                                        url += '?resourceName=' + 
encodeURIComponent(WWS.resourceName);
                                        if (WWS.connectionToken) {
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..b73eb01 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},  
pageClass: '${pageClass}', 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 e48b908..6d6736d 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
@@ -84,6 +84,7 @@ abstract class TestWebSocketProcessor extends 
AbstractWebSocketProcessor
                Args.notNull(page, "page");
                MockHttpServletRequest request = createRequest(wicketTester);
                request.addParameter("pageId", page.getId());
+               request.addParameter("pageClass", 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 41fa304..f7e4ca4 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 4808dbd..a73324b 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
@@ -47,6 +47,7 @@ public class WicketEndpoint extends Endpoint
         * The name of the request parameter that holds the application name
         */
        private static final String WICKET_APP_PARAM_NAME = "wicket-app-name";
+       private static final String WICKET_SESSION_ID = "jsessionid";
 
        private final AtomicBoolean applicationDestroyed = new 
AtomicBoolean(false);
 
@@ -56,6 +57,7 @@ public class WicketEndpoint extends Endpoint
        public void onOpen(Session session, EndpointConfig endpointConfig)
        {
                String appName = getApplicationName(session);
+               session.getId();
 
                WebApplication app = (WebApplication) 
WebApplication.get(appName);
                app.getApplicationListeners().add(new 
ApplicationListener(applicationDestroyed));

Reply via email to