Struts tiles

Discussions

Web tier: servlets, JSP, Web frameworks: Struts tiles

  1. Struts tiles (13 messages)

    I'm new to struts. I'm trying to implement tiles as described in this article:
    Reuse Tiles and Simplify UI By James Holmes

    In the article a centralized xml file is used to describe the inheritenace between pages. For some reason I can't make this work.

    The tiles are working like this:
    <tiles:insert page="/template.jsp" flush="true">
      <tiles:put name="title" value="Sample Page Title2" />
      <tiles:put name="header" value="/pages/_header.jsp" />
      <tiles:put name="left" value="/pages/_left.jsp" />
      <tiles:put name="body" value="/pages/_body.jsp" />
      <tiles:put name="footer" value="/pages/_footer.jsp" />
    </tiles:insert>

    ..when added in another page. So this way the current page inherits the layout from the template.jsp. But the code goes in each page.

    I want it all in the tiles-defs.xml file.

    ***

    Another thing concerning tiles...

    Is it possible to use tiles in several levels? Like if the body part should add pieces of common code.


    Thank you in advance.

    Threaded Messages (13)

  2. Struts tiles[ Go to top ]

    Here's a simple tiles-defs.xml that works:
    <?xml version="1.0" encoding="windows-1252" ?>
    <!DOCTYPE tiles-definitions PUBLIC
           "-//Apache Software Foundation//DTD Tiles Configuration//EN"
           "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">

    <tiles-definitions>
      <definition name="tiles.mainLayout" path="/templates/template.jsp">
    <put name="title" value="Tiles Header title" />
    <put name="header" value="/tiles/header.jsp" />
    <put name="footer" value="/tiles/footer.jsp" />
    <put name="body" value="/tiles/body.jsp" />
      </definition>


      <definition name="tiles.subclassedLayout.page" extends="tiles.mainLayout" >
    <put name="title" value="A subclassed Page" />
    <put name="body" value="/tiles/body2.jsp" />
      </definition>

    </tiles-definitions>
  3. Struts tiles[ Go to top ]

    Replace
    <tiles:insert page="/template.jsp" flush="true">
    with
    <definition name="someName" path="/template.jsp">
    and
    </tiles:insert>
    with
    </definition>

    Dunan Mills' response is right on the money.

    Also, yes you can do tiles in levels. Instead of
    <put name="body" value="/pages/_body.jsp"/>
    use
    <put name="body" value="XYZ"/>
    then, add a new tile definition for the body with a name of XYZ.
  4. Struts tiles[ Go to top ]

    Thank you both for replying.

    Maybe it's obvious, but how do I call this inherited page?

    Template:
    http://localhost/testApp/template.jsp

    Inherited:
    http://localhost/testApp/someName


    I suppose I don't have to create a page like before, since there is no url in the inherited definition.
  5. Struts tiles[ Go to top ]

    Hallo Daniel

    You cannot call a tile directly from the browser you'll have to do it by using a actionforward.

    something like the following;
    package com.example.struts;
    public MyAction extends ... {

       public void execute(...) {

         return mapping.findActionForward("myTile");
       }
    }

    Your Struts definition should contain something like;

     <action path="/myAction"
                type="com.example.struts.MyAction >
            <forward name="myTile" path="tile"/>
        </action>


    Hope this will help you.

    /Per
  6. Struts tiles[ Go to top ]

    Thanks Per. I can't get it to work though. This is what I have:
    (I used findForward, since I didn't find findActionForward in the ActionMappingClass.)

    package test;
    import org.apache.struts.action.*;
    import javax.servlet.http.*;
    public class MyAction extends org.apache.struts.action.Action {

        public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) {

         return mapping.findForward("myTile");
       }
    }

    In the struts-config:
    <action path="/myAction"
            type="test.MyAction" >
        <forward name="myTile" path="Template"/>
    </action>

    In the tiles-def:
    <definition name="someName" path="/_template.jsp">
        <put name="title" value="Standard Title" />
        <put name="header" value="/pages/_header.jsp" />
        <put name="left" value="/pages/_left.jsp" />
        <put name="body" value="/pages/_body.jsp" />
        <put name="footer" value="/pages/_footer.jsp" />
    </definition>

    <definition name="Template" extends="someName">
        <put name="title" value="Another Title" />
    </definition>


    Anyway, does this mean I have to create a new class for every new tile?


    Thanks!

    /Daniel
  7. Struts tiles[ Go to top ]

    Thanks Per. I can't get it to work though. This is what I have:(I used findForward, since I didn't find findActionForward in the ActionMappingClass.)package test;import org.apache.struts.action.*;import javax.servlet.http.*;public class MyAction extends org.apache.struts.action.Action {&nbsp;&nbsp;&nbsp;&nbsp;public ActionForward execute(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionMapping mapping,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionForm form,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest request,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse response) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return mapping.findForward("myTile");&nbsp;&nbsp;&nbsp;}}In the struts-config:<action path="/myAction"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type="test.MyAction" >&nbsp;&nbsp;&nbsp;&nbsp;<forward name="myTile" path="Template"/></action>In the tiles-def:<definition name="someName" path="/_template.jsp">&nbsp;&nbsp;&nbsp;&nbsp;<put name="title" value="Standard Title" />&nbsp;&nbsp;&nbsp;&nbsp;<put name="header" value="/pages/_header.jsp" />&nbsp;&nbsp;&nbsp;&nbsp;<put name="left" value="/pages/_left.jsp" />&nbsp;&nbsp;&nbsp;&nbsp;<put name="body" value="/pages/_body.jsp" />&nbsp;&nbsp;&nbsp;&nbsp;<put name="footer" value="/pages/_footer.jsp" /></definition><definition name="Template" extends="someName">&nbsp;&nbsp;&nbsp;&nbsp;<put name="title" value="Another Title" /></definition>Anyway, does this mean I have to create a new class for every new tile?Thanks!/Daniel

    ---
    If the tile doesn't work try using this naming convention:
    Call your tile definitions something like;
    .<someName>.[.something-more]
    and do the reference in the actionforward by this name.

    Another problem could be that you don't use the TileRequestProcessor, but the default StrutsRequestProcessor.


    No you don't have to make a new class for each tile;
    example
    -------

    In the struts-config:
    <action path="/myAction"
            type="test.MyAction" >
        <forward name="newView" path=".newView.product"/>
        <forward name="editView" path=".editView.product"/>
    </action>

    In the tiles-def:
    <definition name="someName" path="/_template.jsp">
        <put name="title" value="Standard Title" />
        <put name="header" value="/pages/_header.jsp" />
        <put name="left" value="/pages/_left.jsp" />
        <put name="body" value="/pages/_body.jsp" />
        <put name="footer" value="/pages/_footer.jsp" />
    </definition>

    <definition name=".newView.product" extends="someName">
        <put name="title" value="New Product" />
    </definition>

    <definition name=".editView.product" extends="someName">
        <put name="title" value="Edit Product" />
    </definition>


    In this case you can control in your action which action forward to choose and then this tile will be presented.

    The classic example is that you have one Action that saves the Product, dependent on whether its a new Product the title for the tile should show New, or Edit if the Product already exists.

    Nb. Sorry for the findActionForward(), I wrote the example in this editor :-).

    /Per
  8. Struts tiles[ Go to top ]

    Thanks a lot for your help, it's really appreciated!


    I copied what you suggested to the tiles-defs and struts-config files.

    The MyAction class was changed to:

    ..
    public ActionForward execute(...) {
        return mapping.findForward("newView");
    }
    ..

    And I then (after recompiling and restarting the app), I tried to call the tile using these urls:

    http://localhost/testApp/myAction
    http://localhost/testApp/newView
    The result was "The requeste resource is not available." in both cases.

    Oh and I use the TileRequestProcessor;
    <controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/>


    Could it be that the tiles-defs are not loaded for some reason? I added this plug-in in the struts-config:

    <plug-in className="org.apache.struts.tiles.TilesPlugin" >
        <set-property property="definitions-config"
            value="/WEB-INF/tiles-defs.xml" />
        <set-property property="moduleAware" value="true" />
    </plug-in>

    The Tomcat log file says:
    13/11/2004 15:47:33 org.apache.struts.tiles.TilesPlugin initDefinitionsFactory
    INFO: Tiles definition factory loaded for module ''.

    I tried to cut the module-aware tag, no difference.



    Again, thanks a lot for your help.
  9. Struts tiles[ Go to top ]

    Thanks a lot for your help, it's really appreciated!I copied what you suggested to the tiles-defs and struts-config files.The MyAction class was changed to:..public ActionForward execute(...) {&nbsp;&nbsp;&nbsp;&nbsp;return mapping.findForward("newView");}..And I then (after recompiling and restarting the app), I tried to call the tile using these urls:http://localhost/testApp/myActionhttp://localhost/testApp/newViewThe result was "The requeste resource is not available." in both cases.Oh and I use the TileRequestProcessor;<controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/>Could it be that the tiles-defs are not loaded for some reason? I added this plug-in in the struts-config:<plug-in className="org.apache.struts.tiles.TilesPlugin" >&nbsp;&nbsp;&nbsp;&nbsp;<set-property property="definitions-config"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="/WEB-INF/tiles-defs.xml" />&nbsp;&nbsp;&nbsp;&nbsp;<set-property property="moduleAware" value="true" /></plug-in>The Tomcat log file says:13/11/2004 15:47:33 org.apache.struts.tiles.TilesPlugin initDefinitionsFactoryINFO: Tiles definition factory loaded for module ''.I tried to cut the module-aware tag, no difference.Again, thanks a lot for your help.

    hallo
    Your setup look correct for the tile part..

    You might have forgotten to prefix your struts call with
    .do like this ??

    http://localhost/testApp/myAction.do
    http://localhost/testApp/newView.do

    Another thing could be that the actionforward should reference tile with .names.

    public ActionForward execute(...) {
        return mapping.findForward("newView");
    }
    ..
    struts def.

    <forward name="newView" path=".myTile"/>

    ..

    Tiles-defs.

    <definition name=".default" path="/_template.jsp">
        <put name="title" value="Standard Title" />
        <put name="header" value="/pages/_header.jsp" />
        <put name="left" value="/pages/_left.jsp" />
        <put name="body" value="/pages/_body.jsp" />
        <put name="footer" value="/pages/_footer.jsp" />
    </definition>

    <definition name=".myTile" extends=".default">
        <put name="title" value="Another Title" />
    </definition>


    /Per
  10. Struts tiles[ Go to top ]

    Hey, it's working! Thanks a lot!

    I wasn't aware that .do is necessary in the url.
    http://localhost/testApp/myAction.do


    So for a set of functions I can use the same action class (saveStuff).
    Suppose I have one template and 20 pages that should inherit it. I want to call each page through a different url, like
    ../page1.do, ../page2.do, etc. In the example;
    http://localhost/testApp/newView.do
    http://localhost/testApp/editView.do.

    Can I still use the same action class for all?

    I suppose I have to create one class for each different url, unless I use parameters.
  11. Struts tiles[ Go to top ]

    Hey, it's working! Thanks a lot!I wasn't aware that .do is necessary in the url.http://localhost/testApp/myAction.doSo for a set of functions I can use the same action class (saveStuff).Suppose I have one template and 20 pages that should inherit it. I want to call each page through a different url, like ../page1.do, ../page2.do, etc. In the example; http://localhost/testApp/newView.dohttp://localhost/testApp/editView.do.Can I still use the same action class for all?I suppose I have to create one class for each different url, unless I use parameters.

    Im glad to hear that it works, I think you will be very happy using tiles.

    You can use the same action class for many templates, but each url is connected to one actionform which identifies your form input data, so the best strategy if you want to avoid having many action making simple CRUD operation is to use a DispatchAction (I think one is included with Struts).

    /Per
  12. Check out sitemesh[ Go to top ]

    For an alternative to tiles, check out sitemesh here. I have used both and sitemesh is (IMHO) much more powerful and easier to use.

    Derek
  13. sitemesh[ Go to top ]

    Thanks for the tip, I'll look into it.

    For now I'll probably use tiles though.

    /Daniel
  14. Database driven tiles[ Go to top ]

    I have been using tiles for a few months now and found that using urlController allows for much more advanced applications. Wow, I love it. However, I do not see a lot of articles/tutorials about it. Maybe there is a reason why its not used that often? I for once find it very powerful to pick a layout to use from database as well as pull all the components from it.

    I did run into an interesting issue lately, my urlController is getting pretty fat (hey maybe that’s reason why hehe) but I wanted to call different Actions based on the data requested from this controller and cant find a way to do it. Is there a way to execute an Action from urlController and than come back to executing the rest of urlController?

    Thanks