Since my article "JSP Best Practices" first appeared in JavaWorld in late 2001, the use of JavaServer Pages (JSP) technology has grown dramatically. Numerous tools now make Webpage development with JSP technology easier than ever. The best practices I recommended in my previous article still apply. With new available features, tools, and JSP development ideas, however, you may employ several additional best practices for even smoother development of highly maintainable JSP-based applications. This article outlines some best practices that utilize the most significant new features, tools, and ideas:

Begin writing JSP documents

Employ JSP code conventions

Use the appropriate scope

Carefully manage session scope

Take advantage of JavaServer Pages Standard Tag Library (JSTL)

Take advantage of servlet filters (Intercepting Filter pattern)

Document the "APIs" of your JSP pages and documents

Precompile your JSP pages and documents

Organize your files and directories for easy development and deployment

Carefully consider using proprietary, vendor-specific features

Use Extensible Hypertext Markup Language (XHTML) syntax for HTML tags

Begin writing JSP documents rather than JSP pages

The JSP specification supports JSP pages as well as JSP documents. The main differentiator between the two is their level of XML compliance. JSP pages use the traditional or "shorthand" syntax, while JSP documents are completely XML-compliant. JSP documents are sometimes referred to as "JSP pages using XML syntax," but I will distinguish them here as JSP pages and JSP documents.

I prefer JSP documents for several reasons including:

You can easily verify JSP documents as well-formed XML/HTML.

You can validate JSP documents against an XML Schema.

You can readily write and parse JSP documents using standard XML tools.

You can readily write or present JSP documents in alternate forms using XSLT (Extensible Stylesheet Language Transformations). See the "JSP Documentation with XSLT" sidebar for an example.

JSP uses XML-compliant include and forward actions, as well as custom tags, so making the entire document XML-compliant leads to increased code consistency.

JSP documents require slightly more developer discipline than JSP pages, but your reward is more readable and maintainable documents, especially if you are new to JSP.

One significant disadvantage of JSP documents is that no XML-compliant version of JSP comments exists. A JSP document developer can use client-side (HTML-/XML-style) comments or embed Java comments in scriptlets, but there is no JSP document equivalent to <%-- -->. This is a disadvantage because the other two commenting styles JSP documents can use have their own drawbacks. You can see the client-side comments in the rendered page using the browser's View Source option. The Java comments in scriptlets require placing Java code directly in the JSP document.

Throughout the rest of this article, I refer generically to JSPs to imply both JSP pages and JSP documents, because the best practices I discuss generally apply to both JSP types.

Employ JSP code conventions

It is prudent on any project, using any language, to follow coding standards and conventions to improve development, maintenance, and testing of your software. Reading another developer's code is often neither simple nor enjoyable. Conversely, if all developers followed the same naming and other conventions, code review and maintenance would be easier for everyone involved, including the original developer.

Sun Microsystems has recently assisted organizations trying to create these conventions by making the document "Code Conventions for the JavaServer Pages Technology Version 1.x Language" freely available (see Resources). If your organization does not already follow JSP code conventions, I recommend using this document as a starting point. You can either use it as-is or build your own conventions around it.

Use appropriate scope for bound objects

The JSP specification supports four levels of scope (application, session, request, and page) that you can associate with objects created explicitly for JSPs to use. Because objects bound to any of these four scopes consume memory and, in some cases, require cleanup, it is best to use the appropriate scope for the task you want to accomplish.

Application scope

Application scope is the broadest scope and should only be used when necessary. You can create objects bound at application level in JSPs that are not session-aware, so application scope is useful for storing information when using these types of JSPs. You can also use application-bound objects to share data among different sessions of the same application. When you no longer need objects bound to an application, you should explicitly remove them to free up memory resources.

Session scope

In my experience, session scope is more commonly used than application scope. Session scope allows you to create and bind objects to a session. You must create objects bound to the session in session-aware JSPs and make them available to all JSPs and servlets in the same session. Session scope is often used for managing security credentials and for managing state among multiple pages (such as in a Web-based wizard). As with application scope, objects bound to session scope should be explicitly removed when no longer needed. Also, I typically make classes serializable if I intend to bind their instantiations to the session scope.

Request scope

I use request scope most often for binding created objects. Objects created and bound to request scope are available to pages in that same request. These objects are automatically released from memory when request processing completes. This is advantageous because explicit cleanup is not required and there is less risk of burdening the system with needless memory consumption.

Page scope

