Iterate through Attributes

View: New views
13 Messages — Rating Filter:   Alert me  

Iterate through Attributes

by JRD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

We are migrating an app from Struts1/Tiles1 to Struts2/Tiles2

We have a bunch of different transactions types that all collect similar data (Addresses, dates, text inputs, etc...).  We use tiles as a view controller (among other things).

So for each thing we want to display we would have a read-only and a data-entry display.  The view controller would use state and security to determine what view was appropriate, and then pass along all of the original data passed in to the correct view.

In Tiles 1 our view controller looked like this:

<c:set var="tilesKey" value="org.apache.struts.taglib.tiles.CompContext"/>
<cw:set var="theTiles" bean="${tilesKey}"/>


...select view...

<tiles:insert definition="${definition}">
        <tiles:put name="viewFormat" value="${viewFormat}"/>
        <c:forEach items="${theTiles.attributeNames}" var="attribute">
                <tiles:put name="${attribute}"><tiles:getAsString name="${attribute}"/></tiles:put>
        </c:forEach>

</tiles:insert>

The view selector can not know what attributes to pass along since each thing we want to display has different attributes.  Any idea how to do this in Tiles 2?

Thanks in advance,
Jonathan

Re: Iterate through Attributes

by Antonio Petrelli-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2008/4/15, JRD <danger_jon@...>:
>  <tiles:insert definition="${definition}">
>         <tiles:put name="viewFormat" value="${viewFormat}"/>
>         <c:forEach items="${theTiles.attributeNames}" var="attribute">
>                 <tiles:put name="${attribute}"><tiles:getAsString
>  name="${attribute}"/></tiles:put>
>         </c:forEach>
>  </tiles:insert>

I am sorry to say it, put this is plain wrong: you are trying to push
the attributes from the attribute context in which the <tiles:*> tags
are, to the context of the inserted definition, one by one.
I suggest to refactor your code putting the attributes directly in the
inserted definition, for example, via a ViewPreparer:
http://tiles.apache.org/tutorial/advanced/preparer.html

Notice that this won't help you in pushing the attributes from one
context to another (the "AttributeContext" parameter is the current
context, i.e. in your case it would be the context of the
"${definition}" definition).

Maybe the right thing to do is starting from the beginning: what are
you trying to accomplish?

Antonio

Re: Iterate through Attributes

by JRD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The begining: I am building an application that has several different 'transactions'.  All transactions collect similar information and all transactions have the same look and feel.  So transaction 'A' might collect two addresses and two dates, and transaction 'B' might collect one address, one text field, and one date.

How a user interacts with a transaction depends both upon the transactions state and the users security level.  If the transaction is not considered final and the users security level allows it, the transaction should appear as a form.  If not the user just sees a read only screen.

For each transaction I have a single JSP (and would like to keep it that way)

EX:
transaction_a.jsp
[ADDRESS]
[DATE]
[ADDRESS]
[DATE]

transaction_b.jsp
[ADDRESS]
[TEXT]
[DATE]

I want to have a view selector jsp that sits between each component and its views.

tiles-def file:
<definition name=".output_selector" template=".../output_selector.jsp"/>
<definition name=".text" extends=".output_selector">
        <put-attribute name="dataEntry" value=".../data_entry/text.jsp"/>
        <put-attribute name="readOnly"  value=".../read_only/text.jsp"/>
</definition>
<definition name=".date" extends=".output_selector">
        <put-attribute name="dataEntry" value=".../data_entry/date.jsp"/>
        <put-attribute name="readOnly"  value=".../read_only/date.jsp"/>
</definition>

Going back to my transaction_b.jsp it would look like
...
<t:insertDefinition name=".text" >
        <t:putAttribute name="property"  value="votingPercentageAcquired" />
        <t:putAttribute name="labelKey"  value="label.votingPrecentageAcquired"/>
        <t:putAttribute name="size"      value="3"/>
        <t:putAttribute name="maxlength" value="3"/>
</t:insertDefinition>
<t:insertDefinition name=".date" >
        <t:putAttribute name="property"  value="effectiveDate" />
        <t:putAttribute name="labelKey"  value="label.effectiveDate"/>
        <t:putAttribute name="format"    value="MM/dd/yyyy"/>
</t:insertDefinition>

This would go to the view selector that would determine the format and then insert the correct view.  The correct view would need all of the attributes.  For the text it needs field, property, labelKey, size, & maxlength.  For the date it needs property, labelKey, and format.

As you can see, the view_selector can not make any assumptions about what properties to pass along, its job is just to select the view and pass along everything to it.  Every view that uses it has different attributes.

output_selector:
...select approprate view...
<tiles:insertAttribute name="${approprateView}">
        pass everything along to this view...either one by one or all at once
</tiles>
JRD wrote:
We are migrating an app from Struts1/Tiles1 to Struts2/Tiles2

