Saturday, February 7, 2015

EE JSP: Generating Dynamic Content with JSTL Tag Libraries

Besides writing your own Custom Tags in JSP, you will find that Java EE actually provides a set of Java Standard Tag Library (JSTL) ready for you to use. These built-in tags include repeating (for-loop) tags, if condition tags, variable declaration and output tags etc. The Libraries also come with many utility functions and international message formatting tags. Here is an example how it looks like.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
    <body>
        <h1>JSTL Examples</h1>
        <h2>List of Application Context: ${applicationScope}</h2>
        <table>
            <c:forEach var="entry" items="${applicationScope}">
            <tr>
                <td>${entry.key}</td>
                <td>
                    <c:out value="${entry.value}"/>
                </td>
            </tr>
            </c:forEach>
        </table>
       
        <h2>List of Session Context: ${sessionScope}</h2>
        <table>
            <c:forEach var="entry" items="${sessionScope}">
            <tr>
                <td>${entry.key}</td>
                <td>
                    <c:out value="${entry.value}"/>
                </td>
            </tr>
            </c:forEach>
        </table>
       
        <h2>List of Page Context: ${pageScope}</h2>
        <table>
            <c:forEach var="entry" items="${pageScope}">
            <tr>
                <td>${entry.key}</td>
                <td>
                    <c:out value="${entry.value}"/>
                </td>
            </tr>
            </c:forEach>
        </table>
       
        <h2>List of Request Context: ${requestSope}</h2>
        <table>
            <c:forEach var="entry" items="${requestSope}">
            <tr>
                <td>${entry.key}</td>
                <td>
                    <c:out value="${entry.value}"/>
                </td>
            </tr>
            </c:forEach>
        </table>
       
        <h2>List of Query Parameters: ${param}</h2>
        <table>
            <c:forEach var="entry" items="${param}">
            <tr>
                <td>${entry.key}</td>
                <td>
                    <c:out value="${entry.value}"/>
                </td>
            </tr>
            </c:forEach>
        </table>
       
        <h2>List of Header Parameters: ${header}</h2>
        <table>
            <c:forEach var="entry" items="${header}">
            <tr>
                <td>${entry.key}</td>
                <td>
                    <c:out value="${entry.value}"/>
                </td>
            </tr>
            </c:forEach>
        </table>       
       
        <h2>List of Cookies: ${cookie}</h2>
        <table>
            <c:forEach var="entry" items="${cookie}">
            <tr>
                <td>${entry.key}</td>
                <td>
                    <c:out value="${entry.value}"/>
                </td>
            </tr>
            </c:forEach>
        </table>
    </body>
</html>


I used the core tag here to display map entries of few implicit variables. You may explore more on those tags declarations I have define on top of the example page from the Spec. These code are from the jsp-example from GitHub.

GLASSFISH NOTE: When deploying above example in GlassFish 3/4, you will run into a NullPointerException and causing the page resulted in error. It turns out that GF server added a internal variable named com.sun.jsp.taglibraryCache  in ServletContext (Application Scope) that throws NPE when its toString() is called! To workaround this, I created jstl-example2.jsp that wraps the ${entry.value} into a custom JSTL function so that it guarantees to return an output without throwing exception. So the lesson learned is that you should always return a String and not throw Exception when overriding toString() of a Java class. It's just bad practice.


Tuesday, February 3, 2015

EE JSP: Generating Dynamic Content with Custom Tag Libraries

When developing View layer in a web application, you want to try not to duplicate content in JSP files as much as possible. The JSP spec API allows you to reduce this duplication by using tag libraries. A custom JSP tag is a user defined xml tag element that you can insert into JSP file to replace with some dynamic content.

Here is an simple jsp-example using a custom JSP tag that insert a server time stamp value:

<%@ taglib prefix="myapp" tagdir="/WEB-INF/myappTags" %>
<!DOCTYPE html>
<html>
    <body>
        <h1>Hello World!</h1>
        <p>Page served on <myapp:serverTime pattern="yyyy-MM-dd HH:mm:ss"/></p>
    </body>
</html>


JSP tags can also allow you to pass in parameters as attributes of the tag. In the example above <myapp:serverTime> tag uses a custom pattern attribute to control how the date string should be formatted.

JSP tags can also be nested with sub tags, or any HTML content elements. The nested JSP tags can provide a way for you to conditionally render the enclosed content. Using tag to render conditional content is more verbose due to XML structure, but it eliminates the use of direct Scriptlet code in JSP.

There are two ways you can create custom JSP tags. The first method is to implement the tag using pure Java code and then register it with a XML taglib definition file. I will skip this method for now and show you another easier way.

The second method uses "Tag Files" that are similar to JSP pages to construct a tag (remember that JSP tag is nothing more than just a placeholder for some content!). I am going to show you how the second method is done for above example. First create a serverTime.tag file under your src/main/webapp/WEB-INF/tags/myapp project folder.

<%@ attribute name="pattern" required="true" %>

<%@ tag import="java.util.Date, java.text.SimpleDateFormat" %>
<%= new SimpleDateFormat(pattern).format(new Date()) %>


The Tag File implementation depends on simple convention of file naming and location. Note that the src/main/webapp/WEB-INF/tags directory is a required path. Inside this folder,  you may create any sub folder you want to organize the tag files. In our case, it's the myapp directory. A Tag File can be just like any JSP file you would normally create, except the tag directives are little different. You can see the JSP spec for a complete list of them. Whatever you output from the Tag File, it will be inserted and replaced the caller of the tag. Notice how I use the pattern attribute parameter to allow user change the date pattern, and it's available in the Tag File inside the Scriptlet Java code as variable.

Since you can write Tag Files just as you would with JSP, I will again caution the excessive use of Java code Scriptlet even inside Tag Files. If you must call Java code, try to wrap the code and replace by single line call, or write the Tag implementation with pure Java code; especially if you have very complex business logic involve. This would bring debugging much easier on your code and to maintain.

JSP tags provide a powerful way to construct your View layer in the web application. It helps you reuse code or content, and generating a specific piece of response.