You should use page scope for objects created only for the current page. Like request scope, the page scope does not require explicit removal of created and bound objects. I rarely use page scope in my JSP applications, but it is the <jsp:useBean> action's default scope.

Which scope to use?

You should carefully choose scope for created objects to ensure efficient memory use and management. In general, I typically begin with request scope in my designs and then evaluate whether I need a broader scope for my created objects.

Carefully manage session scope

As stated in the best practice above, use session scope only when necessary and be sure to explicitly remove objects from session scope when you no longer require session access to these objects. For any JSP in which you don't use a session-bound object, you can set the page directive's session attribute to false to avoid the overhead involved with session management. However, I find few Web applications that don't need session support. Instead, I typically use session support for security mechanisms and other Web application needs. Even though a session expires after a configurable amount of time, it is best to invalidate these sessions explicitly when you no longer need them rather than rely exclusively on the automatic timeout mechanism.

Take advantage of JSTL

One of the most significant advancements for JSP developers has been the introduction and adoption of JSTL. Normally referred to as JSTL, it is also referred to as JSP Standard Tag Library. Note the T in JSTL stands for Tag rather than Template.

JSTL: A brief background and overview

In my earlier article, I recommended that JSP developers use available custom tag libraries rather than reinvent the wheel. Many commercial and open source custom tag libraries are available, but their one drawback requires developers to write JSPs to use those libraries in ways mandated by those custom tags. The advent of JSTL has addressed this downside by providing standard interfaces to the custom tags that perform many basic functions JSP developers need. Different vendors might implement the JSTL tags differently, but developers don't need to know about the differences in implementation. If a JSP developer writes his pages or documents to use JSTL tags, the JSP page or document should work with any JSTL implementation.

Plenty of good books and online resources exist for learning about JSTL (see Resources). Here, I briefly touch on JSTL's general advantages and features.

JSTL's advantages

In short, JSTL offers all the benefits of any publicly available custom tag library, but also provides the additional benefit of a standardized tag API. JSTL facilitates highly maintainable and transferable pages or documents. I list JSTL's specific advantages:

JSTL allows for tag-based iteration, conditionals, and other functionality previously implemented with Java scriptlets embedded directly in the JSP either with homegrown custom tags, a nonstandard tag library, or by abandoning the JSP in favor of a servlet.

JSTL tag interfaces (tag name, optional and required attributes, etc.) are standardized so that, once written, JSPs using these tags should work with any JSTL tag implementation.

JSTL takes advantage of expression language (EL) syntax.

Writing custom tags requires more effort and experience than many JSP development tasks. JSTL addresses this in two ways: First, as mentioned above, JSTL handles many common needs for custom tags. Second, JSTL provides mechanisms that make writing your own custom tags easier, especially if you want your own custom tag libraries to support the EL.

Specific JSTL features and advantages

This section briefly summarizes some advantages of using three of the four available JSTL custom tag libraries and some reasons not to use the JSTL database access library. I also discuss the advantages of using EL in this section.

Database access library

JSTL provides a database access custom tag library, but I seldom use it because I strongly feel that you should not implement database access directly inside JSPs. Accessing a database directly from a JSP reduces reuse because the database access code is not accessible outside the specific JSP in which the database tags are used. Direct database access in JSPs indicates strong coupling between the presentation and database tiers. Disciplined separation means more modularity, greater opportunity for reuse, and better opportunities for specialization of presentation and database experts. While I recommend using the other three JSTL tag libraries when they satisfy a JSP developer's needs, I do not recommend using the JSTL database access library outside of prototypes and the simplest Web applications.

JSTL core tag library

As its name suggests, the JSTL core tag library is the most commonly used of the four libraries. This tag library provides custom tags for iterating over collections, handling conditionals (if-else type constructs), and other familiar procedural constructs. This tag library alone saves JSP developers from writing many of their own custom tags or embedding Java directly in JSPs.

For Webpages and Websites available in multiple countries and/or languages, internationalization (I18N) can be one of the more challenging aspects of Web development projects. The JSTL formatting tag library helps JSP developers meet this challenge with custom tags that support writing and reading numbers and dates appropriately for the specified locale.

Expression language

JSTL has two tag types for these custom tag libraries: traditional request time (RT) custom tags and EL tags. Because EL is more flexible, I recommend using the EL custom tag libraries rather than the RT libraries.

According to the JSP 2.0 Specification Proposed Final Draft 2, all JSP tags will support an EL. Getting to know EL now by using JSTL's EL custom tag versions will make this transition smoother.

JSTL and other custom tag libraries