We have a bunch of different transactions types that all collect similar data (Addresses, dates, text inputs, etc...).  We use tiles as a view controller (among other things).

So for each thing we want to display we would have a read-only and a data-entry display.  The view controller would use state and security to determine what view was appropriate, and then pass along all of the original data passed in to the correct view.

In Tiles 1 our view controller looked like this:

<c:set var="tilesKey" value="org.apache.struts.taglib.tiles.CompContext"/>
<cw:set var="theTiles" bean="${tilesKey}"/>


...select view...

<tiles:insert definition="${definition}">
        <tiles:put name="viewFormat" value="${viewFormat}"/>
        <c:forEach items="${theTiles.attributeNames}" var="attribute">
                <tiles:put name="${attribute}"><tiles:getAsString name="${attribute}"/></tiles:put>
        </c:forEach>

</tiles:insert>

The view selector can not know what attributes to pass along since each thing we want to display has different attributes.  Any idea how to do this in Tiles 2?

Thanks in advance,
Jonathan

Re: Iterate through Attributes

by Antonio Petrelli-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2008/4/15, JRD <danger_jon@...>:
>
> <t:insertDefinition name=".date" >
>         <t:putAttribute name="property"  value="effectiveDate" />
>         <t:putAttribute name="labelKey"  value="label.effectiveDate"/>
>         <t:putAttribute name="format"    value="MM/dd/yyyy"/>
> </t:insertDefinition>



I think you've gone too far the intention of Tiles: it seems like a job for
a custom component of Struts 2, or even a normal component.

Antonio

Re: Iterate through Attributes

by JRD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I don't really see it that way.  To me this is the exact intention of Tiles.  From my perspective you have two ways of building a UI that has both dataEntry & readOnly views of the same data.  You can have struts make the call which one to show or you can leave it to Tiles.  I think the tiles approach is far superior.  You only have to build and maintain one page for each object.  The objects in that page are basically abstracted into sub tiles which guarantees a uniform look across the system.  If you need to make a change you make it in exactly one place.  All of this really adds up when you have a lot of these objects in your system.

I was able to get what I wanted by making my own tag.  I'm not happy doing it as now I need to be careful with Tiles if I want to upgrade but not having this feature is sort of a show-stopper.

public class TilesAttributesTag extends AttributeTagSupport {

        private String var = null;
        public String getVar() { return var; }
        public void setVar(String var) { this.var = var; }

        @Override
        public void execute() throws JspException, IOException {
                Map<String, String> names = new HashMap<String, String>();
                for (Iterator i = attributeContext.getAttributeNames(); i.hasNext();) {
                        String name = (String) i.next();
                        Attribute attr = attributeContext.getAttribute(name);
                        names.put(name, attr.getValue().toString());
                }
                pageContext.setAttribute(getVar(), names);
        }
       
        @Override
        public void release() {
                super.release();
                var = null;
        }
}

and then my view selector

<e:attributeNames var="attributes"/>
<t:insertAttribute name="${format}">
        <c:forEach items="${attributes}" var="attribute">
                <t:putAttribute name="${attribute.key}" value="${attribute.value}"/>
        </c:forEach>
</t:insertAttribute>

I do think this functionality should be offered out of the box.  I read that you were working on cascading properties which sounds like it would solve my problem depending on the implementation.  If you just took everything out of the parents attributeContext and put it into the new attributeContext it should be ok.

Let me know what you think,
Jonathan

Antonio Petrelli-3 wrote:
2008/4/15, JRD <danger_jon@hotmail.com>:
>
> <t:insertDefinition name=".date" >
>         <t:putAttribute name="property"  value="effectiveDate" />
>         <t:putAttribute name="labelKey"  value="label.effectiveDate"/>
>         <t:putAttribute name="format"    value="MM/dd/yyyy"/>
> </t:insertDefinition>



I think you've gone too far the intention of Tiles: it seems like a job for
a custom component of Struts 2, or even a normal component.

Antonio

Re: Iterate through Attributes

by Antonio Petrelli-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2008/4/16, JRD <danger_jon@...>:
>
>
> I don't really see it that way.  To me this is the exact intention of
> Tiles.
> From my perspective you have two ways of building a UI that has both
> dataEntry & readOnly views of the same data.  You can have struts make the
> call which one to show or you can leave it to Tiles.  I think the tiles
> approach is far superior.



Well... you are not too much wrong :-D Anyway Struts 2 gives you a lot of
ways for customizing your components, even with parameters and little
tricks. See:
http://www.vitarara.org/cms/struts_2_cookbook/creating_a_ui_component


