Push (comet) style model update

89 views
Skip to first unread message

Mario Giammarco

unread,
Jan 5, 2018, 3:31:15 AM1/5/18
to invesdwin-platform
Hello,
this one is difficult.
I receive from a jms camel queue an asychronous message (from a secondary thread) and I update the Java model.
How can I force a page update?
I a Vaadin application I had to add a comet/websocket plugin that semi automatically triggered a page refresh from web page.
Have you some suggestions?
Thanks,
Mario

Edwin Stang

unread,
Jan 5, 2018, 5:49:25 AM1/5/18
to invesdwin-platform
It is essentially the same approach in wicket and requires a little page code. A quick google revealed the following example code: https://github.com/martin-g/blogs/blob/master/wicket6-websocket-broadcast/src/main/java/com/wicketinaction/FeedPage.java
Inside FeedPage.handleMessage() you can do your model modifications and call GuiService.processRequestFinally(this) to push the changes to the client.

Here are also a few more approaches on how to do it, but the one above seems to be the most simple one: https://stackoverflow.com/questions/20100732/trigger-repainting-a-wicket-component-via-push-message

I guess this functionality could be wrapped into a reusable (abstract) behavior. If you have something that works I would be happy for a pull request or a sample that I can incorporate.

Mario Giammarco

unread,
Mar 18, 2018, 1:24:27 PM3/18/18
to invesdwin-platform
Hello,
since I need to show quickly a working prototype I think about cheating.
I will not use comet for now and I would like to use an AbstractAjaxTimerBehavior.
I will start the time on search button press and I will stop the timer when I receive latest reply from backend.
I would like to know if I can put an AbstractAjaxTimerBehavior in an interceptor and on which component I should add it.
Thanks,
Mario

Mario Giammarco

unread,
Mar 18, 2018, 1:34:05 PM3/18/18
to invesdwin-platform
I forgot to say that in the final page there will be some tabs with in each one an AjaxDataTable and I need to update the on timer timeout.

Edwin Stang

unread,
Mar 18, 2018, 3:06:56 PM3/18/18
to invesdwin-platform
You can either put one AjaxTimerBehavior per Panel for each Tab individually. Or have one for the whole Page. In either case it is best to register them to a component that lives beyond page refreshes if the AjaxTimerBehavior should survive ajax refreshes on the client side. Everything that is inside a Wicket-Form will be replaced by the NoWicket update mechanism. Though I would suggest just trying a few possibilities and see which variation suits your requirements best.

Worst case if you put it on a component that gets replaced, you might get multiple AjaxTimerBehaviors started each time a refresh occurs. Though you can prevent that also via additional code. But just adding all behaviors to the page directly is the safest approach.

Internally we use Components.findRoot(markupContainer) to get the page from any component to add our own behaviors that handle the GuiService functionality here: https://github.com/subes/invesdwin-nowicket/blob/master/invesdwin-nowicket-parent/invesdwin-nowicket/src/main/java/de/invesdwin/nowicket/generated/guiservice/internal/SessionGuiService.java

Though that use case is more involved since we also need to make sure only one behavior is added while multiple NoWicket panels/components might request that to be added to a page. That is why we use MetaDataKeys to handle the state globally for the page so no duplication occurs. Your use case should normally not require that workaround, but it depends on your usage.

Mario Giammarco

unread,
Mar 19, 2018, 5:09:15 PM3/19/18
to invesdwin-platform
I have tried to add the ajax timer in the search button but I get a null pointer exception:

