Ursine rambling and grumbling

In a recent thread in the JavaRanch JSP forum, the subject of JSP 2.0 tag files came up, and there was much teeth-gnashing over the fact that this wonderful mechanism was not available for JSP 1.2 environments.

As anyone who's followed my posts in that forum would be aware, I detest putting HTML markup in Java code almost as much as I hate putting Java code in JSP pages. So while I was working in the JSP 1.2 environement I came up with a mechanism that allowed me to easily include JSP fragments from the Java code of tag handlers.

I dubbed this mechanism "taglets" and, for those who must still operate within the JSP 1.2 environment for the time being, I figured I'd present that mechanism here.

The TagletTagSupport Class

The major component of the taglet mechanism is a fairly simple base class that tag handlers extend (in lieue of TagSupport) that provides a protected method to include a named resource. It's fairly simple (the most complicated part being the conversion of exceptions) and is presented below in its entirety:

package org.bibeault.tags;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * Tag support class that enables deriving tags handlers to emit 'taglets':
 * JSP fragments that can be used to emit markup from a tag without having to
 * build the markup in Java code.
 *
 * The emitting tag is made available to the taglet via the key defined by
 * KEY_EMITTING_TAG.
 */
public class TagletTagSupport extends TagSupport {
    
    public static final String KEY_EMITTING_TAG = "emittingTag";
    
    /**
     * Includes the JSP fragment identified by the passed resource. By convention
     * such resources are usually stored in /WEB-INF/taglets
     *
     * @param resource the context-relative path to the JSP fragment resource
     */
    protected void includeTaglet( String resource ) throws JspException {
        pageContext.setAttribute( KEY_EMITTING_TAG, this, PageContext.REQUEST_SCOPE );
        try {
            pageContext.include( resource );
        }
        catch (IOException e) {
            throw new JspException( "I/O error including taglet with resource of " + resource + ": " + e.getMessage(), e );
        }
        catch (ServletException e) {
            Throwable rootCause = (e.getRootCause() != null) ? e.getRootCause() : e;
            throw new JspException( "Error including taglet with resource of " + resource + ": " + rootCause.getMessage(), rootCause );
        }
    }
    
}

Note that the includeTaglet() method establishes the emitting tag as a request-scoped variable named emittingTag. This makes it really easy to use the JSTL and EL in the taglet to obtain any attributes of the tag that are exposed as properties.

A Simple Example Tag

The ExampleTagletTag is a simple example of a taglet-enabled tag that has a single attribute that it passes to its taglet fragment:

package org.bibeault.tags;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;

/**
 * Simple sample tag using the taglet support base class. A single tag attribute
 * named whatever is passed to the taglet as a scoped variable.
 * This attribute is also exposed as a property should the taglet prefer to
 * reference the attribute value via the EL.
 *
 * Note: in a non-example class I would never hard-code the path to the resource
 * as done here. Rather, I'd get the base path to the taglet resource from a
 * context variable or other such property.
 */
public class ExampleTagletTag extends TagletTagSupport {
    
    public static final String KEY_WHATEVER = "whatever";
    
    private String whatever;
    
    public void setWhatever( String value ) { this.whatever = value; }
    public String getWhatever() { return this.whatever; }
    
    public int doStartTag() throws JspException {
        pageContext.setAttribute( KEY_WHATEVER, this.whatever, PageContext.REQUEST_SCOPE );
        includeTaglet( "/WEB-INF/taglets/example-tag.jsp" );
        return EVAL_BODY_INCLUDE;
    }
    
}

The Simple Example Taglet

A super-simple example of how the taglet file example-tag.jsp could be implemented is:

<%--
  Simple example taglet for the ExampleTagletTag tag handler. Normally I would
  use the JSTL and EL in such files, but for simplicity this example sticks
  to scriplet expressions.
--%>
<%@ page import="org.bibeault.tags.ExampleTagletTag" %>

<div>
  This could be any markup you want it to be.
</div>
<div>
  The value of the <b>whatever</b> attribute is: <%= request.getAttribute( ExampleTagletTag.KEY_WHATEVER ) %>
</div>

Alternatively, and preferably, the taglets would utilize the JSTL and EL rather than scriplet expressions (but I didn't want to cloud this example with JSTL setup). Under JSTL, accessing the attribute would become:

<c:out value="${emittingTag.whatever}"/>

and it would not have been necessary for the ExampleTagletTag class to export the attribute as a scoped variable.

Using the Simple Example Tag

Assuming we brought the TLD for the tag set containing our example tag into a page using the prefix xyz and the tag name example, using the tag is as simple as:

<xyz:example whatever="Hi there!"/>
    

which results in the following on the page:

This could be any markup you want it to be.
The value of the whatever attribute is: Hi there!
    

Why do not use tag files in this case?

Quote: <em>Why do not use tag files in this case? </em>

Tag files are not available under JSP 1.2. That's the whole point. Tag files are wonderful, but not everyone is able to upgrade to JSP 2.0 at this time.

What is the point of using such technik??
Any real-life example?
Really, don't understand what "taglets" for :((

"taglets" are for when you want to use JSP and markup for the output of your custom tag rather than using StringBuffers in Java to build up HTML and JSP markup.

I really dislike seeing Java in JSP pages, and I equally dislike seeing HTML in Java code.

If building markup in strng buffers doesn't violate your sensibilities like it does mine, this technique may not be of value to you.

Very cool. I love tag files on my server running Tomcat 5. But on the Tomcat 4 server (can't upgrade just yet), this will make my life easier for now. Thanks!
brilliant! Just what I need.
Exactly what I was looking for. This will save me several headaches. Thanks!


Add a comment

Title
Body
HTML : b, i, blockquote, br, p, pre, a href="", ul, ol, li
Math Quiz 1 + 4 = (Helps stop blog spam)
Name
E-mail address
Website
Remember me Yes  No 

E-mail addresses are not publicly displayed, so please only leave your e-mail address if you would like to be notified when new comments are added to this blog entry (you can opt-out later).

TrackBack to http://radio.javaranch.com/bear/addTrackBack.action?entry=1106722509000