jspspring-mvcapache-tiles

Manage JavaScript and CSS with Apache Tiles


I'm looking for a good way to manage CSS and JS resources using Apache Tiles in a similar way to ASP.NET MVC 4.

In ASP.NET MVC4 you have ContentBundles and ScriptBundles and you can simply write

@Scripts.Render("~/bundles/jquery");

It will insert your css/scripts with all the proper syntax. Then to make it even better there is @RenderSection("JavaScript", required:false) which allows you to insert JavaScript in the correct include order with it being defined on a view as so.

@section JavaScript
{
    <script type="text/javascript" src="@Url.Content("/Scripts/jquery.tablesorter.min.js")"></script>
    <script type="text/javascript" src="@Url.Content("/Scripts/Custom/Roster.js")"></script>
}

To make this short I basically want to do something like this in Spring MVC using Apache Tiles. Is it even possible?

My initial thought and attempt was to create a "bundle" as a definition in the tiles config file but then there needs to be some JSP code to insert and create the html syntax properly. Has anyone ever attempted this before or found a good solution?

I found this example at http://www.coderanch.com/how-to/java/TilesJavaScript but it doesn't seem to be syntactically correct for Tiles 3.

master-layout.jsp

">

Here's how you'd do it for multiple js files:

tiles-defs.xml


    <!-- Child page Definition --> 
    <definition name="child.page" extends="master.page">    
        <put name="title" value="Child Page" /> 
        <put name="jsfile" value="app.childpage.jsfiles.tile" />
    </definition>

    <!-- JS Files Definition tile -->

    <definition name="app.childpage.jsfiles.tile" path="/layouts/jslayout.jsp">
        <putList name="jsfilesList">
            <add value="/config/childpage_jsfile1.js"/>
            <add value="/config/childpage_jsfile2.js"/>
            <add value="/config/childpage_jsfile3.js"/>
        </putList>
    </definition>

jslayout.jsp

<tiles:useAttribute id="list" name="jsfilesList" classname="java.util.List" />
<c:forEach var="jsfileName" items="${list}">
    <script src="<%=request.getContextPath()%><c:out value='${jsfileName}' />"></script>
</c:forEach>

Essentially I want a clean way to include all my JavaScript and CSS using Apache Tiles similar to the ASP.NET MVC bundle method. This way I'm not having to hard code the links into every single JSP file that needs something additional.


Solution

  • For anyone who is interested this is how I ended up implementing it. I did this using Tiles 3, I'm not sure if the syntax is different in previous versions of Tiles. It seems to work pretty well.

    layout.xml

    <!-- templates -->
    <definition name="base" template="/WEB-INF/views/templates/template.jsp">
        <put-attribute name="title" value=""></put-attribute>
        <put-attribute name="header" value="/WEB-INF/views/tiles/shared/header.jsp"></put-attribute>
        <put-attribute name="content" value=""></put-attribute>
        <put-attribute name="footer" value="/WEB-INF/views/tiles/shared/footer.jsp"></put-attribute>
        <put-list-attribute name="javascripts">
            <add-attribute value="/static/javascript/modernizr.js" />
            <add-attribute value="/static/jquery/jquery-2.1.0.min.js" />
            <add-attribute value="/static//bootstrap/js/bootstrap.min.js" />
        </put-list-attribute>
        <put-list-attribute name="stylesheets">
            <add-attribute value="/static/bootstrap/css/bootstrap.min.css" />
            <add-attribute value="/static/stylesheets/global.css" />
        </put-list-attribute>
    </definition>
    
    <!-- HomeController  -->
    <definition name="home/index" extends="base">
        <put-attribute name="title" value="Home"></put-attribute>
        <put-attribute name="content" value="/WEB-INF/views/tiles/home/home.jsp"></put-attribute>
    </definition>
    
    <!-- LoginController -->
    <definition name="login/login" extends="base">
        <put-attribute name="title" value="Login"></put-attribute>
        <put-attribute name="header" value=""></put-attribute>
        <put-attribute name="content" value="/WEB-INF/views/tiles/user/login.jsp"></put-attribute>
        <put-attribute name="footer" value=""></put-attribute>
        <put-list-attribute name="stylesheets" inherit="true">
            <add-attribute value="/static/stylesheets/sign-in.css" />
        </put-list-attribute>
    </definition>
    
    <!-- UserController -->
    <definition name="user/list" extends="base">
        <put-attribute name="title" value="Users"></put-attribute>
        <put-attribute name="content" value="/WEB-INF/views/tiles/user/list.jsp"></put-attribute>
    </definition>
    
    <definition name="user/add" extends="base">
        <put-attribute name="title" value="User - Add"></put-attribute>
        <put-attribute name="content" value="/WEB-INF/views/tiles/user/createOrUpdate.jsp"></put-attribute>
    </definition>
    
    <definition name="user/edit" extends="base">
        <put-attribute name="title" value="User - Edit"></put-attribute>
        <put-attribute name="content" value="/WEB-INF/views/tiles/user/createOrUpdate.jsp"></put-attribute>
    </definition>
    
    <!-- ErrorController -->
    <definition name="error/error" extends="base">
        <put-attribute name="title" value="Error"></put-attribute>
        <put-attribute name="content" value="/WEB-INF/views/tiles/error/error.jsp"></put-attribute>
    </definition>
    

    template.jsp

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
    
    <tiles:importAttribute name="javascripts"/>
    <tiles:importAttribute name="stylesheets"/>
    
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="author" content="XXXXXXXXXXX">
        <meta name="description" content="Something">
        <title><tiles:insertAttribute name="title"></tiles:insertAttribute></title>
        <!-- stylesheets -->
        <c:forEach var="css" items="${stylesheets}">
            <link rel="stylesheet" type="text/css" href="<c:url value="${css}"/>">
        </c:forEach>
        <!-- end stylesheets -->
    </head>
    <body>
    
        <!--[if lt IE 10]>
            <p class="alert alert-warning">
                Warning: You are using an unsupported version of Internet Explorer. We recommend using Internet Explorer
                10+. If you are a Windows XP user you'll need to download an alternative browsers such as FireFox, Chrome,
                Opera, or Safari. 
            </p>
        <![endif]-->
    
        <!-- header -->
        <div id="header">
            <tiles:insertAttribute name="header"></tiles:insertAttribute>
        </div>
        <!-- end header  -->
    
        <!-- content -->
        <div id="content">
            <tiles:insertAttribute name="content"></tiles:insertAttribute>
        </div>
        <!-- end content -->
    
        <!-- footer -->
        <div id="footer">
            <tiles:insertAttribute name="footer"></tiles:insertAttribute>
        </div>
        <!-- end footer -->
    
        <!-- scripts -->
        <c:forEach var="script" items="${javascripts}">
            <script src="<c:url value="${script}"/>"></script>
        </c:forEach>
        <!-- end scripts -->
    
    </body>
    </html>