if (HomeConstants.cerca.equals(e.getWicketId())) {
                    final Component c = super.createSubmitButton(e);
                    c.add(new AbstractAjaxTimerBehavior(Duration.seconds(1)) {

in the line c.add......

It seems strange to me because super method should create something.
I have commited and pushed the code on the project you already have.
Thanks for any hint.
Mario

sub es

unread,
Mar 19, 2018, 5:25:10 PM3/19/18
to Mario Giammarco, invesdwin-platform
Hi Mario

if you look at the base class of your interceptor you see that it returns null. To get the default instantiated you would have to call the default binding builder implementation. Though it can only be accessed by instantiating it yourself, as using it is discouraged. What you are doing is not intended usage. You use an interceptor to replace components if you don't want the default components.

If you just want to reconfigure or modify the components, you should use the components registry to look them up after the generatedbinding.generate() is finished.

You can access the component registry via either:
generatedbinding.getContext().getComponentRegistry()

Or if you don't want to create a separate variable for the generatedbinding instance, just request it via:
HtmlContext.get(this).getComponentRegistry()

An example can be found at:

Best regards,
Edwin

Gesendet: 19. März 2018 10:09 nachm.
Betreff: Re: Push (comet) style model update

I have tried to add the ajax timer in the search button but I get a null pointer exception:

if (HomeConstants.cerca.equals(e.getWicketId())) {
                    final Component c = super.createSubmitButton(e);
                    c.add(new AbstractAjaxTimerBehavior(Duration.seconds(1)) {

in the line c.add......

It seems strange to me because super method should create something.
I have commited and pushed the code on the project you already have.
Thanks for any hint.
Mario

Il giorno domenica 18 marzo 2018 20:06:56 UTC+1, Edwin Stang ha scritto:
You can either put one AjaxTimerBehavior per Panel for each Tab individually. Or have one for the whole Page. In either case it is best to register them to a component that lives beyond page refreshes if the AjaxTimerBehavior should survive ajax refreshes on the client side. Everything that is inside a Wicket-Form will be replaced by the NoWicket update mechanism. Though I would suggest just trying a few possibilities and see which variation suits your requirements best.

Worst case if you put it on a component that gets replaced, you might get multiple AjaxTimerBehaviors started each time a refresh occurs. Though you can prevent that also via additional code. But just adding all behaviors to the page directly is the safest approach.

...

Edwin Stang

unread,
Mar 19, 2018, 5:30:38 PM3/19/18
to invesdwin-platform
Alternatively it should also be possible to override the configure(...) method of your binding interceptor to modify the component as it is passed through. Though this should normally only be used to add behaviors to all components or if the interceptor should be reusable between pages/panels. But it can still be used for special cases if you prefer it that way.
Message has been deleted

Mario Giammarco

unread,
Mar 20, 2018, 7:48:47 AM3/20/18
to invesdwin-platform
Ok I have thought about it.
I added ajax timer on onConfigure step it was very easy.
I ask you if you have also javadocs of NoWicket.
Now to keep model clean I would like that the onTimer() call back calls the current model so the model can take the decision to refresh page based on its state.
How can I get current model object?
Thanks,
Mario

sub es

unread,
Mar 20, 2018, 8:00:45 AM3/20/18
to Mario Giammarco, invesdwin-platform
Please tell your ide/maven to download the sources. This is much better than the javadoc and you also see the documentation via tooltips in your IDE. In m2e in Eclipse you can tell maven per project to download sources or you can tell it by default in the settings to always download sources.

To get the model, call HtmlContext.getModel(component).
The idea is to fetch the current model from the page/panel. It is a bad idea to store that model since serialization will duplicate the instances and your information will get out of sync. So it is better to always retrieve the model object from the page/panel.

Regarding setting the timer in the model, I guess you found out yourself that this is against the MVC pattern. The Model should not in any way know about the components or wicket specifics. Though it is possible to access this stuff in models via RequestCycle.getPage and then retrieving a specific component (the Components utility class provides some helpers for that) from the page to then access the appropriate HtmlContext/ComponentRegistry. Though this should normally be avoided as much as possible. And storing wicket components in models is even worse. :D

Best regards,
Edwin



Gesendet: 20. März 2018 12:48 nachm.
Betreff: Re: Push (comet) style model update

Ok I have thought about it.
I added ajax timer on onConfigure step it was very easy.
I ask you if you have also javadocs of NoWicket.
Now to keep model clean I would like that the onTimer() call back calls the current model so the model can take the decision to refresh page based on its state.
How can I get current model object?
Thanks,
Mario

Il giorno lunedì 19 marzo 2018 22:25:10 UTC+1, subes ha scritto:
Hi Mario

if you look at the base class of your interceptor you see that it returns null. To get the default instantiated you would have to call the default binding builder implementation. Though it can only be accessed by instantiating it yourself, as using it is discouraged. What you are doing is not intended usage. You use an interceptor to replace components if you don't want the default components.

If you just want to reconfigure or modify the components, you should use the components registry to look them up after the generatedbinding.generate() is finished.

You can access the component registry via either:
generatedbinding.getContext().getComponentRegistry()

Or if you don't want to create a separate variable for the generatedbinding instance, just request it via:
HtmlContext.get(this).getComponentRegistry()

An example can be found at:

...

Mario Giammarco

unread,
Mar 20, 2018, 8:04:02 AM3/20/18
to invesdwin-platform
I am trying to understand better.
Basically if I use this code:

protected void onTimer(final AjaxRequestTarget target) {
                                GuiService.get().processRequestFinally(getComponent());
            }

I get uncontrolled page refresh so I need to control  start and stop from the model.

So I tried this way:

protected void onTimer(final AjaxRequestTarget target) {
                            
            }


The timer got fired but I do nothing. My hope was that model was called again and so it can choose what to do.
I get only that, at first refresh, all widgets get readonly.

Mario Giammarco

unread,
Mar 20, 2018, 8:11:19 AM3/20/18
to invesdwin-platform
I completely agree, I would like to keep model completely agnostic about wicket framework.
Infact I just replied that my idea is: a timer fires, a page reloading get executed, the model is called again.
The model, if it thinks it is good,  update its state and web page on the browser get updated.
It is an approach similar to what elm-language does.
But please look the other message because the timer fires but I do not get the expected result.

subes

unread,
Mar 20, 2018, 8:19:05 AM3/20/18
to invesdwin-platform
The components stay disabled because this script:
https://github.com/subes/invesdwin-nowicket/blob/master/invesdwin-nowicket-parent/invesdwin-nowicket/src/main/java/de/invesdwin/nowicket/component/header/disableComponentsOnAjaxCall.js

waits for a onDomReady event. If you don't update any components from your model, the ajax response will not update the dom and thus the event will not be fired, thus the components will stay disabled. In that case add as a response to the AjaxRequestTarget either a component manually or call the javascript function "undisableComponentsAfterAjaxCall()" manually (or just fire a onDomReady event.

If you call "GuiService.get().
processRequestFinally(getComponent());", this will update all forms in the current page. You can prevent that by doing what I wrote in the paragraph above in the case that nothing should be updated. And if you don't want all forms to be updated, you can also add manually only specific components to be updated to the response, so that not a full refresh occurs. Though if you want to still have GuiServiceTasks to execute, you have to invoke them yourself. But I don't think this is needed for your use case.

The next problem might be that you don't want the components disabled at all during this request or maybe the ajax wait overlay is shown even if you don't want that. In that case there will be some javascript needed to disable that functionality for that timer. If you are that far I can have a look what the best solution would be for that case.

Mario Giammarco

unread,
Mar 20, 2018, 8:20:08 AM3/20/18
to invesdwin-platform
Reading again latest posts it seems there is a mismatch about what model is:
1) model can be the model of a wicket component;
2) model can be the class that extends AValueObject;

When I use the word "model" I mean 2) not 1) (in this thread at least)
So I write two examples of pseudo code to explain what I am trying to do:

FIRST


protected void onTimer(final AjaxRequestTarget target) {
    // I fire redraw of page only if there is something new to stop                         
  if (myHomeClass.isStateUpdated()) GuiService.get().processRequestFinally(getComponent());

}

SECOND


protected void onTimer(final AjaxRequestTarget target) {
    // I do nothing hoping that only firing the timer is enough for wicket/nowicket to invoke again myHomeClass               

subes

unread,
Mar 20, 2018, 8:24:22 AM3/20/18
to invesdwin-platform
If you look at the code of HtmlContext.getModel(component), you see that you will get "2) model can be the class that extends AValueObject;". Having the sources in your IDE downloaded and attached via maven, you should be able directly navigate into that method.

For the case "I do nothing", you have to at least call "undisableComponentsAfterAjaxCall()". You can add that to the AjaxRequestTarget as inline-Javascript.

Mario Giammarco

unread,
Mar 20, 2018, 1:31:42 PM3/20/18
to invesdwin-platform
Ok I am stuck.
I have followed your precious suggestions and now I have this code:

int actualSize = 0;

            @Override

            protected void onTimer(final AjaxRequestTarget target) {
                final int size = ((Home) HtmlContext.getModel(c).getObject()).getRisultati().size();
                if (size > actualSize) {
                    logger.debug("++++++++++++++++rinfresco pagina");
                    GuiService.get().processRequestFinally(getComponent());

                } else {
                    target.add(c);

                }
                actualSize = size;
            }

I have two problems, one blocking and one minor:

1) Blocking one: getRisultati() of my model gives updated result but the web page output does not change
2) Minor one: ajax refreshes all page I need to check better how to refresh only tabs

Mario Giammarco

unread,
Mar 20, 2018, 3:19:37 PM3/20/18
to invesdwin-platform
Ok I have enable spring support just in case to solve also singleton issue.

Now I get an exception that does not seems related to my code (that I have committed and pushed):

Root cause:

java.lang.AssertionError: [Unable to find any Panel for model class [it.giammar.umwebclient.ng.panel.QueryReplyModel] or any of its super classes!]
Expecting actual not to be null
at de.invesdwin.nowicket.application.PanelFactory.getPanel(PanelFactory.java:36)
at de.invesdwin.nowicket.generated.binding.processor.visitor.builder.component.tabbed.ModelTab.getPanel(ModelTab.java:42)
at org.apache.wicket.extensions.markup.html.tabs.TabbedPanel.setCurrentTab(TabbedPanel.java:422)
at org.apache.wicket.extensions.markup.html.tabs.TabbedPanel.onBeforeRender(TabbedPanel.java:272)
at org.apache.wicket.Component.internalBeforeRender(Component.java:949)
at org.apache.wicket.Component.beforeRender(Component.java:1017)
at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1568)
at org.apache.wicket.Component.onBeforeRender(Component.java:3877)
at org.apache.wicket.Component.internalBeforeRender(Component.java:949)
at org.apache.wicket.Component.beforeRender(Component.java:1017)
at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1568)
at org.apache.wicket.Component.onBeforeRender(Component.java:3877)
at org.apache.wicket.markup.html.border.Border.onBeforeRender(Border.java:637)
at org.apache.wicket.Component.internalBeforeRender(Component.java:949)
at org.apache.wicket.Component.beforeRender(Component.java:1017)
at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1568)
at org.apache.wicket.Component.onBeforeRender(Component.java:3877)
at org.apache.wicket.markup.html.form.Form.onBeforeRender(Form.java:1807)
at de.invesdwin.nowicket.component.csrf.CsrfTokenForm.onBeforeRender(CsrfTokenForm.java:33)
at org.apache.wicket.Component.internalBeforeRender(Component.java:949)
at org.apache.wicket.Component.beforeRender(Component.java:1017)
at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1568)
at org.apache.wicket.Component.onBeforeRender(Component.java:3877)
at org.apache.wicket.Page.onBeforeRender(Page.java:801)
at org.apache.wicket.Component.internalBeforeRender(Component.java:949)
at org.apache.wicket.Component.beforeRender(Component.java:1017)
at org.apache.wicket.Component.internalPrepareForRender(Component.java:2215)
at org.apache.wicket.Page.internalPrepareForRender(Page.java:242)
at org.apache.wicket.Component.render(Component.java:2304)
at org.apache.wicket.Page.renderPage(Page.java:1018)
at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:124)
at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:236)
at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:175)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:865)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:265)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:222)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:293)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:261)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:203)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:284)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

