You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by Bertrand Guay-Paquet <be...@step.polymtl.ca> on 2012/08/10 15:31:52 UTC

Calling isPageStateless() can mess up the statelessness of a page

Hi,

(Using Wicket 6.0-SNAPSHOT, or 1.5.7)

I found a strange behavior when calling Page#isPageStateless(). I have a 
simple label in my personal wicket debug bar which displays "stateless" 
when a page is stateless. It works like so:

new WebMarkupContainer("statelessMarker") {
     @Override
     protected void onConfigure() {
         super.onConfigure();
         setVisible(getPage().isPageStateless());
     }
};

This worked great until I got by chance a page which was stateless 
except for ajax links which were children of a repeater. Here is what 
happens then:
1) onConfigure() is called which calls isPageStateless() and determines 
the page is stateless
2) onBeforeRender() is executed which populates the repeaters and adds 
stateful components to the tree
3) Since the page was determined stateless in 1), it stays that way
4) stateful ajax callback links do not work on the page

Therefore, it seems that isPageStateless() should never be called before 
onBeforeRender() is executed or mayhem may ensue. However, after cursory 
inspection of callers of isPageStateless(), it looks like that is not 
always the case so I'm not certain.

Should this be considered a bug? Should an assertion be made in 
isPageStateless() that onBeforeRender() was executed?

Regards,
Bertrand

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


Re: Calling isPageStateless() can mess up the statelessness of a page

Posted by vineet semwal <vi...@gmail.com>.
it actually is "isPageStatelessAtTimeIAmChecking"
i have one idea ..if isPageStateless() is only made to cache that
variable after page#onbeforerender then it will be ok.
if some call is made before that then don't allow caching of that
variable ,it's very easy to make this improvement...
what should be returned if call is made before page#onbeforerender
depends how much you want to deviate from current behvior,you can
return the isPagestateless() without caching with a warning *too early
to check if page is stateless*
or change the return type to Boolean and return null or throw runtimexception.

On Sat, Aug 11, 2012 at 10:33 AM, Bertrand Guay-Paquet
<be...@step.polymtl.ca> wrote:
> This is weird, I never received Martin's email! I managed to see it in your
> first reply Vineet... I also lost a few hours' worth of mailing list emails.
>
> Removing the caching in isPageStateless() would indeed make sure that the
> code in WebPageRenderer would not get the wrong value. However, all the
> calls made to isPageStateless() before that point could still get the wrong
> value returned, depending on the page. In that case, it seems kind of
> pointless to rely on isPageStateless() for anything at all before rendering
> (or at least onBeforeRender) occurs.
>
> I had a deeper look at callers of isPageStateless() in Wicket's source and
> found two possible causes of concern: WebPageRenderer#respond(RequestCycle)
> and ListenerInterfaceRequestHandler#respond(RequestCycle). I'll need to
> examine in them in more details.
>
> To be continued...
>
>
> On 10/08/2012 6:33 PM, vineet semwal wrote:
>>
>> you are right onconfigure is executed once before rendering .
>>
>> actually isPageStateless() can be broken easily as that variable can
>> be populated before the page#onbeforerender is completed ie. say if
>> some component in onbeforerender  uses  ispagestateless() then the
>> variable will be set prematurely
>>
>> now i see martin-g is correct the solution is to just remove the
>> caching but the problem can be that method is used in a lot of places
>> and can be called many times  foreg. it's used inside urlFor in
>> Component which means link will at least call this method once in
>> getUrl and if you have a repeater of 20 links this is 20 X
>> isPageStateless()  ,it actually depends on how expensive
>> ispagestateless() itself is and at how many places is it used ..
>>
>>
>> On Fri, Aug 10, 2012 at 10:53 PM, Bertrand Guay-Paquet
>> <be...@step.polymtl.ca> wrote:
>>>
>>> On 10/08/2012 12:12 PM, vineet semwal wrote:
>>>>
>>>> it might give you wrong result even if you add your component after
>>>> adding all the components because  some components foreg. a repeater
>>>> like listview/dataview/gridview  add children in onbeforerender so
>>>> isPageStateless() can be assumed to work correctly only after
>>>> onbeforerender
>>>
>>> Yes that's exactly what I wanted to say! The repeaters are only populated
>>> in
>>> their onBeforeRender() which is executed after onConfigure().
>>>
>>>
>>>> that caching part is ok imho   for isPageStateless() ,actually that
>>>> cached variable is reset in page#onbeforerender which is the another
>>>> reason isPageStateless()  should work correctly after onbeforerender
>>>
>>> I hadn't noticed that reset in Page#onBeforeRender() so I had a look
>>> since
>>> it would contradict my observations.
>>>
>>> This is the stack trace when my label's onConfigure() is reached :
>>> TmpPage$1.onConfigure() line: 24    <-- my stateless indicator label;
>>> calls
>>> isPageStateless()
>>> TmpPage$1(Component).configure() line: 1028
>>> TmpPage$1(Component).internalBeforeRender() line: 913
>>> TmpPage$1(Component).beforeRender() line: 990
>>> TmpPage(MarkupContainer).onBeforeRenderChildren() line: 1688
>>> TmpPage(Component).onBeforeRender() line: 3830
>>> TmpPage(Page).onBeforeRender() line: 802    <--- line 799 already did the
>>> reset of the cached "stateless" var
>>> TmpPage(Component).internalBeforeRender() line: 922
>>> TmpPage(Component).beforeRender() line: 990
>>> TmpPage(Component).internalPrepareForRender(boolean) line: 2204
>>> TmpPage(Page).internalPrepareForRender(boolean) line: 247
>>> TmpPage(Component).render() line: 2289
>>> TmpPage(Page).renderPage() line: 1021
>>>
>>> This stack trace occurs before the repeating view is populated which
>>> would
>>> render the page stateful and causes the Page to cache that it is
>>> stateless.
>>>
>>> By the way, I did find a workaround to achieve the desired effect so
>>> that's
>>> not why I brought this up here. I'm just concerned that such erroneous
>>> computations of the page's stateless state might cause other bugs down
>>> the
>>> road.
>>>
>>>
>>> ---------------------------------------------------------------------
>>> 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
>



