ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

JSP 1.2: Great News for the JSP Community, Part 2
Pages: 1, 2, 3

Reset per-invocation state

A tag handler may create or collect data that is only valid for one invocation. One example is a list of values set by custom actions nested in the body of the main action:



<demo:redirect>
  <demo:param name="foo" value="bar" />
  <demo:param name="fee" value="baz" />
</demo:redirect>

In this example, the nested param actions call a method in the tag handler for the parent redirect action to add the parameter to a list that is then used in the redirection URL:

private ArrayList params;
 ...
public void addParam(Param param) {
    if (params == null) {
    params = new ArrayList();
    }
params.add(param);
}

If the container decides to reuse this tag handler, the list will grow for each invocation unless you reset it at some point. There's no guarantee that the doEndTag() method is called (in case of an exception in the body), so the best place to reset the list is in the doStartTag() method:

public int doStartTag() throws JspException {
  // Reset per-invocation state
  params = null;
   ...
}

This approach works fine for objects that can hang around until the tag handler is used again. But what if you need to use an expensive resource, such as a database connection, that must be released (or returned to a pool) as soon as possible? That's when the new TryCatchFinally interface comes in handy. Say you have a custom action that provides a database connection for a set of nested custom actions that performs database operations that must be executed as part of the same database transaction:

<demo:sqlTransaction dataSource="myDataSource">
  <demo:sqlUpdate>
    UPDATE Account SET Balance = Balance - 1000
WHERE AccountNumber = 1234
  </demo:sqlUpdate>
  <demo:sqlUpdate>
    UPDATE Account SET Balance = Balance + 1000
WHERE AccountNumber = 5678
  </demo:sqlUpdate>
</demo:sqlTransaction>

Here the tag handler for the sqlTransaction action gets a Connection from the specified DataSource and makes it available to the nested actions through a getter method. If any exception occurs while processing a nested action, the sqlTransaction tag handler must roll back the transaction. No matter what happens, the tag handler must always close the Connection (returning it to the pool, if it's a pooled DataSource).

By implementing the TryCatchFinally interface for the sqlTransaction tag handler, this is easy to accomplish:

public class SqlTransactionTag extends TagSupport,
    implements TryCatchFinally {
    
      private java.sql.Connection conn;
 ...
public void doCatch(Throwable t) throws Throwable {
    conn.rollback();
    throw t;
}

public void doFinally() {
    // Close or return to pool if pooled
    conn.close();
  }
}

The doCatch() method rolls back the transaction and doFinally() closes the Connection, no matter if an exception was thrown or not.

Keep expensive resources for the lifetime of the tag handler object

Some objects used by a tag handler can be expensive to create, such as a java.text.SimpleDateFormat instance or an XML parser. Instead of creating objects like this every time the tag handler is invoked, it's better to create them once when the tag handler itself is created or the first time it's used. The place to get rid of objects like this is in the release() method:

private java.text.SimpleDateFormat dateFormat =
   new java.text.SimpleDateFormat();

 ...
public void release() {
    dateFormat = null;
}

The release() method is only called just before the container gets rid of the tag handler, to let it do this kind of cleanup. It is never called between invocations.

Tag Library Descriptor (TLD) changes

Besides the new elements for validators and listeners described earlier, JSP 1.2 introduces a number of other changes and additions to the TLD.

First of all, some elements have been renamed for consistency with the naming conventions used in other J2EE descriptor files. More precisely, hyphens are now used to separate words in element names, and the <info> element has been replaced with an element used for the same purpose in other descriptors. The following table summarizes these name changes:

JSP 1.1 JSP 1.2
<tlibversion> <tlib-version>
<jspversion> <jsp-version>
<shortname> <short-name>
<info> <description>
<tagclass> <tag-class>
<teiclass> <tei-class>
<bodycontent> <body-content>

A number of new elements have also been added to allow more descriptive information in the TLD. This information may be used by page-authoring tools and also by tools that generate user documentation from the TLD:

New element Description
<display-name> Used to specify a short name displayed by tools. This element can be used as a subelement of the <taglib> and <tag> elements.
<small-icon> and <large-icon> Used to specify icons displayed by tools. The values are paths to files containing either GIF or JPEG images. Both elements can be used as subelements of the <taglib> and <tag> elements.
<example> Used to include an example of how a tag can be used. This element can only be used as a subelement of the <tag> element.
<type> Used to specify the type of a request-time attribute value. This element can only be used as a subelement of the <attribute> element.

Finally, the new <variable> element can be used to declare scripting variables introduced by a tag. In JSP 1.1, you had to create a TagExtraInfo class for the tag and let the getVariableInfo() method return information about the variables. By using the new <variable> element, you can avoid creating a TagExtraInfo class for this purpose in most cases:

<tag>
  <name>myTag</name>
  <tag-class>com.foo.MyTag</tag-class>

  <variable>
    <name-given>foo</name-given>
    <variable-class>String</variable-class>
    <declare>true</declare>
    <scope>AT_END</scope>
    <description>This variable contains ...</description>
  </variable>
    ...
</tag>

In this example, the myTag custom action introduces a scripting variable named foo of type String. The container is asked to create a variable declaration (declare is true) for this variable after the end tag (scope is AT_END). The other valid values for the <scope> element are AT_BEGIN and NESTED, exactly the same as in a TagExtraInfo class.

As an alternative to declaring a hard-coded variable name, like foo in this example, you can let the variable name be specified by the page author through an action element attribute. To do so, replace the <name-given> element with the <name-from-attribute> element:

<variable>
  <name-from-attribute>id</name-from-attribute>
   ...
</variable>

With this declaration, the container uses the value of the id attribute as the variable name instead.

Conclusion

Related Reading

JavaServer PagesJavaServer Pages
By Hans Bergsten
Table of Contents
Index
Sample Chapter
Full Description
Read Online -- Safari

In this article I have described JSP 1.2's most important new features, fine-tuning, and clarifications. I have also showed you examples of how to use the new stuff and what to watch out for. You're now ready to try it out on your own. I suggest you download Tomcat 4.0 and play around with it to see how you can best take advantage of JSP 1.2 in your own application.

Resources


Hans Bergsten is the founder of Gefion Software and author of O'Reilly's JavaServer Pages, 3rd Edition.


Return to ONJava.com.