Composing Apache Tiles 2 layout from many templates

4.6k views Asked by At

I'm building the web application with Spring 3 and Tiles 2.2. I've put following layout definition:

<tiles-definitions>  
<definition name="default" template="/WEB-INF/layouts/default.jspx">  
<put-attribute name="header" value="main.header" />  
<put-attribute name="top_menu" value="/WEB-INF/views/top_menu.jspx" />  
<put-attribute name="left_column" value="main2.left_column" />  
<put-attribute name="main_column" value="main2.main_column" />  
<put-attribute name="footer" value="/WEB-INF/views/footer.jspx" />  
</definition> 

<definition name="main2.main_column" template="/WEB-INF/layouts/double_column/main_column.jspx">  
</definition>

<definition name="main2.left_column" template="/WEB-INF/layouts/left_column.jspx">  
        <put-attribute name="profile_menu" value="/WEB-INF/views/userprofile/userdetails.jspx" />  
        <put-attribute name="common_menu" value="/WEB-INF/views/menu.jspx" />  
      </definition>  
</tiles-definitions>

In WEB-INF/layouts/default.jspx

<div id="main_page" >   
    <tiles:insertAttribute name="left_column"/>    
    <tiles:insertAttribute name="main_column"/>   
        <div id="footer" >  
<tiles:insertAttribute name="footer" ignore="true"/>  
                </div>  
            </div>  

Now in /WEB-INF/layouts/double_column/main_column.jspx i have:

<tiles:insertAttribute name="body"/>  

Requested path view.xml is defined as following:

<tiles-definitions>  
    <definition extends="default" name="secure/createAccount/*">  
        <put-attribute name="body" value="/WEB-INF/views/secure/createAccount/{1}.jspx"/>  
    </definition>  
</tiles-definitions>

and error is:

org.apache.tiles.template.NoSuchAttributeException: Attribute 'body' not found.
    org.apache.tiles.template.DefaultAttributeResolver.computeAttribute(DefaultAttributeResolver.java:49)
    org.apache.tiles.template.InsertAttributeModel.resolveAttribute(InsertAttributeModel.java:187)
    org.apache.tiles.template.InsertAttributeModel.start(InsertAttributeModel.java:107)
    org.apache.tiles.jsp.taglib.InsertAttributeTag.doTag(InsertAttributeTag.java:306)
    org.apache.jsp.WEB_002dINF.layouts.double_005fcolumn.main_005fcolumn_jspx._jspx_meth_tiles_005finsertAttribute_005f0(main_005fcolumn_jspx.java:79)
    org.apache.jsp.WEB_002dINF.layouts.double_005fcolumn.main_005fcolumn_jspx._jspService(main_005fcolumn_jspx.java:54)

If i put "body" directly to the default template it works, but thing is I want have my template bricks being reusable by many layouts, not only default one and i dont want to copy all formating to each template definition using main_column

Please advice

2

There are 2 answers

0
gregor On

As the exception tells you the definition of main_column has not attribute body. Your second definition says that it is an your root definition and not of main_column. By default there is no such thing like attributes inheritance or bubbling. Hence the children don't know anything about the attributes of their parents and vice versa. Their are two solutions for your problem:

You can add the attribute cascade="true" to your attribute definition. That lets the attribute cascade to the child definitions (see cascaded attributes)

You could use nested definitions:

<tiles-definitions>  
  <definition extends="default" name="secure/createAccount/*">  
    <put-attribute name="main_column">
      <definition template="/WEB-INF/layouts/double_column/main_column.jspx">
        <put-attribute name="body" value="/WEB-INF/views/secure/createAccount/{1}.jspx"/>  
      </definition>
    </put-attribute>
  </definition>  
</tiles-definitions>

(see nesting definitions)

0
Jagadeesh On

May be you are specifying the baselayout.jsp page at welcomepagelist in web.xml. if you specified that one remove that and send dummy request to action class then forward your response to some jsp which is declared in tiles.xml