-- 
regards,

Vineet Semwal

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


Re: Calling isPageStateless() can mess up the statelessness of a page

Posted by Bertrand Guay-Paquet <be...@step.polymtl.ca>.
This is weird, I never received Martin's email! I managed to see it in 
your first reply Vineet... I also lost a few hours' worth of mailing 
list emails.

Removing the caching in isPageStateless() would indeed make sure that 
the code in WebPageRenderer would not get the wrong value. However, all 
the calls made to isPageStateless() before that point could still get 
the wrong value returned, depending on the page. In that case, it seems 
kind of pointless to rely on isPageStateless() for anything at all 
before rendering (or at least onBeforeRender) occurs.

I had a deeper look at callers of isPageStateless() in Wicket's source 
and found two possible causes of concern: 
WebPageRenderer#respond(RequestCycle) and 
ListenerInterfaceRequestHandler#respond(RequestCycle). I'll need to 
examine in them in more details.

To be continued...

On 10/08/2012 6:33 PM, vineet semwal wrote:
> you are right onconfigure is executed once before rendering .
>
> actually isPageStateless() can be broken easily as that variable can
> be populated before the page#onbeforerender is completed ie. say if
> some component in onbeforerender  uses  ispagestateless() then the
> variable will be set prematurely
>
> now i see martin-g is correct the solution is to just remove the
> caching but the problem can be that method is used in a lot of places
> and can be called many times  foreg. it's used inside urlFor in
> Component which means link will at least call this method once in
> getUrl and if you have a repeater of 20 links this is 20 X
> isPageStateless()  ,it actually depends on how expensive
> ispagestateless() itself is and at how many places is it used ..
>
>
> On Fri, Aug 10, 2012 at 10:53 PM, Bertrand Guay-Paquet
> <be...@step.polymtl.ca> wrote:
>> On 10/08/2012 12:12 PM, vineet semwal wrote:
>>> it might give you wrong result even if you add your component after
>>> adding all the components because  some components foreg. a repeater
>>> like listview/dataview/gridview  add children in onbeforerender so
>>> isPageStateless() can be assumed to work correctly only after
>>> onbeforerender
>> Yes that's exactly what I wanted to say! The repeaters are only populated in
>> their onBeforeRender() which is executed after onConfigure().
>>
>>
>>> that caching part is ok imho   for isPageStateless() ,actually that
>>> cached variable is reset in page#onbeforerender which is the another
>>> reason isPageStateless()  should work correctly after onbeforerender
>> I hadn't noticed that reset in Page#onBeforeRender() so I had a look since
>> it would contradict my observations.
>>
>> This is the stack trace when my label's onConfigure() is reached :
>> TmpPage$1.onConfigure() line: 24    <-- my stateless indicator label; calls
>> isPageStateless()
>> TmpPage$1(Component).configure() line: 1028
>> TmpPage$1(Component).internalBeforeRender() line: 913
>> TmpPage$1(Component).beforeRender() line: 990
>> TmpPage(MarkupContainer).onBeforeRenderChildren() line: 1688
>> TmpPage(Component).onBeforeRender() line: 3830
>> TmpPage(Page).onBeforeRender() line: 802    <--- line 799 already did the
>> reset of the cached "stateless" var
>> TmpPage(Component).internalBeforeRender() line: 922
>> TmpPage(Component).beforeRender() line: 990
>> TmpPage(Component).internalPrepareForRender(boolean) line: 2204
>> TmpPage(Page).internalPrepareForRender(boolean) line: 247
>> TmpPage(Component).render() line: 2289
>> TmpPage(Page).renderPage() line: 1021
>>
>> This stack trace occurs before the repeating view is populated which would
>> render the page stateful and causes the Page to cache that it is stateless.
>>
>> By the way, I did find a workaround to achieve the desired effect so that's
>> not why I brought this up here. I'm just concerned that such erroneous
>> computations of the page's stateless state might cause other bugs down the
>> road.
>>
>>
>> ---------------------------------------------------------------------
>> 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: Calling isPageStateless() can mess up the statelessness of a page