Because custom tags have been supported for much longer than JSTL has been available, many individuals and organizations have developed custom tag libraries that largely overlap with JSTL. In most cases, I recommend first using JSTL when possible instead of homegrown custom tag libraries or other publicly available custom tag libraries that implement the same functionality. The standardization provided by JSTL is a significant advantage because the tag APIs can be learned once and used consistently.

Comparing Struts tag libraries and JSTL provides a good example of how to implement this best practice. Struts provides many advantages beyond the Model-View-Controller (MVC) framework with which it is commonly associated. One additional advantage is its set of custom tag libraries. Struts custom tags supported iterations and conditionals long before JSTL was available. However, I am now beginning to use JSTL iteration and conditional tags rather than the Struts equivalents. I still use Struts form tags because they are closely tied with Struts form handling, and no JSTL equivalent exists.

The above approach works well when comparing any custom tag library to JSTL. If JSTL fully supports the same functionality, use the standardized JSTL tags. If JSTL tags fail to support some important features you use in these other tag libraries, there is no reason to change to JSTL. In most cases, as I described in my use of Struts and JSTL tags above, you will probably use a mixture of JSTL tags and other tag libraries.

JSTL: Final notes

See Resources for links to more details about JSTL, its advantages, and how to use JSTL in your JSPs. The Resources section also contains a link to Apache's Jakarta Standard Taglib, an open source and widely used JSTL implementation. Web server vendors have begun to deliver JSTL implementations with their Web servers, and JSTL is anticipated to be an integrated part of the final JSP 2.0 specification.

Take advantage of servlet filters

While servlet filters were actually introduced as part of the Servlet 2.3 specification, these filters benefit JSP development and maintenance as well. Because JSPs are converted into servlets and are highly coupled with servlet technology, it shouldn't be surprising that significant advancements in the servlet specification often impact JSP development.

Servlet filters are the J2EE implementation of the Intercepting Filter pattern and thus provide the advantages associated with this pattern. These advantages include better maintainability, reduced code redundancy, and greater portability. Servlet filters offer these advantages because many required services that you would normally need to add to each JSP you can instead place into a single servlet. The JSPs do not even need to be aware the filter exists. This lack of coupling between pluggable filters and JSPs means that any changes to the filters will not directly impact the JSPs themselves. You can chain filter servlets, enabling mixing and matching of different filters, each designed for specifically different purposes.

Usefulness of servlet filters in JSP Web applications

Two examples illustrate the usefulness of servlet filters in JSP-based Web applications. In many security configurations, each JSP checks the session ID or some other security credential to authenticate the JSP's caller. You can move the code for performing this check out of each JSP that makes the check and into a single servlet filter invoked before each JSP executes. Moving the redundant security code out of each JSP and into a single servlet filter significantly improves the JSPs' maintainability and portability. You likely only need to make changes or additions to security-related code in the single servlet filter and not in each JSP. If an entirely different security mechanism is chosen in the future, the servlet filter is the only piece of the system you must replace. The individual JSPs would require no changes.

In the previous "JSP Best Practices" article, I recommended storing exception information in some type of secondary storage and only providing the user with an identifier to search the storage for the entire exception trace. A servlet filter is very useful in this situation. You can configure a Web application (via the web.xml file) to automatically execute a servlet filter that logs exception information whenever the exception JSP is called. This allows a presentation-oriented exception page with all the processing and storage code placed in the intercepting filter.

Document the APIs for your JSPs

One of Java's many desirable features is its Javadoc support. Javadoc lets you quickly and easily provide Web-based documentation of your Java code. Unfortunately, the Javadoc tool does not support JSP, and the JSP specification does not call out a similar method of providing "JSP APIs."

What is the JSP API?

It would be extremely useful to quickly identify some JSP aspects without scouring the JSP code itself. For example, you need to know which variables are bound to session, request, or application scope, and which of these scopes they are bound to. Another example of useful JSP API information is denoting in JSP segments which variables they require the calling JSP to have declared and defined when including them.

The JSP specifications do not address the issue of documenting JSP APIs. The JSP 1.x Code Convention document from Sun (see Resources) discusses putting comments at the top of JSPs with information such as author, copyright, and description, but I like to document my JSPs' expected inputs more thoroughly.

Because the specification does not address this, there is no standard for commenting this type of JSP API information. One approach might be to use scriptlets and enclose Javadoc-style comments (/** javadoc comment */) in them. Although I typically do not place scriptlets in my JSPs, this is the easiest way to keep these comments on the server side only when using JSP documents. It is not a good idea to expose your JSP APIs to clients by using XML/HTML-style comments for this information.