Complete stack:

org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public de.invesdwin.nowicket.page.error.defaultpage.DefaultInternalErrorPage()'. An exception has been thrown during construction!
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:194)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:67)
at de.invesdwin.nowicket.application.filter.internal.ModelCacheUsingPageFactory.newPage(ModelCacheUsingPageFactory.java:46)
at org.apache.wicket.DefaultMapperContext.newPageInstance(DefaultMapperContext.java:102)
at org.apache.wicket.core.request.handler.PageProvider.resolvePageInstance(PageProvider.java:271)
at org.apache.wicket.core.request.handler.PageProvider.getPageInstance(PageProvider.java:169)
at org.apache.wicket.request.handler.render.PageRenderer.getPage(PageRenderer.java:78)
at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:102)
at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:195)
at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:175)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:865)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:265)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:222)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:293)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:261)

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:175)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:67)
at de.invesdwin.nowicket.application.filter.internal.ModelCacheUsingPageFactory.newPage(ModelCacheUsingPageFactory.java:46)
at org.apache.wicket.DefaultMapperContext.newPageInstance(DefaultMapperContext.java:102)
at org.apache.wicket.core.request.handler.PageProvider.resolvePageInstance(PageProvider.java:271)
at org.apache.wicket.core.request.handler.PageProvider.getPageInstance(PageProvider.java:169)
at org.apache.wicket.request.handler.render.PageRenderer.getPage(PageRenderer.java:78)
at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:102)
at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:195)
at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:175)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:865)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:265)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:222)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:293)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:261)