Posted by vineet semwal <vi...@gmail.com>.
you are right onconfigure is executed once before rendering .

actually isPageStateless() can be broken easily as that variable can
be populated before the page#onbeforerender is completed ie. say if
some component in onbeforerender  uses  ispagestateless() then the
variable will be set prematurely

now i see martin-g is correct the solution is to just remove the
caching but the problem can be that method is used in a lot of places
and can be called many times  foreg. it's used inside urlFor in
Component which means link will at least call this method once in
getUrl and if you have a repeater of 20 links this is 20 X
isPageStateless()  ,it actually depends on how expensive
ispagestateless() itself is and at how many places is it used ..


On Fri, Aug 10, 2012 at 10:53 PM, Bertrand Guay-Paquet
<be...@step.polymtl.ca> wrote:
>
> On 10/08/2012 12:12 PM, vineet semwal wrote:
>>
>> it might give you wrong result even if you add your component after
>> adding all the components because  some components foreg. a repeater
>> like listview/dataview/gridview  add children in onbeforerender so
>> isPageStateless() can be assumed to work correctly only after
>> onbeforerender
>
> Yes that's exactly what I wanted to say! The repeaters are only populated in
> their onBeforeRender() which is executed after onConfigure().
>
>
>> that caching part is ok imho   for isPageStateless() ,actually that
>> cached variable is reset in page#onbeforerender which is the another
>> reason isPageStateless()  should work correctly after onbeforerender
>
> I hadn't noticed that reset in Page#onBeforeRender() so I had a look since
> it would contradict my observations.
>
> This is the stack trace when my label's onConfigure() is reached :
> TmpPage$1.onConfigure() line: 24    <-- my stateless indicator label; calls
> isPageStateless()
> TmpPage$1(Component).configure() line: 1028
> TmpPage$1(Component).internalBeforeRender() line: 913
> TmpPage$1(Component).beforeRender() line: 990
> TmpPage(MarkupContainer).onBeforeRenderChildren() line: 1688
> TmpPage(Component).onBeforeRender() line: 3830
> TmpPage(Page).onBeforeRender() line: 802    <--- line 799 already did the
> reset of the cached "stateless" var
> TmpPage(Component).internalBeforeRender() line: 922
> TmpPage(Component).beforeRender() line: 990
> TmpPage(Component).internalPrepareForRender(boolean) line: 2204
> TmpPage(Page).internalPrepareForRender(boolean) line: 247
> TmpPage(Component).render() line: 2289
> TmpPage(Page).renderPage() line: 1021
>
> This stack trace occurs before the repeating view is populated which would
> render the page stateful and causes the Page to cache that it is stateless.
>
> By the way, I did find a workaround to achieve the desired effect so that's
> not why I brought this up here. I'm just concerned that such erroneous
> computations of the page's stateless state might cause other bugs down the
> road.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>



