You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Ruud Diterwich <rd...@cedron.com> on 2003/06/24 09:45:30 UTC

Redirects and multiple database fetches

The redirects work great, but now I have the problem that the database
is fetched twice. The database is read in prepareForRender(), and the
result is cached in the component as a non-persistent property (The
result is not serializable and too big anyway). However, after the
redirect I don't want to fetch the result again. Is there a way to
access the data that was generated just before the redirect?

Ruud Diterwich

-----Original Message-----
From: Denis Ponomarev [mailto:oz@romsat.ua] 
Sent: Monday, June 23, 2003 13:42
To: Tapestry users
Subject: Re: actions and refresh

RD> When you use an action link, a url is created that will execute the
RD> action, like
RD> http://localhost:8081/dmc2?service=action/1/MyEdit/0/$ActionLink.
RD> However, when the user refreshes the page, the action is executed
again!
RD> Can this be circumvented?

I have static method in my Engine class:

        public static void cleanRequest(IRequestCycle cycle){
                IEngineService pageService =
cycle.getEngine().getService(Tapestry.PAGE_SERVICE);
                String pageName = cycle.getPage().getExtendedId();
                String redirector = pageService.getLink(cycle, null, new
String[]{pageName}).getURL();
                throw new RedirectException(redirector);
        }

I call it from action listeners if I want to avoid reexecuting.


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


RE: Re[2]: Service parameters

Posted by Ruud Diterwich <rd...@cedron.com>.
Thanks a lot! Very useful.


Ruud

> -----Original Message-----
> From: Denis Ponomarev [mailto:oz@romsat.ua]
> Sent: Tuesday, June 24, 2003 14:14
> To: Tapestry users
> Subject: Re[2]: Service parameters
> 
> RD> My initial attempt was using persistent properties. However, I was
> RD> unable to set a persistent property while rendering. And the value
of
> RD> the persistent property depends on the result of the query that is
> RD> executed in the prepareForRender... (The property must be changed
> (only)
> RD> if the number of result elements is less than a certain value, so
it
> RD> should be persistent).
> 
> You can implement PageRenderListener interface in your component.
> It contains of two method, one can be usefull:
> 
> public void pageBeginRender(PageEvent event) {
>        // here is your final chance to change persistent properties
>        // probably this is the place where you should execute query
>        // and correct persistent property depending on query result
> }
> 
> >> Look:
> >>
> >> <component name="prevLink" type="DirectLink">
> >>     <binding name="listener" expression="listeners.changePage"/>
> >>     <binding name="parameters" expression="prevPage"/>
> >>     <binding name="disabled" expression="first"/>
> >> </component>
> >>
> >> <component name="nextLink" type="DirectLink">
> >>     <binding name="listener" expression="listeners.changePage"/>
> >>     <binding name="parameters" expression="nextPage"/>
> >>     <binding name="disabled" expression="last"/>
> >> </component>
> >>
> >> It assumes that your table component has isFirst(), isLast(),
> >> getNext() and getPrevious() methods based on the currentPage
> >> persistent property.
> >>
> >> And action listener method
> >>
> >> public void changePage(IRequestCycle cycle){
> >>        Integer pageNumber = (Integer)
cycle.getServiceParameters()[0];
> >>        setCurrentPage(pageNumber.intValue());
> >> }
> >>
> >> RD> the extra burden on the template author, who has to specify the
> >> RD> parameter on each DirectLink tag.
> >>
> >> Template author just locates components:
> >>
> >> <a jwcid="prevLink">previous</a> <a jwcid="nextLink">next</a>
> >>
> >> There is no parameters specification!
> >>
> 
> RD> I tend to specify the links directly in the html templates using
> RD> jwcid="@DirectLink". I agree that using the jwc file to specify
> RD> parameters is more puristic.
> 
> RD> However, I have a dynamic set of links, one for each page (like
> google)
> RD> of a data set. I have no choice then but to put them directly in
the
> RD> html template:
> 
> RD> <span jwcid="@Foreach" value="ognl:navigationPage"
> RD> source="ognl:navigationPages">
> 
> RD>         <a jwcid="@DirectLink"
listener="ognl:listeners.changePage"
> RD> parameters="ognl:navigationPage">
> RD>                 <span jwcid="@Insert" value="ognl:navigationPage +
> 1"/>
> RD>         </a>
> RD> </span>
> 
> 
> I think it can be implemented:
> ====================
> 
> <component id="everyPage" value="ognl:navigationPage">
>     <binding name="source" expression="navigationPages"/>
>     <binding name="value" expression="navigationPage"/>
> </component>
> 
> <component name="pageLink" type="DirectLink">
>     <binding name="listener" expression="listeners.changePage"/>
>     <binding name="parameters" expression="navigationPage"/>
>     <binding name="disabled" expression="current"/>
> </component>
> 
> <component name="pageIndex" type="Insert">
>     <binding name="value" expression="navigationPage"/>
> </component>
> 
> ====================
> 
> <span jwcid="everyPage">
>       <a jwcid="pageLink"><span jwcid="pageIndex"/></a>
> </span>
> 
> ====================
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re[2]: Service parameters

