wicket-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Henderson <peter.hender...@starjar.com>
Subject Re: WebSockets and Page serialization, oddity.
Date Wed, 03 Jul 2019 08:43:07 GMT
On Tue, 2 Jul 2019 at 16:00, Martin Grigorov <mgrigorov@apache.org> wrote:

> Hi,
>
> Here are the logs:
>
> [qtp1722023916-27] INFO com.mycompany.StartWebSocketPage - onClose
> [Wicket-AsyncPageStore-PageSavingThread] INFO
> com.mycompany.WicketApplication - ===serialize class
> com.mycompany.StartWebSocketPage 0
> [qtp1722023916-16] INFO com.mycompany.WicketApplication - ---deserialize
> class com.mycompany.BackgroundWorkPage 1
> [qtp1722023916-16] INFO com.mycompany.BackgroundWorkPage - onEvent other
> org.apache.wicket.protocol.ws.api.event.WebSocketConnectedPayload@232150f0
> [qtp1722023916-16] INFO com.mycompany.BackgroundWorkPage - onConnect
> [qtp1722023916-16] INFO com.mycompany.BackgroundWorkPage - Broadcasting
> com.mycompany.pushmessages.WebSocketConnected@d0ec7a9
> [qtp1722023916-16] INFO com.mycompany.WicketApplication - ---deserialize
> class com.mycompany.BackgroundWorkPage 1
> [qtp1722023916-16] INFO com.mycompany.BackgroundWorkPage - onEvent
> websocketpushpayload
> [qtp1722023916-16] INFO com.mycompany.BackgroundWorkPage -
> onWebSocketMessage: class com.mycompany.BackgroundWorkPage,
> com.mycompany.pushmessages.WebSocketConnected@d0ec7a9
> [qtp1722023916-16] INFO com.mycompany.BackgroundWorkPage - received
> WebSocketConnected
>
> The problem is in WebSocketPage#onInitialize():
>
>  add(new WebSocketBehavior() {
>
>   @Override
>   protected void onConnect(ConnectedMessage message) {
>     super.onConnect(message);
>     log.info("onConnect");
>
>     connectedMessage = message;
>     broadcast(new WebSocketConnected());
>   }
>
> broadcast() uses new
> WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry()) to
> broadcast the event.
> But since the caller is #onInitialize() the current page instance is not
> yet saved into the page store and the registry loads the previous version
> of BackgroundWorkPage id=1 (the one stored by AjaxLink#onClick() call to
> setResponsePage()).
> So the looked up page instance by WebSocket's connection registry does not
> see the new state (connectedMessage)
>
>
> Below is a diff with the changes I've made locally to debug it:
>
> diff --git pom.xml pom.xml
> index b49937f..202d6f2 100644
> --- pom.xml
> +++ pom.xml
> @@ -41,7 +41,7 @@
>        </license>
>    </licenses>
>    <properties>
> -       <wicket.version>8.5.0</wicket.version>
> +       <wicket.version>8.6.0-SNAPSHOT</wicket.version>
>        <jetty9.version>9.4.18.v20190429</jetty9.version>
>        <slf4j.version>1.7.26</slf4j.version>
>        <junit.version>4.12</junit.version>
> @@ -63,13 +63,6 @@
>            <version>${wicket.version}</version>
>        </dependency>
> -       <dependency>
> -           <groupId>org.apache.wicket</groupId>
> -           <artifactId>wicket-native-websocket-core</artifactId>
> -           <version>${wicket.version}</version>
> -       </dependency>
> -
> -
>        <!-- OPTIONAL DEPENDENCY
>        <dependency>
>            <groupId>org.apache.wicket</groupId>
> @@ -114,14 +107,12 @@
>            <scope>test</scope>
>        </dependency>
> -       <!-- uncomment if WebSocket support is needed
>        <dependency>
>            <groupId>org.eclipse.jetty.websocket</groupId>
>            <artifactId>javax-websocket-server-impl</artifactId>
>            <version>${jetty9.version}</version>
>            <scope>test</scope>
>        </dependency>
> -       -->
>    </dependencies>
>    <build>
>        <resources>
> diff --git src/main/java/com/mycompany/BackgroundWorkPage.java
> src/main/java/com/mycompany/BackgroundWorkPage.java
> index 76d84be..4bd7b84 100644
> --- src/main/java/com/mycompany/BackgroundWorkPage.java
> +++ src/main/java/com/mycompany/BackgroundWorkPage.java
> @@ -23,7 +23,6 @@ public class BackgroundWorkPage extends WebSocketPage {
> super(parameters);
> }
> -
> @Override
> protected void onInitialize() {
> super.onInitialize();
> @@ -61,7 +60,7 @@ public class BackgroundWorkPage extends WebSocketPage {
> });
> future.exceptionally(ex->{
> - log.error("big caclulation failed", ex);
> + log.error("big calculation failed", ex);
> return null;
> });
> diff --git src/main/java/com/mycompany/StartWebSocketPage.java
> src/main/java/com/mycompany/StartWebSocketPage.java
> index 56d1a99..5d1d9f6 100644
> --- src/main/java/com/mycompany/StartWebSocketPage.java
> +++ src/main/java/com/mycompany/StartWebSocketPage.java
> @@ -1,12 +1,10 @@
> package com.mycompany;
> import com.mycompany.pushmessages.WebSocketConnected;
> -import org.apache.wicket.Component;
> -import org.apache.wicket.Page;
> +
> import org.apache.wicket.ajax.AjaxRequestTarget;
> import org.apache.wicket.ajax.markup.html.AjaxLink;
> import org.apache.wicket.markup.html.link.BookmarkablePageLink;
> -import org.apache.wicket.model.Model;
> import org.apache.wicket.protocol.ws.api.WebSocketRequestHandler;
> import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage;
> import org.apache.wicket.request.mapper.parameter.PageParameters;
> @@ -39,7 +37,7 @@ public class StartWebSocketPage extends WebSocketPage {
> setEnabled(isWebSocketConnected());
> }
> };
> - btn.setOutputMarkupId(true);
> + btn.setOutputMarkupPlaceholderTag(true);
> add(btn);
> @@ -50,7 +48,7 @@ public class StartWebSocketPage extends WebSocketPage {
> setEnabled(isWebSocketConnected());
> }
> };
> - worksBtn.setOutputMarkupId(true);
> + worksBtn.setOutputMarkupPlaceholderTag(true);
> add(worksBtn);
> }
> diff --git src/main/java/com/mycompany/WebSocketPage.java
> src/main/java/com/mycompany/WebSocketPage.java
> index bdcb47b..f6118fe 100644
> --- src/main/java/com/mycompany/WebSocketPage.java
> +++ src/main/java/com/mycompany/WebSocketPage.java
> @@ -16,7 +16,7 @@ import org.slf4j.LoggerFactory;
> public class WebSocketPage extends WebPage {
> - static Logger log = LoggerFactory.getLogger(WebSocketPage.class);
> + Logger log = LoggerFactory.getLogger(getClass());
> private ConnectedMessage connectedMessage = null;
> @@ -70,7 +70,7 @@ public class WebSocketPage extends WebPage {
> }
> protected void onWebSocketMessage(WebSocketRequestHandler handler,
> IWebSocketPushMessage message) {
> -
> + log.info("onWebSocketMessage: {}, {}", getClass(), message);
> }
> diff --git src/main/java/com/mycompany/WicketApplication.java
> src/main/java/com/mycompany/WicketApplication.java
> index 85346e5..dbb0c47 100644
> --- src/main/java/com/mycompany/WicketApplication.java
> +++ src/main/java/com/mycompany/WicketApplication.java
> @@ -1,6 +1,7 @@
> package com.mycompany;
> import org.apache.wicket.Application;
> +import org.apache.wicket.Page;
> import org.apache.wicket.markup.html.WebPage;
> import org.apache.wicket.protocol.http.WebApplication;
> import org.apache.wicket.protocol.ws.WebSocketSettings;
> @@ -33,10 +34,6 @@ public class WicketApplication extends WebApplication
>        broadcaster.broadcast(connectedMsg, message);
>    }
> -
> -
> -
> -
>    /**
>     * @see org.apache.wicket.Application#getHomePage()
>     */
> @@ -65,13 +62,19 @@ public class WicketApplication extends WebApplication
>        getFrameworkSettings().setSerializer(new
> JavaSerializer(getApplicationKey()){
>            public byte[] serialize(Object obj) {
> -               log.info("serialize " + obj.getClass() + " " +
> obj.hashCode());
> +               if (obj instanceof Page) {
> +                   Page p = (Page) obj;
> +                   log.info("===serialize " + p.getClass() + " " +
> p.getId());
> +               }
>                return super.serialize(obj);
>            }
>            public Object deserialize(byte[] data) {
>                Object res = super.deserialize(data);
> -               log.info("deserialize " + res.getClass() + " " +
> res.hashCode());
> +               if (res instanceof Page) {
> +                   Page p = (Page) res;
> +                   log.info("---deserialize " + p.getClass() + " " +
> p.getId());
> +               }
>                return res;
>            }
>        });
> diff --git src/test/java/com/mycompany/Start.java
> src/test/java/com/mycompany/Start.java
> index 9acdb08..f06825d 100644
> --- src/test/java/com/mycompany/Start.java
> +++ src/test/java/com/mycompany/Start.java
> @@ -3,7 +3,11 @@ package com.mycompany;
> import java.lang.management.ManagementFactory;
> import javax.management.MBeanServer;
> +import javax.servlet.ServletException;
> +import javax.websocket.DeploymentException;
> +import javax.websocket.server.ServerContainer;
> +import org.apache.wicket.protocol.ws.javax.WicketServerEndpointConfig;
> import org.eclipse.jetty.jmx.MBeanContainer;
> import org.eclipse.jetty.server.HttpConfiguration;
> import org.eclipse.jetty.server.HttpConnectionFactory;
> @@ -14,6 +18,7 @@ import org.eclipse.jetty.server.SslConnectionFactory;
> import org.eclipse.jetty.util.resource.Resource;
> import org.eclipse.jetty.util.ssl.SslContextFactory;
> import org.eclipse.jetty.webapp.WebAppContext;
> +import
>
> org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
> /**
> * Separate startup class for people that want to run the examples directly.
> Use parameter
> @@ -26,8 +31,7 @@ public class Start
>     *
>     * @param args
>     */
> -   public static void main(String[] args)
> -   {
> +   public static void main(String[] args) throws DeploymentException,
> ServletException {
>        System.setProperty("wicket.configuration", "development");
>        Server server = new Server();
> @@ -80,8 +84,8 @@ public class Start
>        // uncomment the next two lines if you want to start Jetty with
> WebSocket (JSR-356) support
>        // you need org.apache.wicket:wicket-native-websocket-javax in the
> classpath!
> -       // ServerContainer serverContainer =
> WebSocketServerContainerInitializer.configureContext(bb);
> -       // serverContainer.addEndpoint(new WicketServerEndpointConfig());
> +       ServerContainer serverContainer =
> WebSocketServerContainerInitializer.configureContext(bb);
> +       serverContainer.addEndpoint(new WicketServerEndpointConfig());
>        // uncomment next line if you want to test with JSESSIONID encoded
> in the urls
>        // ((AbstractSessionManager)
>
>
>
>
> On Tue, Jul 2, 2019 at 1:14 PM Peter Henderson <
> peter.henderson@starjar.com>
> wrote:
>
> > Hi all,
> >
> > QuickStart: https://github.com/bollinger/WicketWebsocketsTest
> >
> >
> >
> > I have a page StartPage[1] which uses web sockets. On this page there is
> an
> > AjaxLink which redirects to a BackgroundPage[2].
> >
> >
> > The BackgroundPage also uses web sockets. It waits for a web socket
> > connection, then kicks off some background work. When the work completes
> it
> > tries to display the results.
> >
> >
> >
> > When navigating directly to the Background page or via a bookmarkable
> link,
> > all works as expected.
> >
> >
> > When arriving at Background page via the AjaxLink funky stuff happens.
> The
> > background work completes but it cannot send a message to the page to
> > refresh because the stored connectedMessage is null.
> >
> > Looking at the serialization it seems like there are 2 background pages.
> >
> >
> >
> > I’m probably doing something incorrectly, but what?
> >
> >
> > Many thanks.
> >
> > Peter.
> >
> >
> >
> > [1]
> >
> >
> >
> https://github.com/bollinger/WicketWebsocketsTest/blob/master/src/main/java/com/mycompany/StartWebSocketPage.java
> >
> >
> >
> > [2]
> >
> >
> >
> https://github.com/bollinger/WicketWebsocketsTest/blob/master/src/main/java/com/mycompany/BackgroundWorkPage.java
> >
> >
> > --
> > Peter Henderson
> >
>




Hi,

Thanks for looking into this. You debugging diffs really helped.


Boiling my question down.

1) What is the correct way of enabling components when a web socket is
connected?

WebSocketBehavior.onConnect
does not have a WebSocketRequestHandler handler so cannot update components
of the page.

Component.onEvent with a payload of WebSocketConnectedPayload
has a handler but it seems not to work. (probably identical to onConnect)

My broadcast bodge works when the start page is not web socket connected.







2) Why is there a difference behaviour of the background page depending on
if the starting page [1] has websockets enabled.