-- 
regards,

Vineet Semwal

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


Re: Calling isPageStateless() can mess up the statelessness of a page

Posted by Bertrand Guay-Paquet <be...@step.polymtl.ca>.
On 10/08/2012 12:12 PM, vineet semwal wrote:
> it might give you wrong result even if you add your component after
> adding all the components because  some components foreg. a repeater
> like listview/dataview/gridview  add children in onbeforerender so
> isPageStateless() can be assumed to work correctly only after
> onbeforerender
Yes that's exactly what I wanted to say! The repeaters are only 
populated in their onBeforeRender() which is executed after onConfigure().

> that caching part is ok imho   for isPageStateless() ,actually that
> cached variable is reset in page#onbeforerender which is the another
> reason isPageStateless()  should work correctly after onbeforerender
I hadn't noticed that reset in Page#onBeforeRender() so I had a look 
since it would contradict my observations.

This is the stack trace when my label's onConfigure() is reached :
TmpPage$1.onConfigure() line: 24    <-- my stateless indicator label; 
calls isPageStateless()
TmpPage$1(Component).configure() line: 1028
TmpPage$1(Component).internalBeforeRender() line: 913
TmpPage$1(Component).beforeRender() line: 990
TmpPage(MarkupContainer).onBeforeRenderChildren() line: 1688
TmpPage(Component).onBeforeRender() line: 3830
TmpPage(Page).onBeforeRender() line: 802    <--- line 799 already did 
the reset of the cached "stateless" var
TmpPage(Component).internalBeforeRender() line: 922
TmpPage(Component).beforeRender() line: 990
TmpPage(Component).internalPrepareForRender(boolean) line: 2204
TmpPage(Page).internalPrepareForRender(boolean) line: 247
TmpPage(Component).render() line: 2289
TmpPage(Page).renderPage() line: 1021

This stack trace occurs before the repeating view is populated which 
would render the page stateful and causes the Page to cache that it is 
stateless.

By the way, I did find a workaround to achieve the desired effect so 
that's not why I brought this up here. I'm just concerned that such 
erroneous computations of the page's stateless state might cause other 
bugs down the road.

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


Re: Calling isPageStateless() can mess up the statelessness of a page

Posted by vineet semwal <vi...@gmail.com>.
it might give you wrong result even if you add your component after
adding all the components because  some components foreg. a repeater
like listview/dataview/gridview  add children in onbeforerender so
isPageStateless() can be assumed to work correctly only after
onbeforerender

that caching part is ok imho   for isPageStateless() ,actually that
cached variable is reset in page#onbeforerender which is the another
reason isPageStateless()  should work correctly after onbeforerender


On Fri, Aug 10, 2012 at 7:43 PM, Martin Grigorov <mg...@apache.org> wrote:
> Hi,
>
> The page can become stateful during rendering, as you have noticed.
> There is a code in WebPageRenderer that re-renders the page if it
> change state during the first rendering because otherwise some
> previously rendered links may became broken.
>
> The real problem here is that #isPageStateless() does caching (by
> using Page#stateless variable) and once set it doesn't bother asking
> the components second time.
>
> I see no reason to add restrictions related to the page's lifecycle.
> This wont help.
> The only solution that I see is to remove the caching and make this
> call more expensive. But even in this case your logic wont work.
> It will work only if your label is at the very bottom of the page.
>
> On Fri, Aug 10, 2012 at 4:31 PM, Bertrand Guay-Paquet
> <be...@step.polymtl.ca> wrote:
>> Hi,
>>
>> (Using Wicket 6.0-SNAPSHOT, or 1.5.7)
>>
>> I found a strange behavior when calling Page#isPageStateless(). I have a
>> simple label in my personal wicket debug bar which displays "stateless" when
>> a page is stateless. It works like so:
>>
>> new WebMarkupContainer("statelessMarker") {
>>     @Override
>>     protected void onConfigure() {
>>         super.onConfigure();
>>         setVisible(getPage().isPageStateless());
>>     }
>> };
>>
>> This worked great until I got by chance a page which was stateless except
>> for ajax links which were children of a repeater. Here is what happens then:
>> 1) onConfigure() is called which calls isPageStateless() and determines the
>> page is stateless
>> 2) onBeforeRender() is executed which populates the repeaters and adds
>> stateful components to the tree
>> 3) Since the page was determined stateless in 1), it stays that way
>> 4) stateful ajax callback links do not work on the page
>>
>> Therefore, it seems that isPageStateless() should never be called before
>> onBeforeRender() is executed or mayhem may ensue. However, after cursory
>> inspection of callers of isPageStateless(), it looks like that is not always
>> the case so I'm not certain.
>>
>> Should this be considered a bug? Should an assertion be made in
>> isPageStateless() that onBeforeRender() was executed?
>>
>> Regards,
>> Bertrand
>>
>> ---------------------------------------------------------------------
>> 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
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>