java.lang.RuntimeException: javax.servlet.ServletException: RequestUri: /home, ServletName: default, StatusCode: 500, Message:
at de.invesdwin.nowicket.page.error.AErrorPanel.showServletException(AErrorPanel.java:39)
at de.invesdwin.nowicket.page.error.AErrorPanel.<init>(AErrorPanel.java:21)
at de.invesdwin.nowicket.page.error.InternalErrorPanel.<init>(InternalErrorPanel.java:18)
at de.invesdwin.nowicket.page.error.InternalErrorPanel.<init>(InternalErrorPanel.java:14)
at de.invesdwin.nowicket.page.error.defaultpage.DefaultInternalErrorPage.<init>(DefaultInternalErrorPage.java:24)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:175)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:67)
at de.invesdwin.nowicket.application.filter.internal.ModelCacheUsingPageFactory.newPage(ModelCacheUsingPageFactory.java:46)
at org.apache.wicket.DefaultMapperContext.newPageInstance(DefaultMapperContext.java:102)
at org.apache.wicket.core.request.handler.PageProvider.resolvePageInstance(PageProvider.java:271)
at org.apache.wicket.core.request.handler.PageProvider.getPageInstance(PageProvider.java:169)
at org.apache.wicket.request.handler.render.PageRenderer.getPage(PageRenderer.java:78)
at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:102)
at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:195)
at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:175)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:865)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:265)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:222)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:293)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:261)

