On Oct 11, 2006, at 6:06 AM, Gregg Leichtman wrote:
I suppose that I could create a different definition like:
<definition name="/mainLayout" path="/tiles/layouts/
siteLayout.jsp">
<put name="htmlHeader" type="template" value=""/>
<put name="header" type="template" value="/tiles/
headerTile.jsp"/>
<put name="rightSideBar" type="template" value="/tiles/
rightSideBarTile.jsp"/>
<put name="footer" type="template" value="/tiles/
footerTile.jsp"/>
</definition>
<definition name="/htmlHeaderPage" extends="/mainLayout">
<put name="htmlHeader" type="template" value="/tiles/
htmlHeaderTile.jsp"/>
</definition>
and then use
<tiles:insert name="/htmlHeaderPage" />
however, I have used the previous method for rendering the "put"
described _within_ the definition successfully under Tomcat with
shale-1.0.3. This is also described by Dick Starr at:
Antonio was correct, but I think his point somehow got lost. You
don't actually need another definition. You need another JSP page.
Let's break it down with a simple example:
Suppose you have a definition:
<definition name="foobar" path="/foobar.jsp">
<put name="header" value="/header.jsp"/>
<put name="body" value="/body.jsp"/>
<put name="footer" value="/footer.jsp"/>
</definition>
Then here's foobar.jsp:
<html>
....
<body>
<tiles:insert name="header"/>
<tiles:insert name="body"/>
<tiles:insert name="footer"/>
</body>
</html>
If you just type "/foobar.jsp" into your browser Tiles is going to
blow up saying you're trying to insert a definition called "header"
which it can't find. It doesn't realize you are already *in* a
definition called "foobar" and you're trying to insert an *attribute*
called "header" because you never invoked Tiles to get the definition
called "foobar". Therefore Tiles thinks you're looking for a
definition called "header".
To make the above example work you need an intermediate JSP. Let's
call it intermediate.jsp. Here's what it would look like in its
entirety:
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insert name="foobar"/>
Then, instead of typing "/foobar.jsp" in your browser you'd type "/
intermediate.jsp" in your browser. Tiles will go find the definition
called "foobar", invoke the foobar.jsp template and process your
header, body, and footer.
In JSF, by doing <jsp:forward page="/tiles/layouts/siteLayout.faces"/
> you are calling /siteLayout.jsp directly - as if you simply typed
the name of that page in your browser. You are not using Tiles to
invoke the template, you are invoking it directly. Using the example
above you need to do something like this:
index.jsp:
<jsp:forward page="/intermediate.jsp"/>
intermediate.jsp:
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insert name="foobar"/>
Or in your case, intermediate.jsp would look like this:
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insert name="/mainLayout"/>
There are two reasons why this is confusing:
1) Tiles has no controller. You would like to be able to invoke
Tiles by simply calling the template page, but you can't. You have
to either call an intermediate page that invokes the template using
the <tiles:insert> tag to insert the definition. Or you have to use
a controller architecture like Struts or JSF that knows how to
forward to a Tiles definition. In essence, Struts and JSF are doing
the <tiles:insert name="/mainLayout"/> for you in the
TielsRequestProcessor and TilesViewHandler respectively. Those
components know how to call into Tiles, get a Tiles definition, and
process it.
Perhaps you'd like Tiles to have a controller so you could type a URL
like "http://mywebapp/mainLayout.tiles" and a Servlet or something
would insert the "mainLayout" definition. But we probably won't do
that because Tiles was not meant to be a controller, it was meant to
work with other controllers like Struts or JSF. In "standalone" mode
it requires an intermediate JSP.
Another option for improvement would be to make Tiles work more like
Facelets. Facelets does not require the intermediate page. In
Facelets you define your template in a page called /
siteLayout.xhtml". Then, if you have a page called "foobar" that
extends the template, you directly invoke "/foobar.xhtml" This page
then "includes" the template. Tiles requires the intermediate page
because it works the other way around. Instead of having pages that
include templates, Tiles has definitions that extend templates and
include pages. I could give an example but it would just make this
post a lot longer.
2) The <tiles:insert> tag is overloaded to mean too many things.
<tiles:insert> can be used to insert definitions, attributes, pages,
strings, and probably scrambled eggs :-) So when you see a
<tiles:insert> tag you need to look further to see what context it is
in. Is it trying to insert an attribute? a definition? We're
trying to figure out the best way to address this issue. It will
probably mean different tags to do different things.
I hope that clears it up.
Thanks,
Greg