Boring non web socket start page. all works
[https-jsse-nio-25000-exec-138] INFO com.mycompany.BackgroundWorkPage -
onInit BackgroundWorkPage
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize BoringStartPage 4
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize BackgroundWorkPage 5
[https-jsse-nio-25000-exec-142] INFO com.mycompany.WebSocketPage - onEvent
WebSocketConnectedPayload
[https-jsse-nio-25000-exec-142] INFO com.mycompany.WebSocketPage - onConnect
[https-jsse-nio-25000-exec-142] INFO com.mycompany.WebSocketPage -
Broadcasting WebSocketConnected
[https-jsse-nio-25000-exec-142] INFO com.mycompany.WebSocketPage - onEvent
websocketpushpayload
[https-jsse-nio-25000-exec-142] INFO com.mycompany.WebSocketPage -
onWebSocketMessage: BackgroundWorkPage, WebSocketConnected
[https-jsse-nio-25000-exec-142] INFO com.mycompany.BackgroundWorkPage -
received WebSocketConnected
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize BackgroundWorkPage 5
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize BackgroundWorkPage 5
[ForkJoinPool.commonPool-worker-19] INFO com.mycompany.BackgroundWorkPage -
Calculation future finished sending out a message
[ForkJoinPool.commonPool-worker-19] INFO com.mycompany.WebSocketPage -
Broadcasting CalculationFinished
[ForkJoinPool.commonPool-worker-19] INFO com.mycompany.WebSocketPage -
onEvent websocketpushpayload
[ForkJoinPool.commonPool-worker-19] INFO com.mycompany.WebSocketPage -
onWebSocketMessage: BackgroundWorkPage, CalculationFinished
[ForkJoinPool.commonPool-worker-19] INFO com.mycompany.BackgroundWorkPage -
received CalculationFinished
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize BackgroundWorkPage 5