I was able to get what I wanted by making my own tag.  I'm not happy doing
> it as now I need to be careful with Tiles if I want to upgrade but not
> having this feature is sort of a show-stopper.
>
> public class TilesAttributesTag extends AttributeTagSupport {
> ...



Uh wait, you can use the <tiles:importAttribute> tag without the "name"
parameter for this:
http://tiles.apache.org/2.0/framework/tiles-jsp/tlddoc/tiles/importAttribute.html

I read that
> you were working on cascading properties which sounds like it would solve
> my
> problem depending on the implementation.  If you just took everything out
> of
> the parents attributeContext and put it into the new attributeContext it
> should be ok.



You can play with cascading attributes right now, I published a snapshot of
Tiles 2.1.0:
http://people.apache.org/repo/m2-snapshot-repository/

HTH
Antonio

Re: Iterate through Attributes

by Antonio Petrelli-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2008/4/15, JRD <danger_jon@...>:
>  <tiles:insert definition="${definition}">
>         <tiles:put name="viewFormat" value="${viewFormat}"/>
>         <c:forEach items="${theTiles.attributeNames}" var="attribute">
>                 <tiles:put name="${attribute}"><tiles:getAsString
>  name="${attribute}"/></tiles:put>
>         </c:forEach>
>  </tiles:insert>

About this particular piece of code (once translated to Tiles 2 tags),
it does not work since the <tiles:getAsString> tag is inside a
<tiles:insertDefinition> tag, that creates a new attribute context.
I am trying to understand if it can be corrected or not (in the sense
that this behaviour is correct). I think it is a bug, but I am trying
to understand what is the best way to fix it, without adding too much
complexity.

Antonio

RE: Iterate through Attributes

by JRD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Yes, in my last message I did the following
 
<e:attributeNames var="attributes"/><t:insertAttribute name="${format}">    <c:forEach items="${attributes}" var="attribute">        <t:putAttribute name="${attribute.key}" value="${attribute.value}"/>    </c:forEach></t:insertAttribute>



> Date: Wed, 16 Apr 2008 17:11:21 +0200> From: antonio.petrelli@...> To: users@...> Subject: Re: Iterate through Attributes> > 2008/4/15, JRD <danger_jon@...>:> > <tiles:insert definition="${definition}">> > <tiles:put name="viewFormat" value="${viewFormat}"/>> > <c:forEach items="${theTiles.attributeNames}" var="attribute">> > <tiles:put name="${attribute}"><tiles:getAsString> > name="${attribute}"/></tiles:put>> > </c:forEach>> > </tiles:insert>> > About this particular piece of code (once translated to Tiles 2 tags),> it does not work since the <tiles:getAsString> tag is inside a> <tiles:insertDefinition> tag, that creates a new attribute context.> I am trying to understand if it can be corrected or not (in the sense> that this behaviour is correct). I think it is a bug, but I am trying> to understand what is the best way to fix it, without adding too much> complexity.> > Antonio
_________________________________________________________________
Get in touch in an instant. Get Windows Live Messenger now.
http://www.windowslive.com/messenger/overview.html?ocid=TXT_TAGLM_WL_Refresh_getintouch_042008

Re: Iterate through Attributes

by Antonio Petrelli-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2008/4/16, Jonathan DeRose <danger_jon@...>:
>
> Yes, in my last message I did the following
>
>
> <e:attributeNames var="attributes"/><t:insertAttribute
> name="${format}">    <c:forEach items="${attributes}"
> var="attribute">        <t:putAttribute name="${attribute.key}"
> value="${attribute.value}"/>    </c:forEach></t:insertAttribute>



Yeah, I understood it :-)
But in fact the discussion parted in two: a possible bug and the best way
for creating custom components (with or without Tiles?). I answered to both,
but in two e-mails (sorry).

Antonio

RE: Iterate through Attributes

by JRD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The importAttribute tag takes everything in the context and puts them individually into page scope.  That doesn't help me since I need to pass along whatever was passed to me.  I wouldn't know what was in page scope that was passed in vs. what was there from other processing.  My tag gets a handle on the AttributeContext and stores the attributes as a map in page scope.  I then use that map to pass along the exact parameters passed in.
 
When will 2.1.0 be out?  And what scheme did you use for cascading?  Do you copy all attributes into the child context upon creation? Or does the inserting def select the ones it wants.



