> On 16 Jul 2015, at 22:00, Nicolas Le Bas <[email protected]> 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 <[email protected]> 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
>> 

Reply via email to