-- 
regards,

Vineet Semwal

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


Re: Calling isPageStateless() can mess up the statelessness of a page

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

The page can become stateful during rendering, as you have noticed.
There is a code in WebPageRenderer that re-renders the page if it
change state during the first rendering because otherwise some
previously rendered links may became broken.

The real problem here is that #isPageStateless() does caching (by
using Page#stateless variable) and once set it doesn't bother asking
the components second time.

I see no reason to add restrictions related to the page's lifecycle.
This wont help.
The only solution that I see is to remove the caching and make this
call more expensive. But even in this case your logic wont work.
It will work only if your label is at the very bottom of the page.

On Fri, Aug 10, 2012 at 4:31 PM, Bertrand Guay-Paquet
<be...@step.polymtl.ca> wrote:
> Hi,
>
> (Using Wicket 6.0-SNAPSHOT, or 1.5.7)
>
> I found a strange behavior when calling Page#isPageStateless(). I have a
> simple label in my personal wicket debug bar which displays "stateless" when
> a page is stateless. It works like so:
>
> new WebMarkupContainer("statelessMarker") {
>     @Override
>     protected void onConfigure() {
>         super.onConfigure();
>         setVisible(getPage().isPageStateless());
>     }
> };
>
> This worked great until I got by chance a page which was stateless except
> for ajax links which were children of a repeater. Here is what happens then:
> 1) onConfigure() is called which calls isPageStateless() and determines the
> page is stateless
> 2) onBeforeRender() is executed which populates the repeaters and adds
> stateful components to the tree
> 3) Since the page was determined stateless in 1), it stays that way
> 4) stateful ajax callback links do not work on the page
>
> Therefore, it seems that isPageStateless() should never be called before
> onBeforeRender() is executed or mayhem may ensue. However, after cursory
> inspection of callers of isPageStateless(), it looks like that is not always
> the case so I'm not certain.
>
> Should this be considered a bug? Should an assertion be made in
> isPageStateless() that onBeforeRender() was executed?
>
> Regards,
> Bertrand
>
> ---------------------------------------------------------------------
> 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

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


Re: Calling isPageStateless() can mess up the statelessness of a page

Posted by vineet semwal <vi...@gmail.com>.
currently i think you can do by keeping some boolean variable that you
can populate after page#onbeforerender
and override your desired component's isVisible() {return my_boolean ;}

On Fri, Aug 10, 2012 at 7:01 PM, Bertrand Guay-Paquet
<be...@step.polymtl.ca> wrote:
> Hi,
>
> (Using Wicket 6.0-SNAPSHOT, or 1.5.7)
>
> I found a strange behavior when calling Page#isPageStateless(). I have a
> simple label in my personal wicket debug bar which displays "stateless" when
> a page is stateless. It works like so:
>
> new WebMarkupContainer("statelessMarker") {
>     @Override
>     protected void onConfigure() {
>         super.onConfigure();
>         setVisible(getPage().isPageStateless());
>     }
> };
>
> This worked great until I got by chance a page which was stateless except
> for ajax links which were children of a repeater. Here is what happens then:
> 1) onConfigure() is called which calls isPageStateless() and determines the
> page is stateless
> 2) onBeforeRender() is executed which populates the repeaters and adds
> stateful components to the tree
> 3) Since the page was determined stateless in 1), it stays that way
> 4) stateful ajax callback links do not work on the page
>
> Therefore, it seems that isPageStateless() should never be called before
> onBeforeRender() is executed or mayhem may ensue. However, after cursory
> inspection of callers of isPageStateless(), it looks like that is not always
> the case so I'm not certain.
>
> Should this be considered a bug? Should an assertion be made in
> isPageStateless() that onBeforeRender() was executed?
>
> Regards,
> Bertrand
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>



-- 
regards,

Vineet Semwal

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