You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by snair <sr...@transport.wa.gov.au> on 2013/02/08 07:00:10 UTC

call the same page using setResponsePage()

Is it ok to call the same page using setResponsePage(), only calling a
different constructor, since the page now needs to display additional
information, which I will be passing into this new constructor?  For
example, from PageA, can I say setResponsePage(new PageA(String a)) when a
submit button button is clicked.



--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/call-the-same-page-using-setResponsePage-tp4656192.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: call the same page using setResponsePage()

Posted by Bernard <bh...@gmail.com>.
Hi,

Thanks for the clarification. It is a correct explanation of Wicket's
behavior and design. But it documents an annoying weakness, that IMHO
could be addressed with a successful outcome.

I have the following suggestion (concept and code) for a remedy for
stateful bookmarkable pages:

It also addresses your concern of unpredictable behaviour because
Wicket does not know whether a component has been added to the page
after the page was instantiated. The idea is that we can provide
Wicket with this information.


Fix #1)

On initial render of the page before expiry, component target URLs of
e.g. StatelessLink must have their target URLs rendered correctly
otherwise the page cannot even be found. Currently this is not
happening because of Component#urlFor() depends on stateless not
bookmarkable. This fix may also improve Wicket performance because it
eliminates the expensive Component#isStateless() call.

This bug fix will ensure that on expiry the page is found and
reconstructed. The result is that the page is only refreshed but the
behavior of the component is not invoked.

Please see examples in

Mounted bookmarkable Page not recreated on Session Expiry
https://issues.apache.org/jira/browse/WICKET-4997

Recovery of bookmarkable Page after Session Expiry
https://issues.apache.org/jira/browse/WICKET-5001


Fix #2)

Looking ahead, the re-instantiation of expired pages may not work
because Wicket calls the wrong constructor. So we need another bug
fix:

PageProvider#getPageInstance() calls wrong Page Constructor if
pageParameters is null
https://issues.apache.org/jira/browse/WICKET-5008


Some of his already worked in Wicket 1.4


Fix #3)

One can improve the recovery by letting Wicket even invoke the
behavior of stateless components.

One achieves this by constructing the page differently if one can
detect that a constructor is called by the Wicket recovery logic. The
trick is to not add stateful components to the page before
onConfigure() so that Wicket does NOT execute the recovery logic
again. Wicket should handle the request normally as if the page was
indeed stateless. In onConfigure() one can either add the remaining
stateful components or take other action e.g. throw
RestartResponseException if the page should not be shown.

Why does this work for a StatelessLink (example) although the
component hierarchy may have been changed?

ListenerInterfaceRequestHandler#respond() can now re-create the page
and it finds the StatelessLink component and invokes its behaviour. 

Alternatively, if the request comes from a stateful component e.g.
AJAX on the same page then Wicket either does not find the component,
or it finds it by invoking Component#onBeforeRender() and destects
that the page is stateful. In both cases it just refreshes the page.

So the corresponding code already exists in the framework, and it
works to our advantage.

Regards,

Bernard


On Fri, 8 Feb 2013 12:07:17 +0100, you wrote:

>Hi,
>
>
>On Fri, Feb 8, 2013 at 11:44 AM, Bernard <bh...@gmail.com> wrote:
>
>> Hi,
>>
>> This is what I like about Wiket.
>>
>> Even if I start with a stateless page! So I update a component, and
>> Wicket takes care of it via server side state - job done.
>>
>> The page is then no longer stateless which is fair.
>>
>> But:
>>
>> When the user stays on this page and the session expires, then even
>> simple Links on the page like a sign-out link that do NOT require
>> state cause PageExpiredException. In this case the beautiful
>> advantages of using Wicket are gone. Working around these issues can
>> be very expensive because one has to examine every single page in the
>> special session expiry scenario. The workaround code becomes very
>> ugly.
>>
>> Are there any plans to fix this or is this a feature?
>>
>
>This is by design.
>If Wicket cannot find the old page by any reason (e.g. expired session with
>all its pages) then depending on the value of
>IPageSettings#getRecreateMountedPagesAfterExpiry() Wicket may create a new
>instance for you.
>Now:
>1) if the new instance is stateless then Wicket will execute the listener
>interface, i.e. will execute StatelessLink#onClick, StatelessForm#onSubmit,
>...
>2) if the newly created page is stateful Wicket will just render it
>*without* executing the listener interface
>Why ? Because the stateless link/form/behavior/... may or may not be in the
>page component tree. Wicket cannot make assumptions that the
>component/behavior exists in the page initial state (i.e. right after
>instantiating it). The link that your user has clicked on the expired page
>may have been added in state 2 of the page, and thus it is not available in
>state 1 (the initial state).
>
>Use case:
>- render a simple stateful page with just linkA and am empty panel
>- the user clicks on linkA which replaces the empty panel with a panel with
>linkB inside
>- later the user clicks on linkB
>- if the session is expired and Wicket creates a new instance of the page
>then linkB is not in the component tree. Only linkA and the empty panel are
>there. Once linkA is used linkB will appear, but Wicket cannot do this
>because it doesn't know what to do to get linkB and execute its onClick()
>method
>
>I'll add this explanation to a FAQ section at
>http://martin-g.github.com/wicket-reference-guide/stateless.html .
>
>If we change this behavior and try to execute the listener interface then
>it will work when linkB is in the initial state and will throw
>ComponentNotFoundException when linkB is added to the tree after some
>interaction. So it will become nondeterministic - a russian roulette.
>
>I'll take a look at your new tickets once I have more time
>
>
>>
>> Bernard
>>
>>
>>
>> On Fri, 8 Feb 2013 09:09:34 +0100, you wrote:
>>
>> >Hi,
>> >
>> >It is OK.
>> >But you can also just update some field/model in the current page
>> instance.
>> >
>> >
>> >On Fri, Feb 8, 2013 at 7:00 AM, snair <sreelatha.nair@transport.wa.gov.au
>> >wrote:
>> >
>> >> Is it ok to call the same page using setResponsePage(), only calling a
>> >> different constructor, since the page now needs to display additional
>> >> information, which I will be passing into this new constructor?  For
>> >> example, from PageA, can I say setResponsePage(new PageA(String a))
>> when a
>> >> submit button button is clicked.
>> >>
>> >>
>> >>
>> >> --
>> >> View this message in context:
>> >>
>> http://apache-wicket.1842946.n4.nabble.com/call-the-same-page-using-setResponsePage-tp4656192.html
>> >> Sent from the Users forum mailing list archive at Nabble.com.
>> >>
>> >> ---------------------------------------------------------------------
>> >> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> >> For additional commands, e-mail: users-help@wicket.apache.org
>> >>
>> >>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> For additional commands, e-mail: users-help@wicket.apache.org
>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: call the same page using setResponsePage()

