You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Paul Stanton <pa...@gunnsoft.com.au> on 2004/07/19 06:23:16 UTC

component value references.. reusing values

i'm finding ognl expressions/component declarations kind of expensive. 
when i need use the result of a complex method a number of times i'd 
like to declare the value and reuse the result instead of having to keep 
calling the expensive method. i'm aware i can do this in the class i am 
referencing by setting the value to an instance variable and testing if 
it is null before running the expensive method again, but this makes my 
business logic overly complex and it's not my business logic's job to 
handle value storing for tapestry.

i'm wondering if i can do this in my page/html files... can i have for 
example an 'Insert' component

<component id="Result" type="Insert">
    <binding name="value" expression="bigMethodThatTakesAges"/>
</component>

and then reference the value for 'Condition' components

<component id="IfResultIsReallyBig" type="Conditional">
    <binding name="condition" expression="components.Result.value > 10"/>
</component>

<component id="IfResultIsReallySmall" type="Conditional">
    <binding name="condition" expression="components.Result.value < 2"/>
</component>

i know this won't work because i've tried it. it looks like tapestry 
unsets the value of the insert component after it is rendered. is there 
an easy way to do what i'm talking about? Is there a 'variable' 
component i can use to store a value or something?

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


Re: component value references.. reusing values

Posted by Omar Valerio <om...@gmail.com>.
Yes, that is what the pageBeginRender() stand for, to create any valid
state you may need within you Page, and store it in suitable
properties, who can then be called during render as many times as you
wish.

--
Omar V.

On Mon, 19 Jul 2004 22:09:58 +1000, Glen Stampoultzis
<gs...@iinet.net.au> wrote:
> 
> I'm not sure I'm following exactly but can't you use the pageBeginRender()
> to initialize the value then reuse that value multiple times during the render?
> 
> -- Glen
>

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


Re: component value references.. reusing values

Posted by Glen Stampoultzis <gs...@iinet.net.au>.
I'm not sure I'm following exactly but can't you use the pageBeginRender() 
to initialize the value then reuse that value multiple times during the render?

-- Glen

At 02:23 PM 19/07/2004, you wrote:
>i'm finding ognl expressions/component declarations kind of expensive. 
>when i need use the result of a complex method a number of times i'd like 
>to declare the value and reuse the result instead of having to keep 
>calling the expensive method. i'm aware i can do this in the class i am 
>referencing by setting the value to an instance variable and testing if it 
>is null before running the expensive method again, but this makes my 
>business logic overly complex and it's not my business logic's job to 
>handle value storing for tapestry.
>
>i'm wondering if i can do this in my page/html files... can i have for 
>example an 'Insert' component
>
><component id="Result" type="Insert">
>    <binding name="value" expression="bigMethodThatTakesAges"/>
></component>
>
>and then reference the value for 'Condition' components
>
><component id="IfResultIsReallyBig" type="Conditional">
>    <binding name="condition" expression="components.Result.value > 10"/>
></component>
>
><component id="IfResultIsReallySmall" type="Conditional">
>    <binding name="condition" expression="components.Result.value < 2"/>
></component>
>
>i know this won't work because i've tried it. it looks like tapestry 
>unsets the value of the insert component after it is rendered. is there an 
>easy way to do what i'm talking about? Is there a 'variable' component i 
>can use to store a value or something?
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
>For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>


Glen Stampoultzis
gstamp@iinet.net.au
http://members.iinet.net.au/~gstamp/glen/

Re: component value references.. reusing values

Posted by Paul Stanton <pa...@gunnsoft.com.au>.
ahh yes. thats much nicer! although i had to use the follownig code:

public FileHandle getLatestFile()
{
    ReportJob job = (ReportJob) ((Foreach) 
getComponents().get("jobLoop")).getValue();
    if (curJob != null && job.getName().equals(curJob))
        return latest;

    curJob = job.getName();
    latest = job.getLatestFile();
    return latest;
}