> Date: Wed, 16 Apr 2008 17:08:37 +0200> From: antonio.petrelli@...> To: users@...> Subject: Re: Iterate through Attributes> > 2008/4/16, JRD <danger_jon@...>:> >> >> > I don't really see it that way. To me this is the exact intention of> > Tiles.> > From my perspective you have two ways of building a UI that has both> > dataEntry & readOnly views of the same data. You can have struts make the> > call which one to show or you can leave it to Tiles. I think the tiles> > approach is far superior.> > > > Well... you are not too much wrong :-D Anyway Struts 2 gives you a lot of> ways for customizing your components, even with parameters and little> tricks. See:> http://www.vitarara.org/cms/struts_2_cookbook/creating_a_ui_component> > > I was able to get what I wanted by making my own tag. I'm not happy doing> > it as now I need to be careful with Tiles if I want to upgrade but not> > having this feature is sort of a show-stopper.> >> > public class TilesAttributesTag extends AttributeTagSupport {> > ...> > > > Uh wait, you can use the <tiles:importAttribute> tag without the "name"> parameter for this:> http://tiles.apache.org/2.0/framework/tiles-jsp/tlddoc/tiles/importAttribute.html> > I read that> > you were working on cascading properties which sounds like it would solve> > my> > problem depending on the implementation. If you just took everything out> > of> > the parents attributeContext and put it into the new attributeContext it> > should be ok.> > > > You can play with cascading attributes right now, I published a snapshot of> Tiles 2.1.0:> http://people.apache.org/repo/m2-snapshot-repository/> > HTH> Antonio
_________________________________________________________________
Pack up or back up–use SkyDrive to transfer files or keep extra copies. Learn how.
http://www.windowslive.com/skydrive/overview.html?ocid=TXT_TAGLM_WL_Refresh_skydrive_packup_042008

Re: Iterate through Attributes

by Antonio Petrelli-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2008/4/16, Jonathan DeRose <danger_jon@...>:
> The importAttribute tag takes everything in the context and puts them individually into page scope.

If you use the "toScope" attribute with a value of "request", the
attribute will be put in request scope.

>  When will 2.1.0 be out?

It's hard to say, we have no schedule.

>  And what scheme did you use for cascading?  Do you copy all attributes into the child context upon creation? Or does the inserting def select the ones it wants.

Not exactly. If you want to cascade an attribute, use <put-attribute
cascade="true"> or <tiles:putAttribute cascade="true" />, the
attribute will be cascaded to inner definitions/templates.
Cascaded attributes are managed separately from not-cascaded, with a
precedence to not-cascaded ones. Cascaded attributes are copied from a
context to the inner.

Antonio

RE: Iterate through Attributes

by JRD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ok, I will keep an eye out for 2.1 then.  Do you know if no schedule = weeks or months.  For now I will stick with my tag approach.  These attributes really belong to the tiles context and I need to make sure they are limited to that.  Otherwise I open myself up to finding some property in the request that was set by a earlier tile that shouldn't apply to the current one being rendered.
 
I think even with the cascading values I would recommend adding the functionality to importAttributeTag where if you don't specify a name but you do specify a toName that you put either the attributeContext or a map of the attributeContext values in that toName in the scope specified.
 
Jonathan
 
 



> Date: Wed, 16 Apr 2008 21:00:43 +0200> From: antonio.petrelli@...> To: users@...> Subject: Re: Iterate through Attributes> > 2008/4/16, Jonathan DeRose <danger_jon@...>:> > The importAttribute tag takes everything in the context and puts them individually into page scope.> > If you use the "toScope" attribute with a value of "request", the> attribute will be put in request scope.> > > When will 2.1.0 be out?> > It's hard to say, we have no schedule.> > > And what scheme did you use for cascading? Do you copy all attributes into the child context upon creation? Or does the inserting def select the ones it wants.> > Not exactly. If you want to cascade an attribute, use <put-attribute> cascade="true"> or <tiles:putAttribute cascade="true" />, the> attribute will be cascaded to inner definitions/templates.> Cascaded attributes are managed separately from not-cascaded, with a> precedence to not-cascaded ones. Cascaded attributes are copied from a> context to the inner.> > Antonio
_________________________________________________________________
Use video conversation to talk face-to-face with Windows Live Messenger.
http://www.windowslive.com/messenger/connect_your_way.html?ocid=TXT_TAGLM_WL_Refresh_messenger_video_042008

Re: Iterate through Attributes

by Antonio Petrelli-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2008/4/16, Jonathan DeRose <danger_jon@...>:
>
> Do you know if no schedule = weeks or months.



It does not make sense: no schedule means "absolutely" no schedule. We are
volunteers, and we update the software in our spare time. It could mean
weeks, months, years, who knows :-) It all depends on the will of the
developers (committers and contributors).
If you want a faster release, help with the development by providing
patches. This is the list of open issues for 2.1.x:
https://issues.apache.org/struts/secure/IssueNavigator.jspa?reset=true&&pid=10160&resolution=-1&fixfor=21820&sorter/field=priority&sorter/order=DESC

I think even with the cascading values I would recommend adding the
> functionality to importAttributeTag where if you don't specify a name but
> you do specify a toName that you put either the attributeContext or a map of
> the attributeContext values in that toName in the scope specified.



This is definitely a Tiles development question. Please write to the Tiles
Developers list:
http://tiles.apache.org/mail-lists.html

Thanks
Antonio