Posted by Martin Grigorov <mg...@apache.org>.
Hi,


On Fri, Feb 8, 2013 at 11:44 AM, Bernard <bh...@gmail.com> wrote:

> Hi,
>
> This is what I like about Wiket.
>
> Even if I start with a stateless page! So I update a component, and
> Wicket takes care of it via server side state - job done.
>
> The page is then no longer stateless which is fair.
>
> But:
>
> When the user stays on this page and the session expires, then even
> simple Links on the page like a sign-out link that do NOT require
> state cause PageExpiredException. In this case the beautiful
> advantages of using Wicket are gone. Working around these issues can
> be very expensive because one has to examine every single page in the
> special session expiry scenario. The workaround code becomes very
> ugly.
>
> Are there any plans to fix this or is this a feature?
>

This is by design.
If Wicket cannot find the old page by any reason (e.g. expired session with
all its pages) then depending on the value of
IPageSettings#getRecreateMountedPagesAfterExpiry() Wicket may create a new
instance for you.
Now:
1) if the new instance is stateless then Wicket will execute the listener
interface, i.e. will execute StatelessLink#onClick, StatelessForm#onSubmit,
...
2) if the newly created page is stateful Wicket will just render it
*without* executing the listener interface
Why ? Because the stateless link/form/behavior/... may or may not be in the
page component tree. Wicket cannot make assumptions that the
component/behavior exists in the page initial state (i.e. right after
instantiating it). The link that your user has clicked on the expired page
may have been added in state 2 of the page, and thus it is not available in
state 1 (the initial state).

Use case:
- render a simple stateful page with just linkA and am empty panel
- the user clicks on linkA which replaces the empty panel with a panel with
linkB inside
- later the user clicks on linkB
- if the session is expired and Wicket creates a new instance of the page
then linkB is not in the component tree. Only linkA and the empty panel are
there. Once linkA is used linkB will appear, but Wicket cannot do this
because it doesn't know what to do to get linkB and execute its onClick()
method

I'll add this explanation to a FAQ section at
http://martin-g.github.com/wicket-reference-guide/stateless.html .

If we change this behavior and try to execute the listener interface then
it will work when linkB is in the initial state and will throw
ComponentNotFoundException when linkB is added to the tree after some
interaction. So it will become nondeterministic - a russian roulette.

I'll take a look at your new tickets once I have more time


>
> Bernard
>
>
>
> On Fri, 8 Feb 2013 09:09:34 +0100, you wrote:
>
> >Hi,
> >
> >It is OK.
> >But you can also just update some field/model in the current page
> instance.
> >
> >
> >On Fri, Feb 8, 2013 at 7:00 AM, snair <sreelatha.nair@transport.wa.gov.au
> >wrote:
> >
> >> Is it ok to call the same page using setResponsePage(), only calling a
> >> different constructor, since the page now needs to display additional
> >> information, which I will be passing into this new constructor?  For
> >> example, from PageA, can I say setResponsePage(new PageA(String a))
> when a
> >> submit button button is clicked.
> >>
> >>
> >>
> >> --
> >> View this message in context:
> >>
> http://apache-wicket.1842946.n4.nabble.com/call-the-same-page-using-setResponsePage-tp4656192.html
> >> Sent from the Users forum mailing list archive at Nabble.com.
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> >> For additional commands, e-mail: users-help@wicket.apache.org
> >>
> >>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>