thanks for the help, it has opened up a whole bunch of new possibilities 
for me.

Danny Mandel wrote:

> Is there a reason you can't cache this value in your component class?
>
> Instead of binding your 'ifHasFile' Conditional to 
> 'components.jobLoop.value.latestFile' you could create an accessor 
> inside your component class called latestFile that would handle the 
> caching of the value.  That way your business object doesn't need to 
> be aware of any caching.
>
> I.e.
>
> public String getLatestFile() {
>    // Assume you have a property called latestFileProp that holds a 
> String
>    String latestFile = getLatestFileProp();
>    if (latestFile == null) {
>       // Do expensive calculations -- this code isn't tested, but has 
> the general idea
>       latestFile = 
> getComponents().get("jobLoop").getValue().getLatestFile();
>       setLatestFileProp(latestFile);
>    }
>    return latestFile;
> }
>
> Hope that helps,
> Danny
>
> Paul Stanton wrote:
>
>> ok, now having a slightly more dramatic twist with this problem.. 
>> what if the 'super slow' method is being called inside a loop 
>> (Foreach component)? for example:
>>
>>    <component id="jobLoop" type="Foreach">
>>        <binding name="source" expression="currentJobs"/>
>>    </component>
>>
>>    <component id="ifHasFile" type="Conditional">
>>        <binding name="condition" 
>> expression="components.jobLoop.value.latestFile != null"/>
>>    </component>
>>      <component id="latestFileNameInsert" type="Insert">
>>        <binding name="value" 
>> expression="components.jobLoop.value.latestFile.name"/>
>>    </component>
>>
>>    <component id="downloadLatest" type="ServiceLink">
>>        <binding name="service" expression="@...DownloadService@NAME"/>
>>        <binding name="parameters" 
>> expression="components.jobLoop.value.latestFile"/>
>>    </component>
>>
>> In this case the method 'getLatestFile' can take 5 seconds (as it 
>> talks to a remote server) and it's being called 3 times. I know i can 
>> cache the result in the first call and return the cached value in 
>> subsequent calls, but that means i have to write 'tapestry' code into 
>> my business object and could also lead to some unexpected behaviour 
>> in non-tapestry uses of the object. I can't initialise this value in 
>> pageBeginRender because it's under a loop. The only solution i can 
>> think of is to create a new method in the bean called 
>> 'getCachedLatestFile' specifically for this case which (as i have 
>> mentioned) i don't like having to do.
>>
>> Paul Stanton wrote:
>>
>>> pageBeginRender sounds like the most viable option at present, but 
>>> it would be nice to have this built into the tapestry component 
>>> model as a 'variable' component. in many cases the variables will be 
>>> context specific; only needing to be computed if a specific set of 
>>> other conditions are met.. some of which may be 'conditional' 
>>> components. i believe having a component which simply holds a value 
>>> and doesn't let it go (a simple mod of the Insert component) would 
>>> save a lot of development time and keep code cleaner in some cases.
>>>
>>>
>>>
>>> Howard Lewis Ship wrote:
>>>
>>>> Another option to to create a component that exists just to evaluate
>>>> an OGNL expression and store the result into a page/component property
>>>> (for use elsewhere within the page/component).  I've thought about
>>>> doing this, but generally have my page/component implement
>>>> PageBeginRender and do all the necessary setup and calucluations
>>>> there.
>>>>
>>>> Yet another option is to use the Delegator component and have the
>>>> delegate (and object that implement IRender, possibly an inner class
>>>> of your page/component) compute, in Java code, the value and store it
>>>> into a property.
>>>>
>>>> On Mon, 19 Jul 2004 08:40:26 -0300, Marcus Brito <mb...@gmail.com> 
>>>> wrote:
>>>>  
>>>>
>>>>> Not a component, but you could declare a property on your page
>>>>> specification, and update/read that property as the page renders. If
>>>>> you require something fancier than a simple property, you could
>>>>> declare a bean with all the smarts you need it to do.
>>>>>
>>>>> -- Marcus
>>>>>
>>>>>
>>>>>
>>>>> On Mon, 19 Jul 2004 14:23:16 +1000, Paul Stanton
>>>>> <pa...@gunnsoft.com.au> wrote:
>>>>>  
>>>>>
>>>>>> i know this won't work because i've tried it. it looks like tapestry
>>>>>> unsets the value of the insert component after it is rendered. is 
>>>>>> there
>>>>>> an easy way to do what i'm talking about? Is there a 'variable'
>>>>>> component i can use to store a value or something?
>>>>>

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