javax.servlet.ServletException: RequestUri: /home, ServletName: default, StatusCode: 500, Message:
at de.invesdwin.nowicket.page.error.AErrorPanel.showServletException(AErrorPanel.java:39)
at de.invesdwin.nowicket.page.error.AErrorPanel.<init>(AErrorPanel.java:21)
at de.invesdwin.nowicket.page.error.InternalErrorPanel.<init>(InternalErrorPanel.java:18)
at de.invesdwin.nowicket.page.error.InternalErrorPanel.<init>(InternalErrorPanel.java:14)
at de.invesdwin.nowicket.page.error.defaultpage.DefaultInternalErrorPage.<init>(DefaultInternalErrorPage.java:24)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:175)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:67)
at de.invesdwin.nowicket.application.filter.internal.ModelCacheUsingPageFactory.newPage(ModelCacheUsingPageFactory.java:46)
at org.apache.wicket.DefaultMapperContext.newPageInstance(DefaultMapperContext.java:102)
at org.apache.wicket.core.request.handler.PageProvider.resolvePageInstance(PageProvider.java:271)
at org.apache.wicket.core.request.handler.PageProvider.getPageInstance(PageProvider.java:169)
at org.apache.wicket.request.handler.render.PageRenderer.getPage(PageRenderer.java:78)
at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:102)
at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:195)
at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:175)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:865)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:265)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:222)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:293)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:261)

javax.servlet.ServletException: Filter execution threw an exception
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

sub es

unread,
Mar 20, 2018, 3:27:56 PM3/20/18
to Mario Giammarco, invesdwin-platform
This is a follow up error because the page could not be instantiated. Somewhere above that error message the real error should have been logged.


...

sub es

unread,
Mar 20, 2018, 3:41:28 PM3/20/18
to Mario Giammarco, invesdwin-platform
Ah no, it is telling that it cannot find a QueryReplyModelPanel class. Maybe your naming pattern is off. Or maybe you exposed a property that should have been actually annotated with @Hidden?


...

Mario Giammarco

unread,
Mar 20, 2018, 6:37:30 PM3/20/18
to invesdwin-platform
It is incredible. The exact name is QueryReplyModelPanel. I had QueryReplyPanel for all day and it did not complain. I wonder what I do to let NoWicket discover the name mismatch.
Anyway I confirm the problem: web gui now works but it is not updated.
I now have a singleton Backend done with spring @Component that is injected in the model.
I log operations and I see from the ajax timer callback that the result list from backend gets bigger.
But unfortunately the web page do not reflect the model update.

