You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tiles.apache.org by mck <mc...@semb.wever.org> on 2015/07/08 09:18:52 UTC

Re: Pull Request #4: Object-Type Attribute Value Evaluation

Sorry for my very late reply. It's been a bit chaotic of late.

> - All other tags in tiles-defs.xml require the developer to specify
> explicitely that she wants the expression evaluated: <add-attribute
> expression="${customer.id}"/> instead of <add-attribute value="Customer
> ID"/>. Doing differently for <item> would make this XML even more
> confusing that it already is.


Brett, why were you using <item> instead of <put-attribute> inside the
<put-list-attribute> ?
Is it only because you want two values? (ie value and link)

Could there be other ways to solve this with tags that are supported in
tiles-3

For example something like…

    <put-list-attribute name="breadcrumbs">
      <add-list-attribute name="customer.id">
        <add-attribute expression="${customer.id}" />
        <add-attribute
        expression="/customers/${customer.id}/salesOrders" />
      </add-list-attribute>
      <add-list-attribute name="order.id">
        <add-attribute expression="${order.id}" />
        <add-attribute
        expression="/customers/${customer.id}/salesOrders" />
      </add-list-attribute>
    </put-list-attribute>


> - Do we want to keep maintaining <item> and <bean>, given that today DI
> frameworks provide several better ways to declare those beans? 

Not for example if approaches like i wrote above are a satisfactory
solution.

~mck
 

Re: Pull Request #4: Object-Type Attribute Value Evaluation

Posted by Nicolas Le Bas <ma...@nlebas.net>.
Oh... I didn't even see that one.
Thanks for the heads up, I'll look at it.