Re: component value references.. reusing values

Posted by Danny Mandel <dm...@tolweb.org>.
Is there a reason you can't cache this value in your component class?

Instead of binding your 'ifHasFile' Conditional to 
'components.jobLoop.value.latestFile' you could create an accessor 
inside your component class called latestFile that would handle the 
caching of the value.  That way your business object doesn't need to be 
aware of any caching.

I.e.

public String getLatestFile() {
    // Assume you have a property called latestFileProp that holds a String
    String latestFile = getLatestFileProp();
    if (latestFile == null) {
       // Do expensive calculations -- this code isn't tested, but has 
the general idea
       latestFile = 
getComponents().get("jobLoop").getValue().getLatestFile();
       setLatestFileProp(latestFile);
    }
    return latestFile;
}

Hope that helps,
Danny

Paul Stanton wrote:

> ok, now having a slightly more dramatic twist with this problem.. what 
> if the 'super slow' method is being called inside a loop (Foreach 
> component)? for example:
>
>    <component id="jobLoop" type="Foreach">
>        <binding name="source" expression="currentJobs"/>
>    </component>
>
>    <component id="ifHasFile" type="Conditional">
>        <binding name="condition" 
> expression="components.jobLoop.value.latestFile != null"/>
>    </component>
>      <component id="latestFileNameInsert" type="Insert">
>        <binding name="value" 
> expression="components.jobLoop.value.latestFile.name"/>
>    </component>
>
>    <component id="downloadLatest" type="ServiceLink">
>        <binding name="service" expression="@...DownloadService@NAME"/>
>        <binding name="parameters" 
> expression="components.jobLoop.value.latestFile"/>
>    </component>
>
> In this case the method 'getLatestFile' can take 5 seconds (as it 
> talks to a remote server) and it's being called 3 times. I know i can 
> cache the result in the first call and return the cached value in 
> subsequent calls, but that means i have to write 'tapestry' code into 
> my business object and could also lead to some unexpected behaviour in 
> non-tapestry uses of the object. I can't initialise this value in 
> pageBeginRender because it's under a loop. The only solution i can 
> think of is to create a new method in the bean called 
> 'getCachedLatestFile' specifically for this case which (as i have 
> mentioned) i don't like having to do.
>
> Paul Stanton wrote:
>
>> pageBeginRender sounds like the most viable option at present, but it 
>> would be nice to have this built into the tapestry component model as 
>> a 'variable' component. in many cases the variables will be context 
>> specific; only needing to be computed if a specific set of other 
>> conditions are met.. some of which may be 'conditional' components. i 
>> believe having a component which simply holds a value and doesn't let 
>> it go (a simple mod of the Insert component) would save a lot of 
>> development time and keep code cleaner in some cases.
>>
>>
>>
>> Howard Lewis Ship wrote:
>>
>>> Another option to to create a component that exists just to evaluate
>>> an OGNL expression and store the result into a page/component property
>>> (for use elsewhere within the page/component).  I've thought about
>>> doing this, but generally have my page/component implement
>>> PageBeginRender and do all the necessary setup and calucluations
>>> there.
>>>
>>> Yet another option is to use the Delegator component and have the
>>> delegate (and object that implement IRender, possibly an inner class
>>> of your page/component) compute, in Java code, the value and store it
>>> into a property.
>>>
>>> On Mon, 19 Jul 2004 08:40:26 -0300, Marcus Brito <mb...@gmail.com> 
>>> wrote:
>>>  
>>>
>>>> Not a component, but you could declare a property on your page
>>>> specification, and update/read that property as the page renders. If
>>>> you require something fancier than a simple property, you could
>>>> declare a bean with all the smarts you need it to do.
>>>>
>>>> -- Marcus
>>>>
>>>>
>>>>
>>>> On Mon, 19 Jul 2004 14:23:16 +1000, Paul Stanton
>>>> <pa...@gunnsoft.com.au> wrote:
>>>>  
>>>>
>>>>> i know this won't work because i've tried it. it looks like tapestry
>>>>> unsets the value of the insert component after it is rendered. is 
>>>>> there
>>>>> an easy way to do what i'm talking about? Is there a 'variable'
>>>>> component i can use to store a value or something?
>>>>>     
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
>>>> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>>>>   
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org




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