Posted by Denis Ponomarev <oz...@romsat.ua>.
RD> My initial attempt was using persistent properties. However, I was
RD> unable to set a persistent property while rendering. And the value of
RD> the persistent property depends on the result of the query that is
RD> executed in the prepareForRender... (The property must be changed (only)
RD> if the number of result elements is less than a certain value, so it
RD> should be persistent).

You can implement PageRenderListener interface in your component.
It contains of two method, one can be usefull:

public void pageBeginRender(PageEvent event) {
       // here is your final chance to change persistent properties
       // probably this is the place where you should execute query
       // and correct persistent property depending on query result
}

>> Look:
>> 
>> <component name="prevLink" type="DirectLink">
>>     <binding name="listener" expression="listeners.changePage"/>
>>     <binding name="parameters" expression="prevPage"/>
>>     <binding name="disabled" expression="first"/>
>> </component>
>> 
>> <component name="nextLink" type="DirectLink">
>>     <binding name="listener" expression="listeners.changePage"/>
>>     <binding name="parameters" expression="nextPage"/>
>>     <binding name="disabled" expression="last"/>
>> </component>
>> 
>> It assumes that your table component has isFirst(), isLast(),
>> getNext() and getPrevious() methods based on the currentPage
>> persistent property.
>> 
>> And action listener method
>> 
>> public void changePage(IRequestCycle cycle){
>>        Integer pageNumber = (Integer) cycle.getServiceParameters()[0];
>>        setCurrentPage(pageNumber.intValue());
>> }
>> 
>> RD> the extra burden on the template author, who has to specify the
>> RD> parameter on each DirectLink tag.
>> 
>> Template author just locates components:
>> 
>> <a jwcid="prevLink">previous</a> <a jwcid="nextLink">next</a>
>> 
>> There is no parameters specification!
>> 

RD> I tend to specify the links directly in the html templates using
RD> jwcid="@DirectLink". I agree that using the jwc file to specify
RD> parameters is more puristic. 

RD> However, I have a dynamic set of links, one for each page (like google)
RD> of a data set. I have no choice then but to put them directly in the
RD> html template:

RD> <span jwcid="@Foreach" value="ognl:navigationPage"
RD> source="ognl:navigationPages">

RD>         <a jwcid="@DirectLink" listener="ognl:listeners.changePage"
RD> parameters="ognl:navigationPage">
RD>                 <span jwcid="@Insert" value="ognl:navigationPage + 1"/>
RD>         </a>
RD> </span>


I think it can be implemented:
====================

<component id="everyPage" value="ognl:navigationPage">
    <binding name="source" expression="navigationPages"/>
    <binding name="value" expression="navigationPage"/>
</component>

<component name="pageLink" type="DirectLink">
    <binding name="listener" expression="listeners.changePage"/>
    <binding name="parameters" expression="navigationPage"/>
    <binding name="disabled" expression="current"/>
</component>

<component name="pageIndex" type="Insert">
    <binding name="value" expression="navigationPage"/>
</component>

====================

<span jwcid="everyPage">
      <a jwcid="pageLink"><span jwcid="pageIndex"/></a>
</span>

====================


RE: Service parameters

Posted by Ruud Diterwich <rd...@cedron.com>.
> 
> I don't know what kind of table components you use, but I think it
> should has _persistent_ property 'currentPage'. So when you navigate
> over one table, second keeps it's state. Did you hear something about
> persistent properties? :)

My initial attempt was using persistent properties. However, I was
unable to set a persistent property while rendering. And the value of
the persistent property depends on the result of the query that is
executed in the prepareForRender... (The property must be changed (only)
if the number of result elements is less than a certain value, so it
should be persistent).

> 
> RD> So the service parameters introduce a kind of 'global' variable
space,
> RD> which is not in line with 'component-based' development. Not to
> mention
> 
> You wrong. Service parameters intended to deliver specific inforamtion
> directly to the component. There is no global space.