sub es

unread,
Mar 20, 2018, 7:00:06 PM3/20/18
to Mario Giammarco, invesdwin-platform
I will investigate that tomorrow.

--
You received this message because you are subscribed to the Google Groups "invesdwin-platform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to invesdwin-platf...@googlegroups.com.
To post to this group, send email to invesdwin...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/invesdwin-platform/034d2966-52de-4048-81cb-b350c8915ea9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Edwin Stang

unread,
Mar 21, 2018, 10:27:47 AM3/21/18
to invesdwin-platform
Thanks for reporting the issue with non updating tabs. I was able to reproduce the issue and fix it with this commit: https://github.com/subes/invesdwin-nowicket/commit/59a3cec71ef65029c4e8b9bbedbe1c52adff3402

Actually wickets TabbedPanel does not natively support dynamic tabs because it uses a direct list of tabs instead of an IModel<list of tabs>, but I found a way to trick it into becoming dynamic.

Also I had to change your code to add the behavior in the constructor to the page (instead of the search button) because the update timer stopped for me otherwise after the first successful update. This is because the update replaces the search button and then the behavior is lost too. Also using onConfigure to add behaviors is a bad idea because then you would get duplicate behaviors. I have attached the fixed HomePage.java.

Please update your snapshots to get the changes.

Best regards,
Edwin
To unsubscribe from this group and stop receiving emails from it, send an email to invesdwin-platform+unsub...@googlegroups.com.
To post to this group, send email to invesdwin-platform@googlegroups.com.
HomePage.java

Edwin Stang

unread,
Mar 21, 2018, 11:06:43 AM3/21/18
to invesdwin-platform
I have now also made the disabling of components during ajax requests a bit more intelligent. See this commit: https://github.com/subes/invesdwin-nowicket/commit/9f8c374144b08e7a6d6fb7b5e175a5e1d40c5639

Now when you disable the ajax indicator for a component, the disabling of components will be skipped too. Also you now don't need to update anything on a request that should not update anything, since the undisable will now be called for any finished ajax request that previously disabled the components. Instead of only undisabling when ondomready event is fired.

Modify your timer behavior as follows to benefit from these changes:

-------------------------------------
add(new AbstractAjaxTimerBehavior(Duration.seconds(5)) {
            private final transient Logger logger = Logger.getLogger(HomePage.class);


            int actualSize = 0;

            @Override
            protected void onTimer(final AjaxRequestTarget target) {
                final int size = ((Home) HtmlContext.getModel(HomePage.this).getObject()).getRisultati().size();

                if (size > actualSize) {
                    logger.debug("++++++++++++++++rinfresco pagina");
                    GuiService.get().processRequestFinally(getComponent());
                }
                //no need to update anything after the request has finished anymore
                actualSize = size;
            }

            @Override
            protected String findIndicatorId() {
                //disable ajax indicator and disabling of components during refresh
                return null;
            }
        });
-------------------------------------

Best regards,
Edwin

Mario Giammarco

unread,
Mar 21, 2018, 12:49:21 PM3/21/18
to invesdwin-platform
I have just tried your last commits and I am very happy. Now tabs gets updated and it seems like the old application in vaadin I would like to replace.
I would like to understand better your last commit below. I can see clearly now the browser refresh of components: they get readonly for a moment and the readwrite again.
Is it the intended behaviour?
I gave maven -U clean compile tomcat7:run and used the last version of your code with findIndicatorId
To post to this group, send email to invesdwin...@googlegroups.com.

sub es

unread,
Mar 21, 2018, 12:54:01 PM3/21/18
to Mario Giammarco, invesdwin-platform
Can you check via browser debugging if the correctly modified javascript gets loaded? Or alternatively look into the jar directly and check that it contains the correct code.

After my change the disabling of components is skipped if the ajax event attribute for the indicator is not set. Which is controller by overriding the findIndicatorId.

Maybe you need to also reset your browser caches.
Gesendet: 21. März 2018 5:49 nachm.
To unsubscribe from this group and stop receiving emails from it, send an email to invesdwin-platf...@googlegroups.com.

To post to this group, send email to invesdwin...@googlegroups.com.

Mario Giammarco