I am aware of two freely available products for documenting your JSPs. JspDoc is available through SourceForge.net. Another tool with a similar name is JSPDoc, available at Open Source Development Network (OSDN)'s Freshmeat.net. (See Resources for more detailed information about these two products.) I present a brief summary of each product here.

JspDoc (SourceForge)

Available through SourceForge, the JspDoc tool generates Javadoc-like documentation pages for JSPs. This documentation generation is enabled by placing XML-compliant tags within Javadoc-style comments (/** */) that are in turn placed within JSP page scriptlet tags (<% %>). A drawback is that this tool only supports JSP pages, though support for JSP documents is on the planned extensions list.

This tool also provides a utility for converting JSP pages ("classic") to JSP documents ("new"). Because I write JSP documents to begin with, I have not used this extra utility, but it might benefit those wishing to migrate JSP pages to JSP documents. Another utility converts JSP documents to JSP pages.

JSPDoc (Freshmeat.net)

Listed as JSP Documentation Generator on the Freshmeat.net site, this tool extracts information directly from your JSPs to build Javadoc-like Web-based documentation pages. One of this tool's strengths is its ability to integrate the generated JSP documentation with Javadoc-generated documentation for Java classes. One drawback is that the expected comment structure for generating documentation pages is fairly rigid. This special syntax uses Javadoc delimiters (/** */), but does not recognize the special significance of the @ symbol, which is meaningful in standard Javadoc. This is an issue for the product's to-do list. Another drawback for me is that this tool does not support XML-compliant JSP documents, but instead requires <% %> syntax use. This product is available under the Mozilla public license.

JSP documentation generation for JSP documents

Because neither JspDoc nor JSPDoc currently support JSP documents, I take advantage of JSP documents' XML-compliance to perform Javadoc-like documentation generation. Using an XSLT stylesheet, you can easily create HTML-based pages documenting the XML-compliant JSP documents. No custom parsing is required because any of the standard translator tools (such as Xalan) will handle this process when the source document is a valid XML document. See the "JSP Documentation with XSLT" sidebar for such a stylesheet example.

Precompile your JSPs, even in development

When you execute a JSP by typing its URL into the browser, the JSP goes through much processing before being rendered to the browser as HTML. Because of all this processing, JSPs take considerably longer to execute the first time they are accessed than they do on later accesses. While most developers understand the importance of compiling these JSPs before making them available to the public, it is also useful in development to precompile JSPs before rendering them as HTML.

You can include the precompilation process in the regular code build, and compile JSPs at the same time as their associated JavaBeans, custom tag handler classes, and other associated classes and servlets. This lets you run a single build and keep most of the waiting time confined to one period. Because developers are often distracted as they wait for compilation, it can be advantageous to do all the compilation at once rather than compile each JSP as it's requested.

Precompilation can catch parser problems and other translation-time problems of pages that typically require several steps to reach. This is advantageous because it prevents the developer from navigating through multiple pages to get to the point where the relevant page is requested. If you use JSP documents, the precompilation step typically verifies that the JSP document is well formed.

Another advantage of precompilation is that you can include your JSPs' compiled versions in the Web archive (war) file rather than delivering the actual JSP source code in the war file. When JSPs are precompiled and translated for inclusion in the war file, they are included as .class files with vendor-specific naming conventions.

JSP precompilation is available with most modern Java 2 Platform, Enterprise Edition (J2EE)/Java IDEs. The major Web servers also support JSP precompilation, though they typically support it with nonstandard commands or interfaces. Most Web servers provide a command line-based JSP precompiler that you can integrate with scripted builds.

Organize files and directories

The following are additional techniques that make JSP development and maintenance easier and more efficient:

Organize the Web context root directory

Organize the WEB-INF directory with appropriate subdirectories

Identify JSP fragments with the .jspf extension

Use IDE, Ant, or other automated tools

Some of these techniques can benefit from the use of coding conventions as described earlier in this article.

Organize the Web context root directory

You can build Web applications by putting nearly all the Web application's content files directly in the Web context root directory. This is the directory in which the WEB-INF subdirectory normally resides. I recommend organizing this directory with subdirectories such as a jsp directory, an html directory, a css directory, an images directory, and so forth. For the simplest applications, this organization is probably more hassle than it's worth, but it eases comprehension and maintainability of large Web applications.

Organize the WEB-INF directory

