Some of the most important possibilities are:
- Generating HTML output
This is the simplest use of custom tags. It has some merit in that a standard building block is available, and can be changed simultaneously everywhere it occurs if necessary. However, in general, using Java code to generate HTML is clumsy and inflexible.
- Using template content to generate HTML output
A more sophisticated variant of the above, avoiding having messy markup generation in Java code and allowing modification of the generated markup without recompilation. Usually a mechanism will need to be designed and documented for controlling variable substitution and any other ways in which the template is made dynamic. An abstract class extending TagSupport or BodyTagSupport could provide standard template lookup and variable interpolation for use across a system. This is a common idiom, and can be very useful in real-world systems.
- Defining scripting variables
This is often a superior alternative to using tags to generate markup directly, especially when iteration is concerned. All computations and control flow is controlled by the tag handler classes, rather than the calling JSP, but the scripting variables are used within the JSP to allow markup generation to be changed easily. As a general rule, tags that define variables should not generate markup.
- Transforming or interpreting tag body content
This is an especially powerful use of tag extensions, with virtually unlimited potential. For example, a tag could establish a database connection and execute SQL contained in its body to display the results. A tag could implement an interpreter for a language, providing entirely new syntax and functionality within JSPs. (For example, it would be conceivable to design an asp tag that would interpret a subset of ASP for running legacy code.) In some of these cases, the tagdependent value should be used to describe the body content in the TLD.
Note that some of the possibilities of this idiom are not compatible with writing maintainable code. JSP is a standard, understood by a whole development community, whereas your tag content may not be, unless you choose some other standard such as SQL. It is also possible to create nested tags that interact in surprising ways; this also reduces readability.
- A gatekeeper role
A custom tag can check for login or some other condition, and redirect the response if the result is unsatisfactory.
q Concealing access to enterprise objects or APIs that should not be visible from JSPs
This is an easy way of providing a JSP interface to enterprise data. However, note that it is not consistent with good J2EE design to write tags that access databases via JDBC. Consider the alternative of a true n-tier architecture, in which the tag handlers access business objects such as session EJBs.
- Exposing complex data
Custom tags can be used to expose data (for example, in a list or table) that might otherwise require complicated JSP logic to display.
- Handling iteration
This is a simple and practical way of avoiding a profusion of scriptlets in JSPs. In this case it is especially important to make tags as generic as possible.
Remember that custom tags are building blocks, and will be most useful when they can be reused easily. The following principles help to make tag extensions reusable:
- Make tags as configurable as possible. This can be achieved through tag attributes and using nesting to provide context. Optional attributes can be used where default values can be supplied.
- Avoid generating HTML in your tag handler unless absolutely necessary.
- When tags handlers must generate HTML, ensure that the generated HTML can be used in a wide variety of contexts: try to avoid <html>, <form>, and other structural tags. Consider reading the HTML from a template file.
- Avoid making custom tags do unexpected things to the request and response. Just because tag handlers can access these objects through the PageContext does not mean it's a good idea. For example, how obvious will it be to a reader of a JSP using a custom tag that the tag may redirect the response? Unless the tag's documentation is scrupulous, figuring this out might require plunging into the tag's Java implementation. Consider another example: if a tag were to flush the JSP's output buffer, the JSP engine would be unable to redirect to an error page if anything went wrong in the rendering of the rest of the JSP. (The page would be in an illegal state, attempting redirection after it had written to the HTTP response.) This would limit the usefulness of the tag and, again, the behavior would be a challenge for a JSP developer to figure out.
When and how to use tag extensions is further discussed in Chapter 14, Writing Maintainable JSP Pages. Remember, however, that some caution is called for in using custom tags. Using too many tag extensions can make JSPs unreadable: the end result will be your own language, which may be the most efficient approach to solving a particular problem, but won't be intelligible to an outside observer, especially if your tags cooperate in complex ways.
Summary
JSP 1.1 tag extensions, or custom tags, are a powerful extension to the JSP model. Their use is limited only by the ingenuity of developers, and they will become an essential building block of well-engineered JSP interfaces.
Tag extensions can access the JSP PageContext. Their behavior can respond dynamically to the XML attributes they are invoked with, and their body content. They are implemented using:
- Java classes implementing tag behavior
- XML Tag Library Descriptor (TLD) files describing one or more tags, and the attributes they require
- Optional extra classes defining scripting variables introduced into the page by the custom tag
Tag extensions are a valuable way of separating presentation from content in JSP interfaces. Since they are a standard part of JSP 1.1, libraries of third party tags can be developed, and will become increasingly valuable building blocks in JSP development.
Importantly, tag extensions are very easy to develop, once the initial concepts are grasped. The tag extension mechanism achieves the goals expressed in the JSP 1.1 specification, that it should be portable, simple, expressive, and built upon existing concepts and machinery.