After more digging I believe I have found the bug:

In AddAttributeTag#doAfterBody:

/**
     * Save the body content of this tag (if any).
     *
     * @return It returns <code>SKIP_BODY</code>.
     */
    public int doAfterBody() {
        if (value == null && bodyContent != null) {  //bug here
            value = bodyContent.getString();
            type = "string";
        }
        return (SKIP_BODY);
    }

The value of this tag is only being updated if there is not already a value set. So, when this tag is used twice in succession on a page, it will always only use the first "value" ever set!!!

I looked back at the older Tiles 2.0.6 version we were using and the code is correct in that version - there is no "value == null" check. So, it looks as though someone added this little check at some point in the 2.1 release, but it seems to severely break things (at least for me!)

I see two ways of fixing this -

1.) Simply remove the value == null check, or if this check is in place for a reason,

2.) Reset value to null after each execution of the tag in doEndTag, or doFinally() from the TryCatchFinally interface:

http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/jsp/tagext/TryCatchFinally.html

I have logged this as a bug here:

https://issues.apache.org/struts/browse/TILES-338

Best,

Zach Bailey
[EMAIL PROTECTED]

On Dec 8, 2008, at 1:21 PM, Zach Bailey wrote:

Hi all,

I was trying some of the new Tiles 2.1 features today, specifically cascading attributes. I like this new feature a lot and it seems to finally solve some of the challenges I have faced with tiles in the past.

I am using the newest tiles release (2.1.0 beta) in conjunction with Spring Web MVC.

However, I have run into what seems to be a rather strange problem. First, let me show you my definitions:

<definition name="wrapper" template="/layouts/wrapper.jsp">
   <put-attribute name="content" value="/common/blank.jsp"/>
</definition>

<definition name="leftColumnMain" extends="wrapper">
   <put-attribute name="content" value="/layouts/leftColumnMain.jsp"/>
<put-attribute name="main" value="/common/blank.jsp" cascade="true"/> <put-attribute name="sidebar" value="/common/blank.jsp" cascade="true"/>
</definition>

<definition name="leftColumnTest" template="/pages/ leftColumnTest.jsp"/>

Essentially, I am constructing a "base" layout - the wrapper - which contains just the most common items (wrapper.jsp) :

<%-- taglibs removed for brevity --%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
 <head>
   <title>Left Column Main</title>
 </head>
 <body>
   <tiles:insertAttribute name="content"/>
 </body>
</html>

which is then extended by a more specific layout which defines a 67% left column and 33% right column (leftColumnMain.jsp) :

<%-- taglibs removed for brevity --%>
   <!-- Left column. -->
   <div class="prepend-2 span-31 last">
     <tiles:insertAttribute name="main"/>
   </div>
   <!-- Closes left column. -->

   <!-- Right column. -->
   <div class="prepend-1 span-14 append-1 last">
     <tiles:insertAttribute name="sidebar"/>
   </div>
   <!-- Closes right column. -->

which is then used for a "leaf node" page just to test all this out (leftColumnTest.jsp) :

<%-- taglibs removed for brevity --%>
<tiles:insertDefinition name="leftColumnMain">

 <tiles:putAttribute name="main" cascade="true">
   <p>This is left column content.</p>
 </tiles:putAttribute>

 <tiles:putAttribute name="sidebar" cascade="true">
   <p>This goes in the sidebar.</p>
 </tiles:putAttribute>

</tiles:insertDefinition>

I am now finding that when I render these definitions, I get "This is the left column content." in place of both the "main" AND "sidebar" attribute. Of course, I would expect to see the main content in the main, left column and then the sidebar content in the other column - but I only see the main content. Can anyone spot my mistake? Could this be a bug, or am I just overlooking something simple?

It gets even weirder -- when I decide to change the order of the tiles:putAttribute tags in my leftColumnTest.jsp, I can produce the exact opposite results:

<tiles:insertDefinition name="designLeftColumnMain">

 <tiles:putAttribute name="sidebar" cascade="true">
   <p>This goes in the sidebar.</p>
 </tiles:putAttribute>

 <tiles:putAttribute name="main" cascade="true">
   <p>This is left column content.</p>
 </tiles:putAttribute>

</tiles:insertDefinition>

By putting the sidebar first, now "This goes in the sidebar" is rendered twice in both places. So, this leads be to believe that somehow something is being overwritten and that the "name" attribute is not really being respected.

Perhaps also this is a bug with the new cascade behavior? If anyone can provide me with help on how to recreate this sort of inheritance without using the cascade attribute, I would be very gracious! I have struggled for quite a few hours now trying to get this sort of template structure working.

Thanks in advance for any help or insight you can give...

Best,

Zach Bailey
[EMAIL PROTECTED]











Reply via email to