Templates in 10 minutes with JSP and tag files
Have you ever seen JSPs full of Aramaic-like scriptlets, crazy includes, duplicated code and no taglibs beyond that provided by the web framework in use? Are you staring at one right now?
This is a fairly common thing, at least for the companies I worked for so far, and that’s what scares me the most. Hopefully, you can easily make things better if you want to.
In this post, I’ll show you a few techniques that can be used to write clean JSPs without resorting to any kind of templating system whatsoever.
An example
The first step is to define the base template for the application pages. Consider the following XHTML example and its graphic representation:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta name="keywords" content="keyword1, keyword2, keyword3" /> <meta name="description" content="Page description" /> <title>Page title</title> <!-- Essential scripts --> <link rel="stylesheet" type="text/css" href="css/style.css"/> <script type="text/javascript" src="js/query.js"></script> <!-- Extra header --> <script type="text/javascript" src="js/util.js"></script> </head> <body> <!-- Main --> <div id="wrapper"> <div id="header"></div> <div id="content"></div> <div id="footer"></div> </div> <!-- Main --> <script type="text/javascript"> // Other scripts (e.g. Google Analytics) </script> </body> </html>
What usually happens, even with a simple template such as this, is a high level of code duplication among the different pages due to the heavy use of Copy and Paste Programming:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta name="keywords" content="keyword1, keyword2, keyword3" /> <meta name="description" content="Page description" /> <title>Page title</title> <!-- Essential scripts --> <jsp:include page="scripts.jsp"/> <!-- Extra header --> <script type="text/javascript" src="js/util.js"></script> </head> <body> <!-- Main --> <div id="wrapper"> <jsp:include file="header.jsp"/> <div id="content">Page content here</div> <jsp:include page="footer.jsp"/> </div> <!-- Main --> <script type="text/javascript"> // Other scripts </script> </body> </html>
See? Why break the template into small pieces if you are going keep duplicating code anyway? The best thing to do is to translate that template into something like this:
<%@ taglib tagdir="/WEB-INF/tags/layout" prefix="layout" %> <layout:page title="Title" description="Page description" keywords="keyword1, keyword2, keyword3"> <jsp:attribute name="extraHeader"> <script type="text/javascript" src="js/util.js"></script> </jsp:attribute> <jsp:attribute name="extraBottom"> // Other scripts (e.g. Google Analytics) </jsp:attribute> <jsp:body> Page content here </jsp:body> </layout:page>
Content reuse with tag files
There are three types of JSP tags, each with its own strengths and weaknesses: classic tag handlers, simple tag handlers and tag files. Today I’ll cover the basics of tag files, but every Java developer should learn when and how to use the other two.
The first thing we need to do is create the WEB-INF/tags/layout directory, which will keep the tag files we are about to create. Now, create two files inside this directory, one for the header and the other for the footer:
header.tag
<%@ tag body-content="empty" description="Header tag file" %> <div id="header"> <!-- Header section here --> </div>
footer.tag
<%@ tag body-content="empty" description="Footer tag file" %> <div id="footer"> <!-- Footer section here --> </div>
As we can see, tag files are just like JSPs, but with some special properties.
The last tag file, page.tag, defines the overall page structure:
<%@ tag description="Page layout" %> <%@ attribute name="title" required="true" description="Page title" %> <%@ attribute name="keywords" required="true" description="Page keywords to improve SEO" %> <%@ attribute name="description" required="true" description="Page description" %> <%@ attribute name="extraHeader" fragment="true" description="Extra code to put before </head>" %> <%@ attribute name="extraBottom" fragment="true" description="Extra code to put before </body>" %> <%@ taglib tagdir="/WEB-INF/tags/layout" prefix="layout" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <!-- Displaying the attributes using EL --> <meta name="keywords" content="${keywords}" /> <meta name="description" content="${description}" /> <title>${title}</title> <!-- Essential scripts --> <link rel="stylesheet" type="text/css" href="css/style.css"/> <script type="text/javascript" src="js/query.js"></script> <!-- Process the given input fragment --> <jsp:invoke fragment="extraHeader"/> </head> <body> <!-- Main --> <div id="wrapper"> <!-- Renders the page header --> <layout:header/> <!-- Renders the tag body inside a DIV --> <div id="content"><jsp:doBody/></div> <!-- Renders the page footer --> <layout:footer/> </div> <!-- Main --> <!-- Process the given input fragment --> <jsp:invoke fragment="extraBottom"/> </body> </html>
This last tag file is more complex than the other two, because you can pass to it both values and fragments. Besides, this tag accepts a body, which gets executed with <jsp:doBody/>.
Of course, the example shown here is fairly simple, so we didn’t have to use more advanced features like variables and dynamic attributes. Be that as it may, it’s a good idea to know what the technology has to offer. You’ll never know when a feature will be useful until you need it.
Usage
Now, let’s put those tag files to use:
<%@ taglib tagdir="/WEB-INF/tags/layout" prefix="layout" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <layout:page title="Index page" description="This is the index page of my amazing app" keywords="amazing, app"> <jsp:attribute name="extraHeader"> <script type="text/javascript" src="js/util.js"></script> <script type="text/javascript" src="js/some_jquery_plugin.js"></script> </jsp:attribute> <jsp:attribute name="extraBottom"> $(function() { // Call some JQuery function here, specific for this page }); </jsp:attribute> <jsp:body> Welcome to my amazing app!<br/> 1+1 = ${1+1} <ul> <c:forEach items="${objects}" var="obj"> <li>${obj.attr}</li> </c:forEach> </ul> </jsp:body> </layout:page>
Although the application as a whole follow the same visual standard, each page may need additional resources (JavaScript, CSS, etc.). This is hardly a problem because our template allows us to include extra content if necessary.
The other advantage is that tag files allow the use of custom tags and unified EL, but deny the use of scriptlets, which is a good thing if you want to get rid of messy JSPs.