You're right, if you make the current page property persistent, you have
the correct behavior.

> Look:
> 
> <component name="prevLink" type="DirectLink">
>     <binding name="listener" expression="listeners.changePage"/>
>     <binding name="parameters" expression="prevPage"/>
>     <binding name="disabled" expression="first"/>
> </component>
> 
> <component name="nextLink" type="DirectLink">
>     <binding name="listener" expression="listeners.changePage"/>
>     <binding name="parameters" expression="nextPage"/>
>     <binding name="disabled" expression="last"/>
> </component>
> 
> It assumes that your table component has isFirst(), isLast(),
> getNext() and getPrevious() methods based on the currentPage
> persistent property.
> 
> And action listener method
> 
> public void changePage(IRequestCycle cycle){
>        Integer pageNumber = (Integer) cycle.getServiceParameters()[0];
>        setCurrentPage(pageNumber.intValue());
> }
> 
> RD> the extra burden on the template author, who has to specify the
> RD> parameter on each DirectLink tag.
> 
> Template author just locates components:
> 
> <a jwcid="prevLink">previous</a> <a jwcid="nextLink">next</a>
> 
> There is no parameters specification!
> 

I tend to specify the links directly in the html templates using
jwcid="@DirectLink". I agree that using the jwc file to specify
parameters is more puristic. 

However, I have a dynamic set of links, one for each page (like google)
of a data set. I have no choice then but to put them directly in the
html template:

<span jwcid="@Foreach" value="ognl:navigationPage"
source="ognl:navigationPages">

	<a jwcid="@DirectLink" listener="ognl:listeners.changePage"
parameters="ognl:navigationPage">
		<span jwcid="@Insert" value="ognl:navigationPage + 1"/>
	</a>
</span>


Ruud



Re: Service parameters

Posted by Denis Ponomarev <oz...@romsat.ua>.
RD> True, but my problem with that is that the service parameters are like
RD> url parameters, where we wanted to be abstracted away from.  Concrete

I can't realize how you are going to work without service parameters.

RD> problem:

RD> I have 2 table components on one page, each with their own page
RD> numbering and current page. If one table is located at page 5, and a
RD> next page on the second table is selected, the original table falls back
RD> to page 1.
RD>

I don't know what kind of table components you use, but I think it
should has _persistent_ property 'currentPage'. So when you navigate
over one table, second keeps it's state. Did you hear something about
persistent properties? :)

RD> So the service parameters introduce a kind of 'global' variable space,
RD> which is not in line with 'component-based' development. Not to mention

You wrong. Service parameters intended to deliver specific inforamtion
directly to the component. There is no global space.
Look:

<component name="prevLink" type="DirectLink">
    <binding name="listener" expression="listeners.changePage"/>
    <binding name="parameters" expression="prevPage"/>
    <binding name="disabled" expression="first"/>
</component>

<component name="nextLink" type="DirectLink">
    <binding name="listener" expression="listeners.changePage"/>
    <binding name="parameters" expression="nextPage"/>
    <binding name="disabled" expression="last"/>
</component>

It assumes that your table component has isFirst(), isLast(),
getNext() and getPrevious() methods based on the currentPage
persistent property.

And action listener method

public void changePage(IRequestCycle cycle){
       Integer pageNumber = (Integer) cycle.getServiceParameters()[0];
       setCurrentPage(pageNumber.intValue());
}

RD> the extra burden on the template author, who has to specify the
RD> parameter on each DirectLink tag.

Template author just locates components:

<a jwcid="prevLink">previous</a> <a jwcid="nextLink">next</a>

There is no parameters specification!


Service parameters

Posted by Ruud Diterwich <rd...@cedron.com>.
True, but my problem with that is that the service parameters are like
url parameters, where we wanted to be abstracted away from.  Concrete
problem:

I have 2 table components on one page, each with their own page
numbering and current page. If one table is located at page 5, and a
next page on the second table is selected, the original table falls back
to page 1. 

So the service parameters introduce a kind of 'global' variable space,
which is not in line with 'component-based' development. Not to mention
the extra burden on the template author, who has to specify the
parameter on each DirectLink tag.

Ruud Diterwich

