Use the power of JSP tag files in OpenCms
Since version 7 OpenCms is a Servlet 2.4 and JSP 2.0 conforming application. In addition to the improved expression language (EL) JSP 2.0 also brings in the possibility of developing custom tags(actions) using JSP rather than writing Java code. This allows for some pretty neat things and enables you to go one step further towards cleaner view code. I’ve used this in one of my last projects extensively to refactor common code like pagers and link generation. For example:
<cms:include file="/system/modules/com.example.ocms.commons/elements/pager">
<cms:param name="currentPage">
<c:out value="${model.currentPage}"/>
</cms:param>
<cms:param name="pageCount">
<c:out value="${model.pageCount}"/>
</cms:param>
</cms:include>
Became:
<wt:pager model="${model}"/>
Not does it only look cleaner and is much more focused, it also decouples your view more from the underlying CMS solution. Of course you could also develop a custom tag library using Java (which I have done a few times) but using a JSP the advantage that code can be changed on the fly and even from a web designer. You can always refactor your JSP taglib into a Java one if you need to do it. There are some limitations of JSP tag files (like you can’t use scriptlets in the body) but they are easy to get around.
But as always: This is no silver bullet. There are problems with tag files which may not be obvious at the first glance.
How to create a tag
Creating a tag is easy. I will show you the necessary steps while developing a tag which allows the user to loop over the contents of an OpenCms VFS directory.
Preparing your module
As normal Java libraries too, JSP tags need to be exported into the filesystem to be read by the Servlet-Container. Normally the tag files reside under a directory like ${yourwebapp}/WEB-INF/tags/mylibrary. So what we will do is adding a new export point to the module containing our tag files.
First we create a new directory called tags inside the module we want to contain our tags (normally I create a module for each site). The resulting structure will look something like this
Then we open the module administration and add an export point to our module (Administration -> Module Management -> Edit Your module -> Module exportpoints -> New exportpoint).
After pressing OK we are well prepared to add custom tags to our OpenCms module.
Creating the tag file
We now create a directory for our taglib. This will be located inside our newly created tags folder. Because we want to create a tag which interacts with the OpenCms VFS we will simply call the folder vfs. Inside this directory we create a new JSP resource called directoryLoop.tag. The result should look something like this:
Now it’s time to write some code
.
Writing the tag file
I don’t want to go into the details of developing tag files in general. This topic has been covered by dozens of books and online tutorials. I have collected some links in this blog post which explain the development of tag files in detail. Have a look at the section Further reading if you want to find out.
I will assume you’ve already developed JSP files inside OpenCms so I won’t explain the steps in detail. If you have questions regarding the sourcecode simply post a comment.
Here’s the commented sourcecode for our tag file.
<%@ tag body-content="scriptless" %>
<%@ tag import="org.opencms.jsp.*,
org.opencms.file.*,
java.util.*" %>
<%@ attribute name="folder" required="true" %>
<%@ variable name-given="resource" scope="NESTED" %>
<%@ variable name-given="status" scope="NESTED" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%
// First we get the pageContext variable.
// Tag files only have an explicit JspContext but in this case
// it is a PageContext which is a subclass of JspContext.
PageContext pageContext = (PageContext)jspContext;
// Instantiate the usual CmsObject to access OpenCms data
CmsJspActionElement cmsa = new CmsJspActionElement(pageContext ,request,response);
CmsObject cmso = cmsa.getCmsObject();
// Read the resources, note that we can access the tag
// parameters using the pageContext.
String folder = (String) pageContext.getAttribute("folder");
folder = cmso.getRequestContext().removeSiteRoot(folder);
List resources = cmso.readResources(folder,CmsResourceFilter.DEFAULT,false);
// We store the list of resources in the pageContext for usage with JSTL
pageContext.setAttribute("resources",resources);
%>
<c:forEach var="resource" items="${resources}" varStatus="status">
<jsp:doBody/>
</c:forEach>
As you can see the tag file looks like a usual JSP file with only a few differences.
The tag exports two variables: The current resource and the iteration status. These can be accessed from the invoking JSP. We will make use of this in the next example.
To use the tag you have to publish the file so it gets written to the file system. After you’re finished writing/modifying the tag: Don’t forget to publish it!
You can’t preview tags, even though they are JSP files. You also won’t get compiler warnings. You always need a JSP file to test your tag files.
Using the created tag
We will use the created tag to implement a simple file browser. The file browser displays the contents of a folder and allows the user to navigate into subfolders recursively. Please note that this is definately no production ready code.
<%@ taglib prefix="vfs" tagdir="/WEB-INF/tags/vfs" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- Determine the current folder, set to "/" if no parameter given --%>
<c:set var="folder" value="${param.folder}"/>
<c:if test="${folder eq '' or folder == null}">
<c:set var="folder" value="/"/>
</c:if>
<html>
<head>
<style type="text/css">
.row-1 {
background-color: #ECECEC;
}
</style>
</head>
<body>
<h1>Resources of folder "${folder}"</h1>
<table>
<tr>
<th></th>
<th>Name</th>
<th>Size</th>
<th>Date created</th>
</tr>
<vfs:directoryLoop folder="${folder}">
<%-- We use the status for alternating row classes, useful for css --%>
<tr class="row-${status.count % 2}">
<td>
<%-- Display D for directory or F for file --%>
<c:choose>
<c:when test="${resource.folder}" >D</c:when>
<c:otherwise>F</c:otherwise>
</c:choose>
</td>
<td>
<%-- If the current resource is a folder, display a link --%>
<c:choose>
<c:when test="${resource.folder}" >
<a href="?folder=${resource.rootPath}">${resource.name}</a>
</c:when>
<c:otherwise>${resource.name}</c:otherwise>
</c:choose>
</td>
<td>
<%-- If the current resource is a file, display size --%>
<c:if test="${!resource.folder}">${resource.length}</c:if>
</td>
<td>${resource.dateCreated}</td>
<tr>
</vfs:directoryLoop>
</table>
</body>
</html>
As you can see the tags are included with the directive.
<%@ taglib prefix="vfs" tagdir="/WEB-INF/tags/vfs" %>
The usage of the tags is similar to normal tags with the exception that you can’t use scriptlets in the tag bodies. If the example is working you should see something like the following.
If you have trouble reading the above code. Here is a more condensed version of a file using the tag:
<%@ taglib prefix="vfs" tagdir="/WEB-INF/tags/vfs" %>
<ul>
<vfs:directoryLoop folder="/system/modules">
<li>${resource.name}</li>
</vfs:directoryLoop>
</ul>
Things to keep in mind
JSP tag files and OpenCms really are a nice fit, but before you start working on converting all your custom includes to tag files keep in mind some of the disadvantages of tag files in respect to using <cms:include>.
- Tag files are not seperated by online/offline. Since the tag files only get exported during publishing there is no way of developing the tags in the offline project. You always have to publish the tag file to see your changes (It’s like a normal, Java based, tag library). This means if you have an error in your code the live system will be affected by it. In my opinion this problem is not as big as it sounds. Tags are normally developed in a staged environment or on a developer machine and then deployed on the live server. Additionally they are no replacement for templates and therefore shouldn’t be changed often.
- Tag files are not cached. The output of a <cms:include> may be cached by the OpenCms FlexCache. This can speed up the rendering enormously, tag files are always processed. In my opinion this no big problem. Tag files will mostly always be used in JSP templates which in turn will be cached by the FlexCache. I would suggtest that tag files are used as the building blocks for JSP templates and therefore are one a finer granular level. The chunks you want to cache are normally much more coarse grained.
Finishing thoughts
In my opinion JSP tag files are a great thing. They can help you clean up messy JSP templates and nicely decouple your JSPs from OpenCms (although I used a pretty OpenCms heavy example in this post). I hope this post was useful and helped you adding another tool to your toolbox. If you have further questions or need help regarding a specific project, please leave a comment or contact me directly.
Further Reading
These tutorials can help you developing your own tag files or looking up classes used in this tutorial.
- The JEE 5 tutorial on creating tag files
- An online tutorial on JSP tag files by Oracle
- A java.net article on tag files, short and good
- The OpenCms JavaDoc, always handy
Tags: Development, Java, JSP, OpenCms, Sourcecode, Taglibs, Tutorial




