HOME  |    TRAINING  |   FREE TUTORIALS   |   JOBS
Find out more about our new RSS feed.
FREE Tutorial
JAVA SERVER PROGRAMMING TAG EXTENSIONS PART 3 - WRITING TAG EXTENSIONS

CATEGORY
SEARCH OUR OTHER TUTORIALS

DESCRIPTION

Once the initial concepts are grasped, implementing tag extensions is surprisingly easy.


This free tutorial is a sample from the book Professional Java Server Programming J2EE Edition.


Processing Attributes

Our simple example is all very well, but it doesn't take advantage of the dynamic potential of custom tags. We could interrogate the PageContext to implement context-specific behavior, but there are far better alternatives.

The easiest way to parameterize tags is to pass in XML attributes.

How do we make our tags handle attributes? The answer, not surprisingly, is that attributes in a TLD tag element map onto bean properties of the corresponding tag handlers. The mapping of attributes onto tag handler properties is, as we might expect, handled by the JSP engine using reflection and not only does it work with primitive types, we can pass any type to a tag handler. (Draft versions of the JSP 1.1 specification included a type subelement of the attribute TLD element; this has now been removed.)

Attributes can be either required or optional. This is specified in the TLD, as is whether attributes can take the value of JSP expressions at runtime, as we mentioned earlier.

Let's suppose we decide to pass a name as an attribute, and change our simple example to display the following:

First, we need to write a tag handler with a name property. With this minor change, it's pretty much like HelloTag:

package tagext;

import java.io.IOException;
import java.util.Date;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

// Hello tag accepting a name attribute.
public class AttribHelloTag extends TagSupport
{
private String name;

// Property getter for name 
public String getName() {
 return name;
}

// Property setter for name 
public void setName(String name) {
 this.name = name;
}

public int doEndTag() throws JspTagException {
 String dateString = new Date().toString();
 try {
  pageContext.getOut().write("Hello <b>" + name + "</b>.<br/>");
  pageContext.getOut().write("My name is " + getClass().getName() +
               " and it's " + dateString + "<p/>");
 }
 catch (IOException ex) {
  throw new JspTagException("Hello tag could not write to JSP out");
 }
 return EVAL_PAGE;
}
}

You should save this in WEB-INF/classes/tagext. Don't be tempted to omit the property 'getter', which at first sight seems unnecessary. The JavaBeans specification requires both getter and setter for a bean property, and some JSP engines may rely on the presence of both methods at translation time. (JRun 3.0, unlike Tomcat, seems to rely on getters to determine property types.) Now we must add a tag entry to our TLD describing the new tag, and specifying that it requires an attribute, name:

<tag>
<name>helloAttrib</name>
<tagclass>tagext.AttribHelloTag</tagclass>
<bodycontent>JSP</bodycontent>
<info>Simple example with attributes</info>
<attribute>
 <name>name</name>
 <required>true</required>
 <rtexprvalue>true</rtexprvalue>
</attribute>
</tag>

The JSP container will throw an exception if the required name attribute is not specified, and the attribute can be set with the runtime value of an expression, as well as with a static string (the value of rtexprvalue being true).

The calling JSP, hello2.jsp, is identical to hello.jsp, except for the way in which we invoke the tag itself:

<%@ taglib uri="/hello" prefix="examples" %>

<html>
<head>
 <title>Simple tag with attributes</title>
</head>
<body>
 This is static output.
<p />
<i>
 <examples:helloAttrib name="Rod">
 </examples:helloAttrib>
</i>

 This is static output again.
</body>
</html>

Attributes are an excellent way of controlling tag behavior at runtime, and are especially valuable in ensuring that tags are generic and reusable.

Elegant as the attribute/property mechanism is, there is one annoying problem with passing String attributes to tags. Specifying some characters in attributes is messy. The double quote character, for example, is (for obvious reasons) illegal in an attribute, and we must use the entity reference " if we want to include it. This rapidly becomes unreadable if the data includes multiple quotation marks. Attributes are also unsuited to handling lengthy values, for reasons of readability.

So there are limits to what can sensibly be achieved with attributes. Where complicated markup is concerned, consider the alternatives:

  • Processing markup and expressions in the body of the tag, possibly repeatedly
  • Defining a subtag that configures its ancestor. This is an advanced strategy, which we'll look at later in the following chapter
  • Implementing the tag to read its markup from a template file or URL

The most elegant of these solutions, where feasible, is to manipulate the tag body. This will only be useful if the tag defines scripting variables that the tag body can use.

There is a curious and confusing inconsistency in JSP syntax when non-String tag attributes are the results of JSP expressions. Let's suppose we want to pass an object of class examples.Values (a kind of list) to a tag extension. The syntax:

<wrox:list values="<%=values%>"

is problematic, because we know from the JSP specification that an expression "is evaluated and the result is coerced to a String which is subsequently emitted into the current out JspWriter object". In the case of the custom tag above, however, the value of the expression is not coerced to a String, but passed to the tag handler as its original type.

Body Content

So far we have used tags only to generate markup, we haven't considered what custom tags may do to their body content (anything found between their start and end tags).

Let's suppose we modify hello.jsp to add some code inside one of the tags, like this:

<examples:hello>
This is tag content!
</examples:hello>

The result, shown by tagcontent.jsp, is that the content we have added is output in addition to any output generated by the tag. Whether the content appears before or after the tag's output depends on whether we chose to do tag output in the doStartTag() or doEndTag() methods. In the case of the HelloTag, the output will appear before the tag's own output, as shown in tagcontent.jsp:

Tag content will be treated at run time as JSP (so long as the body content is set in the TLD to be JSP), so it may include expressions. Try modifying the last example like this:

<examples:hello>
This is tag content containing an expression: 37 * 16 = <%= 37 * 16 %>
</examples:hello>

Scriptlets are also legal, as is any other valid JSP content. The following will produce the same result:

<examples:hello>
<% int a = 37; %>
<% int b = 16; %>
This is tag content containing expressions and scriptlets:
<%=a%> * <%=b%> = <%= a * b %>
</examples:hello>

The output in either case as shown in tcexpr.jsp is:

To do anything really useful with body content, however, we need to make our tags define scripting variables, or manipulate body content.

Continued...


NEXT PAGE



7 RELATED COURSES AVAILABLE
INTRODUCTION TO JAVA PROGRAMMING
The aims of this Java training courses is to understand the role that Java plays on the Internet; describe the be....
JAVA (V1.2): ADVANCED PROGRAMMING
This course teaches the reader to learn, understand and become familiar with the advanced features of Java progra....
INTRODUCTION TO JAVABEANS
To go from the fundamentals of JavaBeans programming to the threshold of Advanced level. Gaining in depth progr....
C++ PROGRAMMING
Object oriented programming is fast becoming the leading software design methodology, with C++ becoming ever more....
C PROGRAMMING
This course is design to provide non-C programmers with the essential skills and knowledge necessary to allow the....
 
1 RELATED JOBS AVAILABLE
JAVA DEVELOPER MANCHESTER
Computer Futures Solutions are seeking a Senior Java Developer for their Manchester based client. You will be joi....
CONTACT US
Monday 6th October 2008  © COPYRIGHT 2008 - VISUALSOFT