> -----Original Message-----
> From: Denis Ponomarev [mailto:oz@romsat.ua]
> Sent: Tuesday, June 24, 2003 11:23
> To: Tapestry users
> Subject: Re[2]: Redirects and multiple database fetches
> 
> RD> My case is a data table with next and previous buttons. When next
is
> RD> clicked, the data for the next page is fetched from the database.
> RD> Especially these navigation clicks should be fast and waiting for
2
> RD> fetches is annoying.
> 
> This is usual navigation actions! :)
> 
> I think your 'next' and 'previous' buttons should be DirectLinks with
> parameter 'pageNumber'. No redirection required.
> 
> You'll get links like
> 
> http://localhost:8081/dmc2?service=direct/1/MyEdit/0/$DirectLink&sp=2
> 
> where final '2' is pageNumber.
> 
> After refreshing you'll get the same page.
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re[2]: Redirects and multiple database fetches

Posted by Denis Ponomarev <oz...@romsat.ua>.
RD> My case is a data table with next and previous buttons. When next is
RD> clicked, the data for the next page is fetched from the database.
RD> Especially these navigation clicks should be fast and waiting for 2
RD> fetches is annoying.

This is usual navigation actions! :)

I think your 'next' and 'previous' buttons should be DirectLinks with
parameter 'pageNumber'. No redirection required.

You'll get links like

http://localhost:8081/dmc2?service=direct/1/MyEdit/0/$DirectLink&sp=2

where final '2' is pageNumber.

After refreshing you'll get the same page.


RE: Redirects and multiple database fetches

Posted by Ruud Diterwich <rd...@cedron.com>.
My case is a data table with next and previous buttons. When next is
clicked, the data for the next page is fetched from the database.
Especially these navigation clicks should be fast and waiting for 2
fetches is annoying.

I tried your suggestion, removing all data I needed to perform the
action from the result set and into persistent properties. Now I get the
error:

org.apache.tapestry.ApplicationRuntimeException: Page recorder for page
UserOverview is locked after a commit(), but received a change to
property lookAheadCount of component UserOverview/overview.

This is my render:

protected void prepareForRender(IRequestCycle cycle) {
	super.prepareForRender(cycle);
	try {

		if (cycle.isRewinding()) {
		}
					
		else if (getEntities() == null) {

			String[] propertyNames = getPropertyNames();
			ArrayList properties = new
ArrayList(propertyNames.length);
			for (int i = 0; i < propertyNames.length; i++) {
	
properties.add(getEntitySource().getEntityInfo().getProperty(propertyNam
es[i]));
			}
			setProperties(properties);

			EntityList entities =
getEntitySource().get(null, null, null, new PagingInfo(getStartIndex(),
getPageSize(), getPageCount() * getPageSize()));
			setEntities(entities);
			setLookAheadCount(entities.getLookAheadCount());

		}
			
	} catch (RenderRewoundException e) {
		throw e;
	} catch (RedirectException e) {
		throw e;
	} catch (Exception e) {
		throw new RuntimeException(e);
	}
}

> -----Original Message-----
> From: Denis Ponomarev [mailto:oz@romsat.ua]
> Sent: Tuesday, June 24, 2003 10:20
> To: Tapestry users
> Subject: Re: Redirects and multiple database fetches
> 
> RD> The redirects work great, but now I have the problem that the
database
> RD> is fetched twice. The database is read in prepareForRender(), and
the
> RD> result is cached in the component as a non-persistent property
(The
> RD> result is not serializable and too big anyway). However, after the
> RD> redirect I don't want to fetch the result again. Is there a way to
> RD> access the data that was generated just before the redirect?
> 
> From my point of view double fething is not a problem. Of course you
> don't send redirects when usual navigation actions triggered, isn't
it?
> You sends them only if you action performs some realy work - such as
> database modification. I think it happens rarely and you can live with
it.
> 
> If not:
> 
> Is the big result for rendering purposes only?
> Can you skip reading big data if you page is rendered to execute
> action listener method?
> 
> Probably you can surround your havy reading by this:
> 
> if(cycle.isRewinding()){
>     // action-triggered, read data which you need to perform action
> }else{
>     // rendering process, read all what you need to display
> }
> 
> I'm not shure this helps, but hope this can be a starting point.
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: Redirects and multiple database fetches

Posted by Denis Ponomarev <oz...@romsat.ua>.
RD> The redirects work great, but now I have the problem that the database
RD> is fetched twice. The database is read in prepareForRender(), and the
RD> result is cached in the component as a non-persistent property (The
RD> result is not serializable and too big anyway). However, after the
RD> redirect I don't want to fetch the result again. Is there a way to
RD> access the data that was generated just before the redirect?