Tag libraries are a valuable resource in JSP development. Large Web applications might consist of several tag libraries such as JSTL tag libaries, Struts tag libraries, and other tag libraries. Instead of inundating the WEB-INF directory with tag library descriptors, I prefer to create a tld subdirectory under WEB-INF and place the tag library descriptors there. You can do this to existing Web applications without harming the existing JSPs as long as the mapping in the web.xml file is edited to account for the new tld subdirectory. The web.xml file, the classes directory, and the lib directory are standard components in the WEB-INF directory. Moving the tag library descriptor files into their own directories reduces WEB-INF directory clutter.

Identify JSP segments with the .jspf extension

Known as JSP segments in more recent JSP specifications and JSP fragments in older specification versions, .jspf files are incomplete JSPs designed for inclusion in an encompassing JSP. The JSP specification encourages the use of naming conventions to help differentiate between outer (or top-level) JSPs and these JSP fragments/segments. Although the specification does not require it, the most common method of making this differentiation is to name complete and top-level JSPs with the traditional .jsp extension and the JSP fragments/segments with the .jspf extension. I also suggest keeping top-level JSPs in a separate subdirectory from the JSP fragments.

Use IDE, Ant, or other automated tools

IDEs can speed development and deployment times and reduce typos and other minor errors. Numerous IDEs are now available with J2EE development tools and wizards. These IDEs are being delivered with integrated frameworks such as Struts and JSTL tag libraries.

Ant is the defacto standard for building and deploying Java and J2EE applications. Ant allows enough flexibility to build and deploy virtually anything you want, but also provides specific support for building and deploying war and ear files. Many IDEs now have Ant-integration support. When I don't have access to an IDE, I consider Ant indispensable. Other tools that automate the building and deployment process can provide the same advantages of Ant, but Ant's most significant advantage may be its cost (freely available as open source) and its wide support and userbase.

I also want to mention Apache Maven as a useful product to consider for total Java project management.

Reconsider nonspecification-compliant features

Web servers occasionally provide vendor-specific features useful in production because they improve performance, increase security, or offer other advantages. In some cases, using these vendor-specific features is justified because the advantages outweigh the risks. However, it is important to be aware of the risks associated with vendor-specific features and to choose specification-compliant features over vendor-specific ones when their benefits are roughly equal. Keep in mind that not all features are specifically called out in the specification and, in that case, any vendor's implementation will be proprietary.

Technical dependencies do not always make vendor-specific features potentially risky. Custom tag libraries provided by Web server vendors may work on any Web server that fully supports custom tags, but you must be wary of licensing issues in these cases.

This best practice's significance depends on the likelihood of switching Web servers. When I am not using Tomcat as my Web server, I occasionally deploy my J2EE-based Web applications against this reference Web server implementation to verify specification compliance. Keep in mind that using vendor-specific features can be risky even if you stay with the same vendor for an extended time period. This is because the rapidly improving J2EE specifications often address issues in a standard way after vendors have made the features popular in their own proprietary way. In those cases, the vendors typically move to the standardized approach with future product versions.

Use XHTML syntax

In "JSP Best Practices," I recommended using HTML best practices in your JSPs. More specifically, I now find that the XHTML specification offers the most useful version of HTML tag syntax in authoring JSP documents. XHTML provides for HTML syntax that is entirely XML compatible, making it the perfect HTML tag syntax for developing XML-compliant JSP documents. Even JSP page authors will likely find it advantageous to use XHTML tag syntax in their JSPs.

To be completely XML-compliant, XHTML tag syntax must follow stricter rules than standard HTML tag syntax. The stricter requirements and the differences between standard HTML and XHTML tags are outlined in the World Wide Web Consortium's XHTML 1.0 pages.

It only gets better

JSP technology was originally created to simplify flexible Web development. Recent advancements such as JSTL have continued this trend. Even improvements in the servlet specification (such as filters) have strengthened JSP development convenience. The advancements in the JSP and servlet specifications, along with the advent of new development tools and sharing of JSP coding standards and conventions, have made highly maintainable JSP development easier than ever.

Dustin
Marx is a senior software engineer and J2EE architect at
Raytheon Company in Aurora, Colo. He has been working with JSP and
J2EE technology for three years and has been heavily involved in
object-oriented software development for seven years. He has a
master's degree in business administration and a bachelor's degree
in electrical engineering.

Dustin Marx is a principal software engineer and architect at Raytheon Company. His previous published work for JavaWorld includes Java and Flex articles and "More JSP best practices" (July 2003) and "JSP Best Practices" (November 2001).