-- 
Martin Grigorov
jWeekend
Training, Consulting, Development
http://jWeekend.com <http://jweekend.com/>

Re: call the same page using setResponsePage()

Posted by Bernard <bh...@gmail.com>.
Hi,

This is what I like about Wiket.

Even if I start with a stateless page! So I update a component, and
Wicket takes care of it via server side state - job done.

The page is then no longer stateless which is fair.

But:

When the user stays on this page and the session expires, then even
simple Links on the page like a sign-out link that do NOT require
state cause PageExpiredException. In this case the beautiful
advantages of using Wicket are gone. Working around these issues can
be very expensive because one has to examine every single page in the
special session expiry scenario. The workaround code becomes very
ugly.

Are there any plans to fix this or is this a feature?

Bernard



On Fri, 8 Feb 2013 09:09:34 +0100, you wrote:

>Hi,
>
>It is OK.
>But you can also just update some field/model in the current page instance.
>
>
>On Fri, Feb 8, 2013 at 7:00 AM, snair <sr...@transport.wa.gov.au>wrote:
>
>> Is it ok to call the same page using setResponsePage(), only calling a
>> different constructor, since the page now needs to display additional
>> information, which I will be passing into this new constructor?  For
>> example, from PageA, can I say setResponsePage(new PageA(String a)) when a
>> submit button button is clicked.
>>
>>
>>
>> --
>> View this message in context:
>> http://apache-wicket.1842946.n4.nabble.com/call-the-same-page-using-setResponsePage-tp4656192.html
>> Sent from the Users forum mailing list archive at Nabble.com.
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> For additional commands, e-mail: users-help@wicket.apache.org
>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: call the same page using setResponsePage()

Posted by Martin Grigorov <mg...@apache.org>.
Hi,

It is OK.
But you can also just update some field/model in the current page instance.


On Fri, Feb 8, 2013 at 7:00 AM, snair <sr...@transport.wa.gov.au>wrote:

> Is it ok to call the same page using setResponsePage(), only calling a
> different constructor, since the page now needs to display additional
> information, which I will be passing into this new constructor?  For
> example, from PageA, can I say setResponsePage(new PageA(String a)) when a
> submit button button is clicked.
>
>
>
> --
> View this message in context:
> http://apache-wicket.1842946.n4.nabble.com/call-the-same-page-using-setResponsePage-tp4656192.html
> Sent from the Users forum mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>


-- 
Martin Grigorov
jWeekend
Training, Consulting, Development
http://jWeekend.com <http://jweekend.com/>

Re: call the same page using setResponsePage()

Posted by Paul Bors <pa...@bors.ws>.
Yes, as per the API for the component class:

http://ci.apache.org/projects/wicket/apidocs/6.0.x/org/apache/wicket/Component.html#setResponsePage(java.lang.Class)
setResponsePage

public final <C extends IRequestablePage> void setResponsePage(Class<C> cls)
Sets the page that will respond to this request
Type Parameters:
C -
Parameters:
cls - The response page class
See Also:
RequestCycle.setResponsePage(Class)
setResponsePage

public final <C extends IRequestablePage> void setResponsePage(Class<C> cls,                                                                PageParameters parameters)
Sets the page class and its parameters that will respond to this request
Type Parameters:
C -
Parameters:
cls - The response page class
parameters - The parameters for this bookmarkable page.
See Also:
RequestCycle.setResponsePage(Class, PageParameters)
setResponsePage

public final void setResponsePage(Page page)
Sets the page that will respond to this request
Parameters:
page - The response page
See Also:
RequestCycle.setResponsePage(org.apache.wicket.request.component.IRequestablePage)
To run this through a simple unit test you would run:

WicketTester#AssertRenderedPage()
http://ci.apache.org/projects/wicket/apidocs/6.0.x/org/apache/wicket/util/tester/WicketTester.html#assertRenderedPage(java.lang.Class)

WicketTester#AssertResultPage()
http://ci.apache.org/projects/wicket/apidocs/6.0.x/org/apache/wicket/util/tester/WicketTester.html#assertResultPage(java.lang.Class,%20java.lang.String)

~ Thank you,
   Paul C Bors

On Feb 8, 2013, at 1:00, snair <sr...@transport.wa.gov.au> wrote:

> Is it ok to call the same page using setResponsePage(), only calling a
> different constructor, since the page now needs to display additional
> information, which I will be passing into this new constructor?  For
> example, from PageA, can I say setResponsePage(new PageA(String a)) when a
> submit button button is clicked.
> 
> 
> 
> --
> View this message in context: http://apache-wicket.1842946.n4.nabble.com/call-the-same-page-using-setResponsePage-tp4656192.html
> Sent from the Users forum mailing list archive at Nabble.com.
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>