Re: component value references.. reusing values

Posted by Paul Stanton <pa...@gunnsoft.com.au>.
ok, now having a slightly more dramatic twist with this problem.. what 
if the 'super slow' method is being called inside a loop (Foreach 
component)? for example:

    <component id="jobLoop" type="Foreach">
        <binding name="source" expression="currentJobs"/>
    </component>

    <component id="ifHasFile" type="Conditional">
        <binding name="condition" 
expression="components.jobLoop.value.latestFile != null"/>
    </component>
   
    <component id="latestFileNameInsert" type="Insert">
        <binding name="value" 
expression="components.jobLoop.value.latestFile.name"/>
    </component>

    <component id="downloadLatest" type="ServiceLink">
        <binding name="service" expression="@...DownloadService@NAME"/>
        <binding name="parameters" 
expression="components.jobLoop.value.latestFile"/>
    </component>

In this case the method 'getLatestFile' can take 5 seconds (as it talks 
to a remote server) and it's being called 3 times. I know i can cache 
the result in the first call and return the cached value in subsequent 
calls, but that means i have to write 'tapestry' code into my business 
object and could also lead to some unexpected behaviour in non-tapestry 
uses of the object. I can't initialise this value in pageBeginRender 
because it's under a loop. The only solution i can think of is to create 
a new method in the bean called 'getCachedLatestFile' specifically for 
this case which (as i have mentioned) i don't like having to do.

Paul Stanton wrote:

> pageBeginRender sounds like the most viable option at present, but it 
> would be nice to have this built into the tapestry component model as 
> a 'variable' component. in many cases the variables will be context 
> specific; only needing to be computed if a specific set of other 
> conditions are met.. some of which may be 'conditional' components. i 
> believe having a component which simply holds a value and doesn't let 
> it go (a simple mod of the Insert component) would save a lot of 
> development time and keep code cleaner in some cases.
>
>
>
> Howard Lewis Ship wrote:
>
>> Another option to to create a component that exists just to evaluate
>> an OGNL expression and store the result into a page/component property
>> (for use elsewhere within the page/component).  I've thought about
>> doing this, but generally have my page/component implement
>> PageBeginRender and do all the necessary setup and calucluations
>> there.
>>
>> Yet another option is to use the Delegator component and have the
>> delegate (and object that implement IRender, possibly an inner class
>> of your page/component) compute, in Java code, the value and store it
>> into a property.
>>
>> On Mon, 19 Jul 2004 08:40:26 -0300, Marcus Brito <mb...@gmail.com> 
>> wrote:
>>  
>>
>>> Not a component, but you could declare a property on your page
>>> specification, and update/read that property as the page renders. If
>>> you require something fancier than a simple property, you could
>>> declare a bean with all the smarts you need it to do.
>>>
>>> -- Marcus
>>>
>>>
>>>
>>> On Mon, 19 Jul 2004 14:23:16 +1000, Paul Stanton
>>> <pa...@gunnsoft.com.au> wrote:
>>>   
>>>
>>>> i know this won't work because i've tried it. it looks like tapestry
>>>> unsets the value of the insert component after it is rendered. is 
>>>> there
>>>> an easy way to do what i'm talking about? Is there a 'variable'
>>>> component i can use to store a value or something?
>>>>     
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
>>> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>>>   
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


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


Re: component value references.. reusing values

Posted by Paul Stanton <pa...@gunnsoft.com.au>.
pageBeginRender sounds like the most viable option at present, but it would be nice to have this built into the tapestry component model as a 'variable' component. in many cases the variables will be context specific; only needing to be computed if a specific set of other conditions are met.. some of which may be 'conditional' components. i believe having a component which simply holds a value and doesn't let it go (a simple mod of the Insert component) would save a lot of development time and keep code cleaner in some cases.



Howard Lewis Ship wrote:

>Another option to to create a component that exists just to evaluate
>an OGNL expression and store the result into a page/component property
>(for use elsewhere within the page/component).  I've thought about
>doing this, but generally have my page/component implement
>PageBeginRender and do all the necessary setup and calucluations
>there.
>
>Yet another option is to use the Delegator component and have the
>delegate (and object that implement IRender, possibly an inner class
>of your page/component) compute, in Java code, the value and store it
>into a property.
>
>On Mon, 19 Jul 2004 08:40:26 -0300, Marcus Brito <mb...@gmail.com> wrote:
>  
>
>>Not a component, but you could declare a property on your page
>>specification, and update/read that property as the page renders. If
>>you require something fancier than a simple property, you could
>>declare a bean with all the smarts you need it to do.
>>
>>-- Marcus
>>
>>
>>
>>On Mon, 19 Jul 2004 14:23:16 +1000, Paul Stanton
>><pa...@gunnsoft.com.au> wrote:
>>    
>>
>>>i know this won't work because i've tried it. it looks like tapestry
>>>unsets the value of the insert component after it is rendered. is there
>>>an easy way to do what i'm talking about? Is there a 'variable'
>>>component i can use to store a value or something?
>>>      
>>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
>>For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>>    
>>

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


Re: component value references.. reusing values

Posted by Howard Lewis Ship <hl...@gmail.com>.
Another option to to create a component that exists just to evaluate
an OGNL expression and store the result into a page/component property
(for use elsewhere within the page/component).  I've thought about
doing this, but generally have my page/component implement
PageBeginRender and do all the necessary setup and calucluations
there.

Yet another option is to use the Delegator component and have the
delegate (and object that implement IRender, possibly an inner class
of your page/component) compute, in Java code, the value and store it
into a property.

On Mon, 19 Jul 2004 08:40:26 -0300, Marcus Brito <mb...@gmail.com> wrote:
> Not a component, but you could declare a property on your page
> specification, and update/read that property as the page renders. If
> you require something fancier than a simple property, you could
> declare a bean with all the smarts you need it to do.
> 
> -- Marcus
> 
> 
> 
> On Mon, 19 Jul 2004 14:23:16 +1000, Paul Stanton
> <pa...@gunnsoft.com.au> wrote:
> > i know this won't work because i've tried it. it looks like tapestry
> > unsets the value of the insert component after it is rendered. is there
> > an easy way to do what i'm talking about? Is there a 'variable'
> > component i can use to store a value or something?
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> 
> 


-- 
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator, Jakarta Tapestry
Creator, Jakarta HiveMind
http://howardlewisship.com

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


Re: component value references.. reusing values

Posted by Marcus Brito <mb...@gmail.com>.
Not a component, but you could declare a property on your page
specification, and update/read that property as the page renders. If
you require something fancier than a simple property, you could
declare a bean with all the smarts you need it to do.

-- Marcus

On Mon, 19 Jul 2004 14:23:16 +1000, Paul Stanton
<pa...@gunnsoft.com.au> wrote:
> i know this won't work because i've tried it. it looks like tapestry
> unsets the value of the insert component after it is rendered. is there
> an easy way to do what i'm talking about? Is there a 'variable'
> component i can use to store a value or something?

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