tiles-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brett Ryan <brett.r...@gmail.com>
Subject Re: Pull Request #4: Object-Type Attribute Value Evaluation
Date Wed, 15 Jul 2015 02:18:23 GMT

> On 15 Jul 2015, at 11:53, Nicolas Le Bas <mail@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
> 
> 
> 
> 
> 


Mime
View raw message