WebSocket start page fails.
[https-jsse-nio-25000-exec-131] INFO com.mycompany.BackgroundWorkPage -
onInit BackgroundWorkPage
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize StartWebSocketPage 0
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize BackgroundWorkPage 1
[https-jsse-nio-25000-exec-130] INFO com.mycompany.WebSocketPage - onEvent
other WebSocketClosedPayload
[https-jsse-nio-25000-exec-130] INFO com.mycompany.WebSocketPage - onClose
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize StartWebSocketPage 0
[https-jsse-nio-25000-exec-113] INFO com.mycompany.WicketApplication -
---deserialize BackgroundWorkPage 1
[https-jsse-nio-25000-exec-113] INFO com.mycompany.WebSocketPage - onEvent
WebSocketConnectedPayload
[https-jsse-nio-25000-exec-113] INFO com.mycompany.WebSocketPage - onConnect
[https-jsse-nio-25000-exec-113] INFO com.mycompany.WebSocketPage -
Broadcasting WebSocketConnected
[https-jsse-nio-25000-exec-113] INFO com.mycompany.WicketApplication -
---deserialize BackgroundWorkPage 1
[https-jsse-nio-25000-exec-113] INFO com.mycompany.WebSocketPage - onEvent
websocketpushpayload
[https-jsse-nio-25000-exec-113] INFO com.mycompany.WebSocketPage -
onWebSocketMessage: BackgroundWorkPage, WebSocketConnected
[https-jsse-nio-25000-exec-113] INFO com.mycompany.BackgroundWorkPage -
received WebSocketConnected
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize BackgroundWorkPage 1
[Wicket-AsyncPageStore-PageSavingThread] INFO
com.mycompany.WicketApplication - ===serialize BackgroundWorkPage 1
[ForkJoinPool.commonPool-worker-19] INFO com.mycompany.BackgroundWorkPage -
Calculation future finished sending out a message
[ForkJoinPool.commonPool-worker-19] INFO com.mycompany.WebSocketPage - Not
broadcasting, connectedMessage is null?

[1]
https://github.com/bollinger/WicketWebsocketsTest/blob/master/src/main/java/com/mycompany/BoringStartPage.java



-- 
Peter Henderson

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message