Question

I am using Struts tiles 1 succesfully, however I have come across a problem when trying to nest tiles.

I currently have a layout like so:

I wish to have another template like this, for use in quite a few user pages:

So I wish to extend the first layout for the user layout. In the tiles definiton I am using:

<definition name=".basic.layout" path="/WEB-INF/jsps/basicLayout.jsp">
    ....

<definition name=".user.layout" extends=".basic.layout">
    <put name="content" value="/WEB-INF/jsps/user/layout.jsp"/>
    ....

<definition name=".user.page" extends=".user.layout">
    <put name="userContent" value="/WEB-INF/jsps/user/page.jsp"/>
    ....

In user/layout.jsp I attempt to show the tile usually, using <tiles:get name="userContent"/>.

And the problem is The requested resource (/WEB-INF/jsps/user/userContent) is not available

Was it helpful?

Solution 3

I found some information from here

This solution worked for me.

In this case, usually you have to create a new definition extending from an existing one, fill the attribute in the correct template and assign the new definition as an attribute to the main template.

In other words:

<definition name="product.nav" template="/productNavLayout.jsp">    
    <put-attribute name="productPathNav" value="/productPathNav.jsp" />    
    <put-attribute name="productNav" value="/productNav.jsp" />  
</definition> 

<definition name="product.nav.extended" extends="product.nav">    
    <put-attribute name="productContent" value="product.grid" />  
</definition> 

<definition name="page.products" extends="layout">
    <put-attribute name="content" value="product.nav.extended" />  
</definition>

OTHER TIPS

There is a cleaner solution.

Another approach is to only use one definition (plus the defaultLayout definition) in the tiles-def.xml file.

tiles-def.xml:

<definition name="defaultLayout" template="/WEB-INF/layout.jsp">
    <put name="header" value="/WEB-INF/header.jsp" />
    <!-- definitions based on this layout must define "body"  -->
    <put name="footer" value="/WEB-INF/footer.jsp" />
</definition>

<definition name="editPage" extends="defaultLayout">
    <put name="body" value="/WEB-INF/editBody.jsp" />
    <put name="a" value="/WEB-INF/a.jsp" />
    <put name="b" value="/WEB-INF/b.jsp" />
</definition>

layout.jsp:

<tiles:insert attribute="header">
  <tiles:insert attribute="body" >
      <!-- propogate "a" and "b" down to the next level -->
      <tiles:put name="a" beanName="a"/>
      <tiles:put name="b" beanName="b"/>
  </tiles:insert>
<tiles:insert attribute="footer">

editBody.jsp:

<table>
   <tr>
      <td><tiles:insert attribute="a"/></td>
      <td><tiles:insert attribute="b"/></td>
   </tr>
</table>

The downside of this approach is that layout.jsp must know the list of possible arguments to (any) body.jsp page.

It's been a long while since I've used Struts Tiles, but shouldn't you be using <tiles:insert> instead of <tiles:get>?

That is, something like:

<tiles:insert attribute="userContent" flush="false"/>

I as can see from your question you use different names for the content attribute. It is content for user.layout and userContent for user.page.

Can you try to use the same name for that attribute either content or userContent?

Hope this helps.

Update. This is quick hack solutions. You can use ignore attribute set to true for tiles:get operation. It will go silently when no userContent defined.

But I think this is something wrong with tiles definitions.

The error message suggests that you are trying to use tile which is not defined. I compiled an example when .user.layout is an extension of .basic.layout. The difference between two is a body part.

<definition name=".basic.layout" path="/WEB-INF/jsps/basicLayout.jsp">
   <put name="header" value="/WEB-INF/jsps/header.jsp"/>
   <put name="content" value="/WEB-INF/jsps/basicLayout.jsp"/>
   <put name="footer" value="/WEB-INF/jsps/footer.jsp"/>
</definition> 

<!-- extending content part of basic layout -->
<definition name=".user.content" value="/WEB-INF/jsps/user/layout.jsp">
   <put name="userContent" value="/WEB-INF/jsps/user/page.jsp"/>
</definition>

<!-- defining new layout -->
<definition name=".user.layout" extends=".basic.layout">
  <put name="content" value=".user.content"/>
</defnition>

<definition name=".user.page" extends=".user.layout">
  <put name="userContent" value="/WEB-INF/jsps/page.jsp"/>
</definition>

<definition name=".user.info" extends=".user.layout">
  <put name="userContent" value="/WEB-INF/jsps/userInfo.jsp"/>
</definition>

<definition name=".other.page" extends=".basic.layout">
  <put name="content" value="/WEB-INF/jsps/other.jsp"/>
</definition>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top