unread,
Mar 22, 2018, 6:25:53 AM3/22/18
to invesdwin-platform
Damned caches I had to change browser to be sure.
Anyway I wrote you to say that on page refresh I stil had problems when clicking on dropdown boxes.
And so I solved the problem in this way ( I simulate a component change only if there is a new result):


 @Override
            protected void onTimer(final AjaxRequestTarget target) {
                final int size = ((Home) HtmlContext.getModel(HomePage.this).getObject()).getRisultati().size();
                if (size > actualSize) {
                    //                                logger.debug("++++++++++++++++rinfresco pagina");
                    //                                GuiService.get().processRequestFinally(getComponent());
                    //
                    //                            } else {
                    final Component c = HtmlContext.get(HomePage.this).getComponentRegistry().getComponent(
                            HomeConstants.risultati);
                    target.add(c);

                }
                actualSize = size;

Edwin Stang

unread,
Mar 22, 2018, 6:41:21 AM3/22/18
to invesdwin-platform
Yes, this is the correct solution. The combo boxes got closed during refresh because they got replaced. You might also want to stop the timer as soon as all results have been loaded or reset it when a new search is being started.

Root cause:

Mario Giammarco

unread,
Mar 22, 2018, 6:43:46 AM3/22/18
to invesdwin-platform
Yes I will also do it but unfortunately I already know that, sometimes, the remote backend do not send all results so I cannot stop the search and consider it completed (sigh)

Root cause:

Edwin Stang

unread,
Mar 22, 2018, 7:50:32 AM3/22/18
to invesdwin-platform
I have now also made it possible to process gui tasks (modal panels, status messages and so on) without having to update all componets. See commit: https://github.com/subes/invesdwin-nowicket/commit/9457fb24a6c8c93e2a1cd36240552ff551a9efab

Call GuiService.get().disableUpdateAllComponentsForCurrentRequest() to only get updates of components that are required for the gui tasks (if any). All other components that should be updated due to model changes will have to be updated manually. Though this is only relevant if for example during your search an error can occur that should be made visible by your timer method via a dialog or status message. Or you could also push a finished message like this.

Best regards,
Edwin

Root cause:

Edwin Stang

unread,
Mar 22, 2018, 7:52:51 AM3/22/18
to invesdwin-platform
Forgot to mention that this controls the behavior or GuiSerivce.get().processRequestFinally(). So this still needs to be called so that the gui tasks actually get processed.

Root cause:

Mario Giammarco

unread,
Mar 25, 2018, 5:30:56 AM3/25/18
to invesdwin-platform
Nice to hear I will see how I can use it.

Root cause:

     at org.apache.wicket.markup.html.form.Form.onBeforeRender(<a href="http://Form.java:1807" rel="nofollow" target="_blank" on

subes

unread,
Jul 25, 2018, 9:30:12 PM7/25/18
to invesdwin-platform
After upgrading to Wicket 8.0.0 and experimenting a bit with the native websocket support, we now have a working example for using web sockets with nowicket:


Wicket normally does not support falling back to other forms of communication, so we created AWebSocketFallbackTimerBehavior to handle graceful fallback to ajax while providing bidirectional communication on a timer basis. For direct web socket usage, refer to the class AWebSocketBehavior. Push messages are only available when a web socket connection has been established. Otherwise the timer has to do its work, which should be sufficient for most use cases. Using web sockets for timers is also a good idea since network overhead should be reduced  in comparison to ajax when having frequent updates.

Anyway, just replace AbstractAjaxTimerBehavior with AWebSocketFallbackTimerBehavior for the benefit and make sure your webserver setup has web sockets enabled.

Root cause:

Mario Giammarco

unread,
Jul 26, 2018, 1:41:54 AM7/26/18
to subes, invesdwin-platform
Very nice news!
Thanks,
Mario

Inviato dal mio BlackBerry, il dispositivo mobile più sicuro
Inviato: 26 luglio 2018 3:30 AM
Oggetto: Re: Push (comet) style model update

--
You received this message because you are subscribed to a topic in the Google Groups "invesdwin-platform" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/invesdwin-platform/tNAOaZ6nYts/unsubscribe.
To unsubscribe from this group and all its topics, send an email to invesdwin-platf...@googlegroups.com.

To post to this group, send email to invesdwin...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages