You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Alessio Gambi <ag...@gmail.com> on 2010/09/16 00:24:53 UTC

Enforcing constraints on component instances in pages

Hi,

I'm trying to find an elegant way in T5.1 to ensure that a page contains one and only once instance of a given component.

My initial idea was to define a base page class that has the logic to render the component using the Component annotation, and to check for duplicates of the same component (to remove them or to generate an exception). Unfortunately, I was no able to get it working properly, I get either an exception during the rendering phase or the template of that component is not rendered at all.

I though about using an approach similar to the layout component as a workaround, thus avoiding the inheritance among pages, but I prefer to use thus approach as B-plan.

Do you have any suggestion ?

Thanks

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


Re: Enforcing constraints on component instances in pages

Posted by Alessio Gambi <ag...@gmail.com>.
Hi,

On Sep 16, 2010, at 6:26 PM, Howard Lewis Ship wrote:

> I'd be interested to know why you are so desperate to enforce this
> unique constraint

I am not really desperate... just curious on how one can check and  
enforce some properties (or constraints) on the page, its components  
and the relationships among them.

I tell you the scenario that motivated the need (that I solve thanks  
to the DOM solution #1) of enforcing this uniqueness (or page level  
singletoness if you prefer):

The context is to how to integrate T5 and GWT.

I followed the tutorial on the wiki (http://wiki.apache.org/tapestry/Tapestry5GWTIntegration 
, BTW the provided jar file is ok while the textual description of the  
approach is a bit out-of-date).
The "trick" to embed GWT components in T5 components rely on a T5  
component called GwtSupport that provides the right path to the needed  
js files
(see the tutorial for the details) and then renders itself as a couple  
of tag SCRIPT.

The problem appeared when I started to extend this approach a bit, as  
I discovered that this GwtSupport component is mandatory to be in a  
page that contains GwtComponents,
but somehow it cannot be duplicate otherwise the GWT Framework (at  
least in the hosted mode) generates an exception and does not load the  
js files.

So the situation was to somehow check for that constraint.

Now if you take the point of view of a developer that wants to create  
a GWT script, (s)he must assume either the GwtSupport is provided or  
not, but till the very end (s)he
cannot be sure that the assumption will hold.

So what I tried to do was to factorize the common code of  
GwtComponents in a base class containing the GwtSupport component, but  
this solved just half of the problem as we
now can safely assume only to have the GwtSupport.
The check for duplication was missing (and this generates my first  
question).

I had a similiar problem when I integrated DWR with T5 to provide a  
DataPushService using comet, but at that time I only "assumed" that  
the supporting
scaffolding of needed-but-not-duplicable components were there as I  
expected.

In the meanwhile, I though about possible scenarios to justify an  
effort in working on how to enforce/check these properties and I come  
up only with few of them:

1) Performance/Non functional constraints. A design time one may want  
to limit the presence of some components in the page to prevent server  
overload.

2) Affinity/Anti-affinity. A designer may want to have/or to avoid  
that two components are rendered in the page at the same time.

3) Licensing. A component cannot be used in more than X pages in the  
same app.

BTW, I do not have any personal experience to say if these situations  
are worth to be considered or not, and when they make sense.

Thanks.

-- Alessio
PS: @Howard: we can talk about this in London in few weeks.

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


Re: Enforcing constraints on component instances in pages

Posted by Howard Lewis Ship <hl...@gmail.com>.
I can imagine a Mixin that enforces uniqueness (at least, during a
full page render).  It could check-and-store a Request attribute.
Should be just a couple of lines of code.  Alas, you would not see the
error until the page rendered (and partial page updates via Ajax could
through a monkey wrench into this as well).

I'd be interested to know why you are so desperate to enforce this
unique constraint (and why you don't test your pages or trust your
coders).

On Thu, Sep 16, 2010 at 7:15 AM, Josh Canfield <jo...@gmail.com> wrote:
>> you can communicate values using the Environment class (push and
>> pop/peek methods)
>
> I considered using the environment for this, but I'm a big proponent of popping what I push; That might be a bit misguided but it's an old habit.
>
>> so you dont
>> have to (ab)use the
>> dom document for something like this
>
> Hmm... I wouldn't have considered this abuse. If your component is going to render something known what's the harm in looking it up later?
>
>>> However, this solution will not scale easily for different constraints.
>
> If you want your components to put constraints on their usage by a developer then you may want to consider a more involved solution. Probably using an annotation and a transformation to keep track of whatever attributes you want to enforce. Unless you expect the component to be added multiple times but only render once I'd also consider throwing an exception so the developer knows why their second instance didn't render. Perhaps an attribute of your annotation?
> @ComponentRestrictions(max=1, failHard=true)
>
> -- Josh
>
> On Sep 16, 2010, at 12:02 AM, Andreas Andreou <an...@di.uoa.gr> wrote:
>
>> you can communicate values using the Environment class (push and
>> pop/peek methods)
>> or by injecting the ServletRequest and set/getAttribute... so you dont
>> have to (ab)use the
>> dom document for something like this
>>
>> On Thu, Sep 16, 2010 at 09:17, Alessio Gambi <ag...@gmail.com> wrote:
>>> Hi Josh,
>>>
>>> thanks.
>>>
>>> As you suggested I defined a special-fixed-component-id for the component
>>> and I checked before its rendering (during its own SetupRender) if that id
>>> was already present
>>> in the document (writer.getDocument().getElementById()). If so I just
>>> skipped the render (by returning False) and everything is fine.
>>>
>>> However, this solution will not scale easily for different constraints.
>>> Assume for example that you want to force one of the following constraints
>>> in the page (not all of them may have real use cases):
>>>
>>> - N and only N components of the same type, N > 1
>>> - No components of type X
>>>
>>> I guess you can always work with the Document object and look for some IDs
>>> (maybe a programmatic way to do that will scale better).
>>> Moreover, I noticed that apparently the Document object
>>> (writer.getDocument()) provides only two methods to retrieve elements:
>>>  Element        find(String path)                       [Finds an element
>>> based on a path of element names.]
>>>  Element        getElementById(String id)               [Tries to find an
>>> element in this document whose id is specified.]
>>>
>>> and both of them assume that you know precisely what you are looking for,
>>> and they cannot use of regexp or similar to specify the id and path params.
>>>
>>> BTW (maybe OT)
>>> Can you render a component inside a page or another component that has no
>>> template at all?
>>>
>>> Something like this.
>>> Container Component Class{
>>>
>>> private ContainedComponent myComponent;
>>>
>>> @BeginRender
>>> public void render(MarkupWriter markupWriter){
>>>        markupWriter.render( myComponent );
>>> }
>>> }
>>>
>>> I tried adding the @Component annotation and returning the object in the
>>> different rendering methods, but it didn't work.
>>>
>>> Thanks again.
>>> -- Alessio
>>>
>>>
>>
>>
>>
>> --
>> Andreas Andreou - andyhot@apache.org - http://blog.andyhot.gr
>> Tapestry PMC / Tacos developer
>> Open Source / JEE Consulting
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>



-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

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


Re: Enforcing constraints on component instances in pages

Posted by Josh Canfield <jo...@gmail.com>.
> you can communicate values using the Environment class (push and
> pop/peek methods)

I considered using the environment for this, but I'm a big proponent of popping what I push; That might be a bit misguided but it's an old habit.
 
> so you dont
> have to (ab)use the
> dom document for something like this

Hmm... I wouldn't have considered this abuse. If your component is going to render something known what's the harm in looking it up later?

>> However, this solution will not scale easily for different constraints.

If you want your components to put constraints on their usage by a developer then you may want to consider a more involved solution. Probably using an annotation and a transformation to keep track of whatever attributes you want to enforce. Unless you expect the component to be added multiple times but only render once I'd also consider throwing an exception so the developer knows why their second instance didn't render. Perhaps an attribute of your annotation? 
@ComponentRestrictions(max=1, failHard=true)

-- Josh

On Sep 16, 2010, at 12:02 AM, Andreas Andreou <an...@di.uoa.gr> wrote:

> you can communicate values using the Environment class (push and
> pop/peek methods)
> or by injecting the ServletRequest and set/getAttribute... so you dont
> have to (ab)use the
> dom document for something like this
> 
> On Thu, Sep 16, 2010 at 09:17, Alessio Gambi <ag...@gmail.com> wrote:
>> Hi Josh,
>> 
>> thanks.
>> 
>> As you suggested I defined a special-fixed-component-id for the component
>> and I checked before its rendering (during its own SetupRender) if that id
>> was already present
>> in the document (writer.getDocument().getElementById()). If so I just
>> skipped the render (by returning False) and everything is fine.
>> 
>> However, this solution will not scale easily for different constraints.
>> Assume for example that you want to force one of the following constraints
>> in the page (not all of them may have real use cases):
>> 
>> - N and only N components of the same type, N > 1
>> - No components of type X
>> 
>> I guess you can always work with the Document object and look for some IDs
>> (maybe a programmatic way to do that will scale better).
>> Moreover, I noticed that apparently the Document object
>> (writer.getDocument()) provides only two methods to retrieve elements:
>>  Element        find(String path)                       [Finds an element
>> based on a path of element names.]
>>  Element        getElementById(String id)               [Tries to find an
>> element in this document whose id is specified.]
>> 
>> and both of them assume that you know precisely what you are looking for,
>> and they cannot use of regexp or similar to specify the id and path params.
>> 
>> BTW (maybe OT)
>> Can you render a component inside a page or another component that has no
>> template at all?
>> 
>> Something like this.
>> Container Component Class{
>> 
>> private ContainedComponent myComponent;
>> 
>> @BeginRender
>> public void render(MarkupWriter markupWriter){
>>        markupWriter.render( myComponent );
>> }
>> }
>> 
>> I tried adding the @Component annotation and returning the object in the
>> different rendering methods, but it didn't work.
>> 
>> Thanks again.
>> -- Alessio
>> 
>> 
> 
> 
> 
> -- 
> Andreas Andreou - andyhot@apache.org - http://blog.andyhot.gr
> Tapestry PMC / Tacos developer
> Open Source / JEE Consulting
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
> 

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


Re: Enforcing constraints on component instances in pages

Posted by Andreas Andreou <an...@di.uoa.gr>.
you can communicate values using the Environment class (push and
pop/peek methods)
or by injecting the ServletRequest and set/getAttribute... so you dont
have to (ab)use the
dom document for something like this

On Thu, Sep 16, 2010 at 09:17, Alessio Gambi <ag...@gmail.com> wrote:
> Hi Josh,
>
> thanks.
>
> As you suggested I defined a special-fixed-component-id for the component
> and I checked before its rendering (during its own SetupRender) if that id
> was already present
> in the document (writer.getDocument().getElementById()). If so I just
> skipped the render (by returning False) and everything is fine.
>
> However, this solution will not scale easily for different constraints.
> Assume for example that you want to force one of the following constraints
> in the page (not all of them may have real use cases):
>
> - N and only N components of the same type, N > 1
> - No components of type X
>
> I guess you can always work with the Document object and look for some IDs
> (maybe a programmatic way to do that will scale better).
> Moreover, I noticed that apparently the Document object
> (writer.getDocument()) provides only two methods to retrieve elements:
>  Element        find(String path)                       [Finds an element
> based on a path of element names.]
>  Element        getElementById(String id)               [Tries to find an
> element in this document whose id is specified.]
>
> and both of them assume that you know precisely what you are looking for,
> and they cannot use of regexp or similar to specify the id and path params.
>
> BTW (maybe OT)
> Can you render a component inside a page or another component that has no
> template at all?
>
> Something like this.
> Container Component Class{
>
> private ContainedComponent myComponent;
>
> @BeginRender
> public void render(MarkupWriter markupWriter){
>        markupWriter.render( myComponent );
> }
> }
>
> I tried adding the @Component annotation and returning the object in the
> different rendering methods, but it didn't work.
>
> Thanks again.
> -- Alessio
>
>



-- 
Andreas Andreou - andyhot@apache.org - http://blog.andyhot.gr
Tapestry PMC / Tacos developer
Open Source / JEE Consulting

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


Re: Enforcing constraints on component instances in pages

Posted by Alessio Gambi <ag...@gmail.com>.
Hi Josh,

thanks.

As you suggested I defined a special-fixed-component-id for the  
component and I checked before its rendering (during its own  
SetupRender) if that id was already present
in the document (writer.getDocument().getElementById()). If so I just  
skipped the render (by returning False) and everything is fine.

However, this solution will not scale easily for different constraints.
Assume for example that you want to force one of the following  
constraints in the page (not all of them may have real use cases):

- N and only N components of the same type, N > 1
- No components of type X

I guess you can always work with the Document object and look for some  
IDs (maybe a programmatic way to do that will scale better).
Moreover, I noticed that apparently the Document object  
(writer.getDocument()) provides only two methods to retrieve elements:
  Element 	find(String path) 			[Finds an element based on a path of  
element names.]
  Element 	getElementById(String id)		[Tries to find an element in  
this document whose id is specified.]

and both of them assume that you know precisely what you are looking  
for, and they cannot use of regexp or similar to specify the id and  
path params.

BTW (maybe OT)
Can you render a component inside a page or another component that has  
no template at all?

Something like this.
Container Component Class{

private ContainedComponent myComponent;

@BeginRender
public void render(MarkupWriter markupWriter){
	markupWriter.render( myComponent );
}
}

I tried adding the @Component annotation and returning the object in  
the different rendering methods, but it didn't work.

Thanks again.
-- Alessio


Re: Enforcing constraints on component instances in pages

Posted by Josh Canfield <jo...@gmail.com>.
Generally your component will be putting something in the page so can
you just check the DOM for a known element? If you can only have one
of the component in the page then it should be safe to use a fixed
element id and then you can call
"writer.getDocument().getElementById("special-fixed-component-id");"
from beginRender(MarkupWriter writer). if the element exists then
throw an exception or whatever.

On Wed, Sep 15, 2010 at 3:24 PM, Alessio Gambi <ag...@gmail.com> wrote:
> Hi,
>
> I'm trying to find an elegant way in T5.1 to ensure that a page contains one and only once instance of a given component.
>
> My initial idea was to define a base page class that has the logic to render the component using the Component annotation, and to check for duplicates of the same component (to remove them or to generate an exception). Unfortunately, I was no able to get it working properly, I get either an exception during the rendering phase or the template of that component is not rendered at all.
>
> I though about using an approach similar to the layout component as a workaround, thus avoiding the inheritance among pages, but I prefer to use thus approach as B-plan.
>
> Do you have any suggestion ?
>
> Thanks
>
> -- Alessio
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>



-- 
--
http://www.bodylabgym.com - a private, by appointment only, one-on-one
health and fitness facility.
--
http://www.ectransition.com - Quality Electronic Cigarettes at a
reasonable price!
--
TheDailyTube.com. Sign up and get the best new videos on the internet
delivered fresh to your inbox.

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