On 15-07-16 08:13 AM, Brett Ryan wrote:
> 
>> On 16 Jul 2015, at 22:00, Nicolas Le Bas <ma...@nlebas.net> wrote:
>>
>> I see.
>> So basically you like to use tiles as some kind of Domain Specific
>> Langage for your views.
>>
>> What if we add support for something like raw data for an attribute,
>> that would be translated into a Map for rendering?
>>
>> Something like:
>>  <definition name="customers/info" extends="customers/base">
>>    <put-list-attribute name="body" cascade="true" inherit="true">
>>      <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" />
>>    </put-list-attribute>
>>    <put-xml-attribute name="breadcrumbs" cascade="true" inherit="true">
>>      <breadcrumbs>
>>        <link href="/customers/${customer.id}">${customer.id}</link>
>>        <link href="/customers/${customer.id}/salesOrders">Orders</link>
>>        <link
>> href="/customers/${customer.id}/salesOrders/${order.id}">${order.id}</link>
>>      </breadcrumbs>
>>    </put-xml-attribute>
>>  </definition>
>>
>> I think most of the pieces to support it are already there:
>> - we already have support for evaluating the expressions at runtime.
>> - we can find libraries out there that translate XML into a usable map
>> structure (xstream?)
>>
>> The only thing that worries me is whether the good old digester would
>> accept to release control of the parsing and let us access the whole
>> body of put-xml-attribute, or if we would have to rewrite
>> DigesterDefinitionsReader. I'm not sure there.
>>
>> How does that sound? What do you think?
> 
> It's certainly a flexible approach that could prove useful, I am ok with the add-list-attribute mck suggested which works as advertised, I made pull request #5 (https://github.com/apache/tiles/pull/5) which adds expression support to list attributes, mck made some requests before accepting but the logic I think is sound.
> 
> Btw, the example I submitted works in the current release of tiles withe the exception of expression evaluation which #5 addresses.
> 
> All in all we can probably close this pull request and concentrate instead on #5.
> 
>> Nick.
>>
>>> On 15-07-14 10:18 PM, Brett Ryan wrote:
>>>
>>>> On 15 Jul 2015, at 11:53, Nicolas Le Bas <ma...@nlebas.net> wrote:
>>>>
>>>> Hi all,
>>>>
>>>> First of all, I take responsibility for cross posting to the dev list.
>>>> Sorry if it surprised you, Brett, I just feel it is a better place to
>>>> discuss code changes. People come here with a different mindset.
>>>
>>> My bad actually, I should have realised there was a dev@ list, I subscribed to users@ years ago and didn't bother to check when submitting patches.
>>>
>>>> And sorry for the delay in my answer, too. We're all volunteers here :)
>>>> As a consequence, it will be a long answer, and I feel like apologizing
>>>> again.
>>>
>>> Hah, it's cool :) I've been unwell and unable to finalise a solution to mck's requests, I was hoping to resume on the weekend but have been bed-ridden and can't think properly. It happens, what ya gonna do?
>>>
>>>> Concerning a universal solution to Brett's problem: well, here's what
>>>> I've been doing for the past years. I do not pretend it is better, just
>>>> that I like it:
>>>>
>>>>
>>>> I find, like Brett, that the "JavaBeans" tags from struts-tiles (item
>>>> and bean) are limited in nature. In my experience I only encountered two
>>>> situtations were they were useful, and in both situations I've found
>>>> other solutions to be more effective and maintainable.
>>>>
>>>>
>>>> 1. The static approach
>>>> I like the pure HTML+CSS solution to this: <ul><li>My Account</li><li>My
>>>> Orders</li></ul>. It looks and lives well within the template itself.
>>>>
>>>> 2. The dynamic list.
>>>> In most cases, I find it more convenient to add a bean into the
>>>> appropriate context through the application. For instance, with spring:
>>>>
>>>> <util:list id="breadcrumbsData">
>>>>  <bean class="example.Link" p:value="#{customer.id}"
>>>> p:link="/customers/#{customer.id}" />
>>>>  <bean class="example.Link" p:value="Orders"
>>>> p:link="/customers/#{customer.id}/salesOrders" />
>>>>  <bean class="example.Link" p:value="#{order.id}"
>>>> p:link="/customers/#{customer.id}/salesOrders/#{order.id}" />
>>>> </util:list>
>>>>
>>>> And then in tiles:
>>>>   <put-attribute name="breadcrumbs" expression="${breadcrumbsData}"/>
>>>>
>>>> I find this "breadcrumbsData" tends to evolve over the life of the
>>>> application into something more and more dynamic, for instance session
>>>> specific or requires a data model more complex than the <item>-type of
>>>> thing. Sometimes it is also more convenient to create the list by hand
>>>> and add it to the session/servlet context programatically.
>>>
>>> I'm trying to remove things like this as much as possible from the application context and defer to tiles as it's a lot less work. Consider this in my template:
>>>
>>>    <tiles:importAttribute name="breadcrumbs" ignore="true"/>
>>>    <ol class="breadcrumb">
>>>      <c:forEach var="item" items="${breadcrumbs}" varStatus="vs">
>>>        <li class="${vs.last ? 'active' : ''}">
>>>          <c:choose>
>>>            <c:when test="${vs.last}">
>>>              <c:out value="${item[0]}"/>
>>>            </c:when>
>>>            <c:otherwise>
>>>              <a href="<c:url value="${item[1]}"/>"><c:out value="${item[0]}"/></a>
>>>            </c:otherwise>
>>>          </c:choose>
>>>        </li>
>>>      </c:forEach>
>>>    </ol>
>>>
>>> Now with this I can opt-in to providing crumbs in many different views, which can be completely dynamic and inheritable by tiles. Consider the customers crumbs I've been using, note that this has been changed from using the "<item/>" version to using nested <add-attribute/> values, though I've raised a new pull-request that I need to alter which provides expression support as it's not presently available.
>>>
>>>  <definition name="customers/base" extends="customers/none">
>>>    <put-attribute name="title" cascade="true" expression="${customer.sortName} (${customer.id})" />
>>>    <put-list-attribute name="body" cascade="true">
>>>      <add-attribute value="/WEB-INF/views/customers/menu-tabs.jsp"/>
>>>    </put-list-attribute>
>>>    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>>>      <add-list-attribute>
>>>        <add-attribute value="Customers"/>
>>>        <add-attribute value="/customers"/>
>>>      </add-list-attribute>
>>>    </put-list-attribute>
>>>  </definition>
>>>
>>>  <definition name="customers/info" extends="customers/base">
>>>    <put-list-attribute name="body" cascade="true" inherit="true">
>>>      <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" />
>>>    </put-list-attribute>
>>>    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>>>      <add-list-attribute>
>>>        <add-attribute expression="${customer.id}"/>
>>>        <add-attribute expression="/customers/${customer.country}/${customer.id}/info"/>
>>>      </add-list-attribute>
>>>    </put-list-attribute>
>>>  </definition>
>>>
>>>  <definition name="orders/view" extends="customers/base">
>>>    <put-list-attribute name="body" cascade="true" inherit="true">
>>>      <add-attribute value="/WEB-INF/views/customers/cust-salesOrder.jsp" />
>>>    </put-list-attribute>
>>>    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>>>      <add-list-attribute>
>>>        <add-attribute expression="${customer.id}"/>
>>>        <add-attribute expression="/customers/${customer.id}/info"/>
>>>      </add-list-attribute>
>>>      <add-list-attribute>
>>>        <add-attribute value="Orders"/>
>>>        <add-attribute expression="/customers/${customer.country}/${customer.id}/salesOrders"/>
>>>      </add-list-attribute>
>>>      <add-list-attribute>
>>>        <add-attribute expression="${salesOrder.id}"/>
>>>        <add-attribute expression="/customers/${customer.country}/${customer.id}/salesOrders/${salesOrder.id}"/>
>>>      </add-list-attribute>
>>>    </put-list-attribute>
>>>  </definition>
>>>
>>> Note here how now my spring controllers need to know nothing about the breadcrumbs. In fact the only thing that knows about them is the view and the view composition, which I believe is the whole point of a framework like tiles, being able to decouple your composition from your controllers, which is what I love about tiles.
>>>
>>>
>>>
>>>> I used the tiles-centric solution back at the time when CSS and DI were
>>>> barely budding, and their long-term adoption was still questionable, but
>>>> now I prefer other ways. That being said, I'm totally open to
>>>> contributions that would be useful to others.
>>>>
>>>>
>>>>
>>>>
>>>> Concerning the documentation: I totally agree it needs work, there's a
>>>> ramp up to learning Tiles 3. Initialization is cumbersome, and as we
>>>> discussed earlier, the duality between "value" and "expression" is
>>>> confusing. All of this is documented on the website, but the docs are
>>>> dry and learning is difficult. Perhaps we could rework the tutorials and
>>>> update the examples. Another dark area is: how to test?
>>>
>>> Would love to help, I've been using tiles for some years and myself only stumble onto 3 specific features when I find them, so I don't "know it all", but I'd be more than happy to help contribute to docs.
>>>
>>>> That being said, my time being limited, I prefer to invest it in
>>>> simplifying the usage of tiles before documenting the simple solution,
>>>> as opposed to trying to explain the complex solution in a clear way.
>>>
>>> I would tend to agree, and considering it's been that way for a while, maybe that's the right approach. Though, how long would the simplified solution take to implement?
>>>
>>>> So personnally I'm looking at reviewing the docs when tiles can be
>>>> configured from DI, and run in junit (tiles 3.1, perhaps. My github fork
>>>> already has the junit part working, and I'm experimenting with DI).
>>>>
>>>> Cheers!
>>>>
>>>> Nick
>>>>
>>>> PS: On 15-07-08 09:21 AM, Brett Ryan wrote:
>>>>> toString should always be a string representation of a value, not
>>>> null, alternatives would be "null" or "(null)".
>>>>
>>>> +1, definitely
>>>

Re: Pull Request #4: Object-Type Attribute Value Evaluation

Posted by Brett Ryan <br...@gmail.com>.
> On 16 Jul 2015, at 22:00, Nicolas Le Bas <ma...@nlebas.net> wrote:
> 
> I see.
> So basically you like to use tiles as some kind of Domain Specific
> Langage for your views.
> 
> What if we add support for something like raw data for an attribute,
> that would be translated into a Map for rendering?
> 
> Something like:
>  <definition name="customers/info" extends="customers/base">
>    <put-list-attribute name="body" cascade="true" inherit="true">
>      <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" />
>    </put-list-attribute>
>    <put-xml-attribute name="breadcrumbs" cascade="true" inherit="true">
>      <breadcrumbs>
>        <link href="/customers/${customer.id}">${customer.id}</link>
>        <link href="/customers/${customer.id}/salesOrders">Orders</link>
>        <link
> href="/customers/${customer.id}/salesOrders/${order.id}">${order.id}</link>
>      </breadcrumbs>
>    </put-xml-attribute>
>  </definition>
> 
> I think most of the pieces to support it are already there:
> - we already have support for evaluating the expressions at runtime.
> - we can find libraries out there that translate XML into a usable map
> structure (xstream?)
> 
> The only thing that worries me is whether the good old digester would
> accept to release control of the parsing and let us access the whole
> body of put-xml-attribute, or if we would have to rewrite
> DigesterDefinitionsReader. I'm not sure there.
> 
> How does that sound? What do you think?

It's certainly a flexible approach that could prove useful, I am ok with the add-list-attribute mck suggested which works as advertised, I made pull request #5 (https://github.com/apache/tiles/pull/5) which adds expression support to list attributes, mck made some requests before accepting but the logic I think is sound.

Btw, the example I submitted works in the current release of tiles withe the exception of expression evaluation which #5 addresses.

All in all we can probably close this pull request and concentrate instead on #5.

> Nick.
> 
>> On 15-07-14 10:18 PM, Brett Ryan wrote:
>> 
>>> On 15 Jul 2015, at 11:53, Nicolas Le Bas <ma...@nlebas.net> wrote:
>>> 
>>> Hi all,
>>> 
>>> First of all, I take responsibility for cross posting to the dev list.
>>> Sorry if it surprised you, Brett, I just feel it is a better place to
>>> discuss code changes. People come here with a different mindset.
>> 
>> My bad actually, I should have realised there was a dev@ list, I subscribed to users@ years ago and didn't bother to check when submitting patches.
>> 
>>> And sorry for the delay in my answer, too. We're all volunteers here :)
>>> As a consequence, it will be a long answer, and I feel like apologizing
>>> again.
>> 
>> Hah, it's cool :) I've been unwell and unable to finalise a solution to mck's requests, I was hoping to resume on the weekend but have been bed-ridden and can't think properly. It happens, what ya gonna do?
>> 
>>> Concerning a universal solution to Brett's problem: well, here's what
>>> I've been doing for the past years. I do not pretend it is better, just
>>> that I like it:
>>> 
>>> 
>>> I find, like Brett, that the "JavaBeans" tags from struts-tiles (item
>>> and bean) are limited in nature. In my experience I only encountered two
>>> situtations were they were useful, and in both situations I've found
>>> other solutions to be more effective and maintainable.
>>> 
>>> 
>>> 1. The static approach
>>> I like the pure HTML+CSS solution to this: <ul><li>My Account</li><li>My
>>> Orders</li></ul>. It looks and lives well within the template itself.
>>> 
>>> 2. The dynamic list.
>>> In most cases, I find it more convenient to add a bean into the
>>> appropriate context through the application. For instance, with spring:
>>> 
>>> <util:list id="breadcrumbsData">
>>>  <bean class="example.Link" p:value="#{customer.id}"
>>> p:link="/customers/#{customer.id}" />
>>>  <bean class="example.Link" p:value="Orders"
>>> p:link="/customers/#{customer.id}/salesOrders" />
>>>  <bean class="example.Link" p:value="#{order.id}"
>>> p:link="/customers/#{customer.id}/salesOrders/#{order.id}" />
>>> </util:list>
>>> 
>>> And then in tiles:
>>>   <put-attribute name="breadcrumbs" expression="${breadcrumbsData}"/>
>>> 
>>> I find this "breadcrumbsData" tends to evolve over the life of the
>>> application into something more and more dynamic, for instance session
>>> specific or requires a data model more complex than the <item>-type of
>>> thing. Sometimes it is also more convenient to create the list by hand
>>> and add it to the session/servlet context programatically.
>> 
>> I'm trying to remove things like this as much as possible from the application context and defer to tiles as it's a lot less work. Consider this in my template:
>> 
>>    <tiles:importAttribute name="breadcrumbs" ignore="true"/>
>>    <ol class="breadcrumb">
>>      <c:forEach var="item" items="${breadcrumbs}" varStatus="vs">
>>        <li class="${vs.last ? 'active' : ''}">
>>          <c:choose>
>>            <c:when test="${vs.last}">
>>              <c:out value="${item[0]}"/>
>>            </c:when>
>>            <c:otherwise>
>>              <a href="<c:url value="${item[1]}"/>"><c:out value="${item[0]}"/></a>
>>            </c:otherwise>
>>          </c:choose>
>>        </li>
>>      </c:forEach>
>>    </ol>
>> 
>> Now with this I can opt-in to providing crumbs in many different views, which can be completely dynamic and inheritable by tiles. Consider the customers crumbs I've been using, note that this has been changed from using the "<item/>" version to using nested <add-attribute/> values, though I've raised a new pull-request that I need to alter which provides expression support as it's not presently available.
>> 
>>  <definition name="customers/base" extends="customers/none">
>>    <put-attribute name="title" cascade="true" expression="${customer.sortName} (${customer.id})" />
>>    <put-list-attribute name="body" cascade="true">
>>      <add-attribute value="/WEB-INF/views/customers/menu-tabs.jsp"/>
>>    </put-list-attribute>
>>    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>>      <add-list-attribute>
>>        <add-attribute value="Customers"/>
>>        <add-attribute value="/customers"/>
>>      </add-list-attribute>
>>    </put-list-attribute>
>>  </definition>
>> 
>>  <definition name="customers/info" extends="customers/base">
>>    <put-list-attribute name="body" cascade="true" inherit="true">
>>      <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" />
>>    </put-list-attribute>
>>    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>>      <add-list-attribute>
>>        <add-attribute expression="${customer.id}"/>
>>        <add-attribute expression="/customers/${customer.country}/${customer.id}/info"/>
>>      </add-list-attribute>
>>    </put-list-attribute>
>>  </definition>
>> 
>>  <definition name="orders/view" extends="customers/base">
>>    <put-list-attribute name="body" cascade="true" inherit="true">
>>      <add-attribute value="/WEB-INF/views/customers/cust-salesOrder.jsp" />
>>    </put-list-attribute>
>>    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>>      <add-list-attribute>
>>        <add-attribute expression="${customer.id}"/>
>>        <add-attribute expression="/customers/${customer.id}/info"/>
>>      </add-list-attribute>
>>      <add-list-attribute>
>>        <add-attribute value="Orders"/>
>>        <add-attribute expression="/customers/${customer.country}/${customer.id}/salesOrders"/>
>>      </add-list-attribute>
>>      <add-list-attribute>
>>        <add-attribute expression="${salesOrder.id}"/>
>>        <add-attribute expression="/customers/${customer.country}/${customer.id}/salesOrders/${salesOrder.id}"/>
>>      </add-list-attribute>
>>    </put-list-attribute>
>>  </definition>
>> 
>> Note here how now my spring controllers need to know nothing about the breadcrumbs. In fact the only thing that knows about them is the view and the view composition, which I believe is the whole point of a framework like tiles, being able to decouple your composition from your controllers, which is what I love about tiles.
>> 
>> 
>> 
>>> I used the tiles-centric solution back at the time when CSS and DI were
>>> barely budding, and their long-term adoption was still questionable, but
>>> now I prefer other ways. That being said, I'm totally open to
>>> contributions that would be useful to others.
>>> 
>>> 
>>> 
>>> 
>>> Concerning the documentation: I totally agree it needs work, there's a
>>> ramp up to learning Tiles 3. Initialization is cumbersome, and as we
>>> discussed earlier, the duality between "value" and "expression" is
>>> confusing. All of this is documented on the website, but the docs are
>>> dry and learning is difficult. Perhaps we could rework the tutorials and
>>> update the examples. Another dark area is: how to test?
>> 
>> Would love to help, I've been using tiles for some years and myself only stumble onto 3 specific features when I find them, so I don't "know it all", but I'd be more than happy to help contribute to docs.
>> 
>>> That being said, my time being limited, I prefer to invest it in
>>> simplifying the usage of tiles before documenting the simple solution,
>>> as opposed to trying to explain the complex solution in a clear way.
>> 
>> I would tend to agree, and considering it's been that way for a while, maybe that's the right approach. Though, how long would the simplified solution take to implement?
>> 
>>> So personnally I'm looking at reviewing the docs when tiles can be
>>> configured from DI, and run in junit (tiles 3.1, perhaps. My github fork
>>> already has the junit part working, and I'm experimenting with DI).
>>> 
>>> Cheers!
>>> 
>>> Nick
>>> 
>>> PS: On 15-07-08 09:21 AM, Brett Ryan wrote:
>>>> toString should always be a string representation of a value, not
>>> null, alternatives would be "null" or "(null)".
>>> 
>>> +1, definitely
>> 

Re: Pull Request #4: Object-Type Attribute Value Evaluation

Posted by Nicolas Le Bas <ma...@nlebas.net>.
I see.
So basically you like to use tiles as some kind of Domain Specific
Langage for your views.

What if we add support for something like raw data for an attribute,
that would be translated into a Map for rendering?

Something like:
  <definition name="customers/info" extends="customers/base">
    <put-list-attribute name="body" cascade="true" inherit="true">
      <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" />
    </put-list-attribute>
    <put-xml-attribute name="breadcrumbs" cascade="true" inherit="true">
      <breadcrumbs>
        <link href="/customers/${customer.id}">${customer.id}</link>
        <link href="/customers/${customer.id}/salesOrders">Orders</link>
        <link
href="/customers/${customer.id}/salesOrders/${order.id}">${order.id}</link>
      </breadcrumbs>
    </put-xml-attribute>
  </definition>

I think most of the pieces to support it are already there:
- we already have support for evaluating the expressions at runtime.
- we can find libraries out there that translate XML into a usable map
structure (xstream?)

The only thing that worries me is whether the good old digester would
accept to release control of the parsing and let us access the whole
body of put-xml-attribute, or if we would have to rewrite
DigesterDefinitionsReader. I'm not sure there.

How does that sound? What do you think?

Nick.

On 15-07-14 10:18 PM, Brett Ryan wrote:
> 
>> On 15 Jul 2015, at 11:53, Nicolas Le Bas <ma...@nlebas.net> wrote:
>>
>> Hi all,
>>
>> First of all, I take responsibility for cross posting to the dev list.
>> Sorry if it surprised you, Brett, I just feel it is a better place to
>> discuss code changes. People come here with a different mindset.
> 
> My bad actually, I should have realised there was a dev@ list, I subscribed to users@ years ago and didn't bother to check when submitting patches.
> 
>> And sorry for the delay in my answer, too. We're all volunteers here :)
>> As a consequence, it will be a long answer, and I feel like apologizing
>> again.
> 
> Hah, it's cool :) I've been unwell and unable to finalise a solution to mck's requests, I was hoping to resume on the weekend but have been bed-ridden and can't think properly. It happens, what ya gonna do?
> 
>> Concerning a universal solution to Brett's problem: well, here's what
>> I've been doing for the past years. I do not pretend it is better, just
>> that I like it:
>>
>>
>> I find, like Brett, that the "JavaBeans" tags from struts-tiles (item
>> and bean) are limited in nature. In my experience I only encountered two
>> situtations were they were useful, and in both situations I've found
>> other solutions to be more effective and maintainable.
>>
>>
>> 1. The static approach
>> I like the pure HTML+CSS solution to this: <ul><li>My Account</li><li>My
>> Orders</li></ul>. It looks and lives well within the template itself.
>>
>> 2. The dynamic list.
>> In most cases, I find it more convenient to add a bean into the
>> appropriate context through the application. For instance, with spring:
>>
>> <util:list id="breadcrumbsData">
>>   <bean class="example.Link" p:value="#{customer.id}"
>> p:link="/customers/#{customer.id}" />
>>   <bean class="example.Link" p:value="Orders"
>> p:link="/customers/#{customer.id}/salesOrders" />
>>   <bean class="example.Link" p:value="#{order.id}"
>> p:link="/customers/#{customer.id}/salesOrders/#{order.id}" />
>> </util:list>
>>
>> And then in tiles:
>>    <put-attribute name="breadcrumbs" expression="${breadcrumbsData}"/>
>>
>> I find this "breadcrumbsData" tends to evolve over the life of the
>> application into something more and more dynamic, for instance session
>> specific or requires a data model more complex than the <item>-type of
>> thing. Sometimes it is also more convenient to create the list by hand
>> and add it to the session/servlet context programatically.
> 
> I'm trying to remove things like this as much as possible from the application context and defer to tiles as it's a lot less work. Consider this in my template:
> 
>     <tiles:importAttribute name="breadcrumbs" ignore="true"/>
>     <ol class="breadcrumb">
>       <c:forEach var="item" items="${breadcrumbs}" varStatus="vs">
>         <li class="${vs.last ? 'active' : ''}">
>           <c:choose>
>             <c:when test="${vs.last}">
>               <c:out value="${item[0]}"/>
>             </c:when>
>             <c:otherwise>
>               <a href="<c:url value="${item[1]}"/>"><c:out value="${item[0]}"/></a>
>             </c:otherwise>
>           </c:choose>
>         </li>
>       </c:forEach>
>     </ol>
> 
> Now with this I can opt-in to providing crumbs in many different views, which can be completely dynamic and inheritable by tiles. Consider the customers crumbs I've been using, note that this has been changed from using the "<item/>" version to using nested <add-attribute/> values, though I've raised a new pull-request that I need to alter which provides expression support as it's not presently available.
> 
>   <definition name="customers/base" extends="customers/none">
>     <put-attribute name="title" cascade="true" expression="${customer.sortName} (${customer.id})" />
>     <put-list-attribute name="body" cascade="true">
>       <add-attribute value="/WEB-INF/views/customers/menu-tabs.jsp"/>
>     </put-list-attribute>
>     <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>       <add-list-attribute>
>         <add-attribute value="Customers"/>
>         <add-attribute value="/customers"/>
>       </add-list-attribute>
>     </put-list-attribute>
>   </definition>
> 
>   <definition name="customers/info" extends="customers/base">
>     <put-list-attribute name="body" cascade="true" inherit="true">
>       <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" />
>     </put-list-attribute>
>     <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>       <add-list-attribute>
>         <add-attribute expression="${customer.id}"/>
>         <add-attribute expression="/customers/${customer.country}/${customer.id}/info"/>
>       </add-list-attribute>
>     </put-list-attribute>
>   </definition>
> 
>   <definition name="orders/view" extends="customers/base">
>     <put-list-attribute name="body" cascade="true" inherit="true">
>       <add-attribute value="/WEB-INF/views/customers/cust-salesOrder.jsp" />
>     </put-list-attribute>
>     <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
>       <add-list-attribute>
>         <add-attribute expression="${customer.id}"/>
>         <add-attribute expression="/customers/${customer.id}/info"/>
>       </add-list-attribute>
>       <add-list-attribute>
>         <add-attribute value="Orders"/>
>         <add-attribute expression="/customers/${customer.country}/${customer.id}/salesOrders"/>
>       </add-list-attribute>
>       <add-list-attribute>
>         <add-attribute expression="${salesOrder.id}"/>
>         <add-attribute expression="/customers/${customer.country}/${customer.id}/salesOrders/${salesOrder.id}"/>
>       </add-list-attribute>
>     </put-list-attribute>
>   </definition>
> 
> Note here how now my spring controllers need to know nothing about the breadcrumbs. In fact the only thing that knows about them is the view and the view composition, which I believe is the whole point of a framework like tiles, being able to decouple your composition from your controllers, which is what I love about tiles.
> 
> 
> 
>> I used the tiles-centric solution back at the time when CSS and DI were
>> barely budding, and their long-term adoption was still questionable, but
>> now I prefer other ways. That being said, I'm totally open to
>> contributions that would be useful to others.
>>
>>
>>
>>
>> Concerning the documentation: I totally agree it needs work, there's a
>> ramp up to learning Tiles 3. Initialization is cumbersome, and as we
>> discussed earlier, the duality between "value" and "expression" is
>> confusing. All of this is documented on the website, but the docs are
>> dry and learning is difficult. Perhaps we could rework the tutorials and
>> update the examples. Another dark area is: how to test?
> 
> Would love to help, I've been using tiles for some years and myself only stumble onto 3 specific features when I find them, so I don't "know it all", but I'd be more than happy to help contribute to docs.
> 
>> That being said, my time being limited, I prefer to invest it in
>> simplifying the usage of tiles before documenting the simple solution,
>> as opposed to trying to explain the complex solution in a clear way.
> 
> I would tend to agree, and considering it's been that way for a while, maybe that's the right approach. Though, how long would the simplified solution take to implement?
> 
>> So personnally I'm looking at reviewing the docs when tiles can be
>> configured from DI, and run in junit (tiles 3.1, perhaps. My github fork
>> already has the junit part working, and I'm experimenting with DI).
>>
>> Cheers!
>>
>> Nick
>>
>> PS: On 15-07-08 09:21 AM, Brett Ryan wrote:
>>> toString should always be a string representation of a value, not
>> null, alternatives would be "null" or "(null)".
>>
>> +1, definitely
>>
>>
>>
>>
>>
> 

Re: Pull Request #4: Object-Type Attribute Value Evaluation

Posted by Brett Ryan <br...@gmail.com>.
> On 15 Jul 2015, at 11:53, Nicolas Le Bas <ma...@nlebas.net> wrote:
> 
> Hi all,
> 
> First of all, I take responsibility for cross posting to the dev list.
> Sorry if it surprised you, Brett, I just feel it is a better place to
> discuss code changes. People come here with a different mindset.

My bad actually, I should have realised there was a dev@ list, I subscribed to users@ years ago and didn't bother to check when submitting patches.

> And sorry for the delay in my answer, too. We're all volunteers here :)
> As a consequence, it will be a long answer, and I feel like apologizing
> again.

Hah, it's cool :) I've been unwell and unable to finalise a solution to mck's requests, I was hoping to resume on the weekend but have been bed-ridden and can't think properly. It happens, what ya gonna do?

> Concerning a universal solution to Brett's problem: well, here's what
> I've been doing for the past years. I do not pretend it is better, just
> that I like it:
> 
> 
> I find, like Brett, that the "JavaBeans" tags from struts-tiles (item
> and bean) are limited in nature. In my experience I only encountered two
> situtations were they were useful, and in both situations I've found
> other solutions to be more effective and maintainable.
> 
> 
> 1. The static approach
> I like the pure HTML+CSS solution to this: <ul><li>My Account</li><li>My
> Orders</li></ul>. It looks and lives well within the template itself.
> 
> 2. The dynamic list.
> In most cases, I find it more convenient to add a bean into the
> appropriate context through the application. For instance, with spring:
> 
> <util:list id="breadcrumbsData">
>   <bean class="example.Link" p:value="#{customer.id}"
> p:link="/customers/#{customer.id}" />
>   <bean class="example.Link" p:value="Orders"
> p:link="/customers/#{customer.id}/salesOrders" />
>   <bean class="example.Link" p:value="#{order.id}"
> p:link="/customers/#{customer.id}/salesOrders/#{order.id}" />
> </util:list>
> 
> And then in tiles:
>    <put-attribute name="breadcrumbs" expression="${breadcrumbsData}"/>
> 
> I find this "breadcrumbsData" tends to evolve over the life of the
> application into something more and more dynamic, for instance session
> specific or requires a data model more complex than the <item>-type of
> thing. Sometimes it is also more convenient to create the list by hand
> and add it to the session/servlet context programatically.

I'm trying to remove things like this as much as possible from the application context and defer to tiles as it's a lot less work. Consider this in my template:

    <tiles:importAttribute name="breadcrumbs" ignore="true"/>
    <ol class="breadcrumb">
      <c:forEach var="item" items="${breadcrumbs}" varStatus="vs">
        <li class="${vs.last ? 'active' : ''}">
          <c:choose>
            <c:when test="${vs.last}">
              <c:out value="${item[0]}"/>
            </c:when>
            <c:otherwise>
              <a href="<c:url value="${item[1]}"/>"><c:out value="${item[0]}"/></a>
            </c:otherwise>
          </c:choose>
        </li>
      </c:forEach>
    </ol>

Now with this I can opt-in to providing crumbs in many different views, which can be completely dynamic and inheritable by tiles. Consider the customers crumbs I've been using, note that this has been changed from using the "<item/>" version to using nested <add-attribute/> values, though I've raised a new pull-request that I need to alter which provides expression support as it's not presently available.

  <definition name="customers/base" extends="customers/none">
    <put-attribute name="title" cascade="true" expression="${customer.sortName} (${customer.id})" />
    <put-list-attribute name="body" cascade="true">
      <add-attribute value="/WEB-INF/views/customers/menu-tabs.jsp"/>
    </put-list-attribute>
    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
      <add-list-attribute>
        <add-attribute value="Customers"/>
        <add-attribute value="/customers"/>
      </add-list-attribute>
    </put-list-attribute>
  </definition>

  <definition name="customers/info" extends="customers/base">
    <put-list-attribute name="body" cascade="true" inherit="true">
      <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" />
    </put-list-attribute>
    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
      <add-list-attribute>
        <add-attribute expression="${customer.id}"/>
        <add-attribute expression="/customers/${customer.country}/${customer.id}/info"/>
      </add-list-attribute>
    </put-list-attribute>
  </definition>

  <definition name="orders/view" extends="customers/base">
    <put-list-attribute name="body" cascade="true" inherit="true">
      <add-attribute value="/WEB-INF/views/customers/cust-salesOrder.jsp" />
    </put-list-attribute>
    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
      <add-list-attribute>
        <add-attribute expression="${customer.id}"/>
        <add-attribute expression="/customers/${customer.id}/info"/>
      </add-list-attribute>
      <add-list-attribute>
        <add-attribute value="Orders"/>
        <add-attribute expression="/customers/${customer.country}/${customer.id}/salesOrders"/>
      </add-list-attribute>
      <add-list-attribute>
        <add-attribute expression="${salesOrder.id}"/>
        <add-attribute expression="/customers/${customer.country}/${customer.id}/salesOrders/${salesOrder.id}"/>
      </add-list-attribute>
    </put-list-attribute>
  </definition>

Note here how now my spring controllers need to know nothing about the breadcrumbs. In fact the only thing that knows about them is the view and the view composition, which I believe is the whole point of a framework like tiles, being able to decouple your composition from your controllers, which is what I love about tiles.



> I used the tiles-centric solution back at the time when CSS and DI were
> barely budding, and their long-term adoption was still questionable, but
> now I prefer other ways. That being said, I'm totally open to
> contributions that would be useful to others.
> 
> 
> 
> 
> Concerning the documentation: I totally agree it needs work, there's a
> ramp up to learning Tiles 3. Initialization is cumbersome, and as we
> discussed earlier, the duality between "value" and "expression" is
> confusing. All of this is documented on the website, but the docs are
> dry and learning is difficult. Perhaps we could rework the tutorials and
> update the examples. Another dark area is: how to test?

Would love to help, I've been using tiles for some years and myself only stumble onto 3 specific features when I find them, so I don't "know it all", but I'd be more than happy to help contribute to docs.

> That being said, my time being limited, I prefer to invest it in
> simplifying the usage of tiles before documenting the simple solution,
> as opposed to trying to explain the complex solution in a clear way.

I would tend to agree, and considering it's been that way for a while, maybe that's the right approach. Though, how long would the simplified solution take to implement?

> So personnally I'm looking at reviewing the docs when tiles can be
> configured from DI, and run in junit (tiles 3.1, perhaps. My github fork
> already has the junit part working, and I'm experimenting with DI).
> 
> Cheers!
> 
> Nick
> 
> PS: On 15-07-08 09:21 AM, Brett Ryan wrote:
>> toString should always be a string representation of a value, not
> null, alternatives would be "null" or "(null)".
> 
> +1, definitely
> 
> 
> 
> 
> 


Re: Pull Request #4: Object-Type Attribute Value Evaluation

Posted by Nicolas Le Bas <ma...@nlebas.net>.
Hi all,

First of all, I take responsibility for cross posting to the dev list.
Sorry if it surprised you, Brett, I just feel it is a better place to
discuss code changes. People come here with a different mindset.

And sorry for the delay in my answer, too. We're all volunteers here :)
As a consequence, it will be a long answer, and I feel like apologizing
again.


Concerning a universal solution to Brett's problem: well, here's what
I've been doing for the past years. I do not pretend it is better, just
that I like it:


I find, like Brett, that the "JavaBeans" tags from struts-tiles (item
and bean) are limited in nature. In my experience I only encountered two
situtations were they were useful, and in both situations I've found
other solutions to be more effective and maintainable.


1. The static approach
I like the pure HTML+CSS solution to this: <ul><li>My Account</li><li>My
Orders</li></ul>. It looks and lives well within the template itself.

2. The dynamic list.
In most cases, I find it more convenient to add a bean into the
appropriate context through the application. For instance, with spring:

<util:list id="breadcrumbsData">
   <bean class="example.Link" p:value="#{customer.id}"
p:link="/customers/#{customer.id}" />
   <bean class="example.Link" p:value="Orders"
p:link="/customers/#{customer.id}/salesOrders" />
   <bean class="example.Link" p:value="#{order.id}"
p:link="/customers/#{customer.id}/salesOrders/#{order.id}" />
</util:list>

And then in tiles:
    <put-attribute name="breadcrumbs" expression="${breadcrumbsData}"/>

I find this "breadcrumbsData" tends to evolve over the life of the
application into something more and more dynamic, for instance session
specific or requires a data model more complex than the <item>-type of
thing. Sometimes it is also more convenient to create the list by hand
and add it to the session/servlet context programatically.


I used the tiles-centric solution back at the time when CSS and DI were
barely budding, and their long-term adoption was still questionable, but
now I prefer other ways. That being said, I'm totally open to
contributions that would be useful to others.




Concerning the documentation: I totally agree it needs work, there's a
ramp up to learning Tiles 3. Initialization is cumbersome, and as we
discussed earlier, the duality between "value" and "expression" is
confusing. All of this is documented on the website, but the docs are
dry and learning is difficult. Perhaps we could rework the tutorials and
update the examples. Another dark area is: how to test?

That being said, my time being limited, I prefer to invest it in
simplifying the usage of tiles before documenting the simple solution,
as opposed to trying to explain the complex solution in a clear way.

So personnally I'm looking at reviewing the docs when tiles can be
configured from DI, and run in junit (tiles 3.1, perhaps. My github fork
already has the junit part working, and I'm experimenting with DI).

Cheers!

Nick

PS: On 15-07-08 09:21 AM, Brett Ryan wrote:
> toString should always be a string representation of a value, not
null, alternatives would be "null" or "(null)".

+1, definitely






Re: Pull Request #4: Object-Type Attribute Value Evaluation

Posted by Brett Ryan <br...@gmail.com>.
mck <mc...@...> writes:

> 
> Sorry for my very late reply. It's been a bit chaotic of late.
> 
> > - All other tags in tiles-defs.xml require the developer to specify
> > explicitely that she wants the expression evaluated: <add-attribute
> > expression="${customer.id}"/> instead of <add-attribute value="Customer
> > ID"/>. Doing differently for <item> would make this XML even more
> > confusing that it already is.
> 
> Brett, why were you using <item> instead of <put-attribute> inside the
> <put-list-attribute> ?
> Is it only because you want two values? (ie value and link)
> 
> Could there be other ways to solve this with tags that are supported in
> tiles-3
> 
> For example something like…
> 
>     <put-list-attribute name="breadcrumbs">
>       <add-list-attribute name="customer.id">
>         <add-attribute expression="${customer.id}" />
>         <add-attribute
>         expression="/customers/${customer.id}/salesOrders" />
>       </add-list-attribute>
>       <add-list-attribute name="order.id">
>         <add-attribute expression="${order.id}" />
>         <add-attribute
>         expression="/customers/${customer.id}/salesOrders" />
>       </add-list-attribute>
>     </put-list-attribute>
> 
> > - Do we want to keep maintaining <item> and <bean>, given that today DI
> > frameworks provide several better ways to declare those beans? 
> 
> Not for example if approaches like i wrote above are a satisfactory
> solution.
> 
> ~mck
> 
> 


Hi guys, I apologise for not subscribing to the dev list before submitting a
pull request, the though had not crossed my mind. It is funny because I did pose
the question on the users mailing list how to achieve what I was after and
directed to look at the source code for the MenuItem.

Anyway, I think the mck's approach would work, however when using `expression`
attributes within `<add-list-attribute>` causes an NPE. I have to be honest that
it's not quite as clean in both the definitions and in the view due to more
nesting in the definition and array indexing in the view as it can't be accessed
by name.

A quite universal solution that would be valuable for many scenarios would be
some sort of tuple support within tiles for paired or triplet values. This would
allow one to add attributes just how mck describes but not need to use indexes
to the attribute in the view, and not have all the nesting vertical problem
within the tiles configs, consider:

    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
      <add-pair-attribute left-value="Orders"
          right-expression="/customers/${customer.id}/orders"/>
      <add-pair-attribute left-expression="${salesOrder.id}"
          right-expression="/customers/${customer.id}/orders/${salesOrder.id}"/>
    </put-list-attribute>

vs

    <put-list-attribute name="breadcrumbs" cascade="true" inherit="true">
      <add-list-attribute>
        <add-attribute value="Orders"/>
        <add-attribute expression="/customers/${customer.id}/orders"/>
      </add-list-attribute>
      <add-list-attribute>
        <add-attribute expression="${salesOrder.id}"/>
        <add-attribute
            expression="/customers/${customer.id}/orders/${salesOrder.id}"/>
      </add-list-attribute>
    </put-list-attribute>

As a final note I think some more example documentation could go a long way.
I would be more than happy to write up any documentation on these sorts of more
interesting uses of tiles, while there's sufficient API and DTD documentation
more example type docs could go a long way. As an example, apart from the DTD
and API documentation I couldn't find any documentation on the use of
add-list-attribute on tiles.apache.org or even a google search.

I'm more than happy to discuss any point further, and very willing to help where
I can. My use of tiles would probably be considered moderate, It's always been
my go to composition choice within spring applications for at least the past 5
years, but as you can tell I don't have an advanced knowledge of tiles.