Skip Headers
Oracle® Application Server Containers for J2EE Support for JavaServer Pages Developer's Guide
10g Release 2 (10.1.2)
B14014-02
  Go To Documentation Library
Library
Go To Product List
Product
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

6 Additional Programming Considerations

This chapter discusses an assortment of programming strategies and tips for use in developing JSP applications. The following sections are included:

General JSP Programming Strategies

This portion discusses issues you should consider when programming JSP pages, regardless of the particular target environment. The following sections are included:


Note:

In addition to being aware of what is discussed in this section, you should be aware of JSP translation and deployment issues and behavior. See Chapter 7, "JSP Translation and Deployment".

JavaBeans Versus Scriptlets

The section "Separation of Business Logic from Page Presentation: Calling JavaBeans" describes a key advantage of JavaServer Pages technology: Java code containing the business logic and determining the dynamic content can be separated from the HTML code containing the request processing, presentation logic, and static content. This separation allows HTML experts to focus on presentation, while Java experts focus on business logic in JavaBeans that are called from the JSP page.

A typical JSP page will have only brief snippets of Java code, usually for Java functionality for request processing or presentation. The sample page in "JSP Data-Access Sample Using JDBC", although illustrative, is probably not an ideal design. Data access, such as in the runQuery() method in the sample, is usually more appropriate in a JavaBean. However, the formatResult() method in the sample, which formats the output, is more appropriate for the JSP page itself.

Static Includes Versus Dynamic Includes

The include directive, described in "Directives", makes a copy of the included page and copies it into a JSP page (the "including page") during translation. This is known as a static include (or translate-time include) and uses the following syntax:

<%@ include file="/jsp/userinfopage.jsp" %>

The jsp:include tag, described in "Standard Actions: JSP Tags", dynamically includes output from the included page within the output of the including page during execution. This is known as a dynamic include (or runtime include) and uses the following syntax:

<jsp:include page="/jsp/userinfopage.jsp" flush="true" />

For those familiar with C syntax, a static include is comparable to a #include statement. A dynamic include is similar to a function call. They are both useful, but serve different purposes.


Note:

You can use static includes and dynamic includes only between pages in the same servlet context.

Logistics of Static Includes

A static include increases the size of the generated code for the including JSP page. It is as though the text of the included page is physically copied into the including page, at the point of the include directive, during translation. If a page is included multiple times within an including page, multiple copies are made.

A JSP page that is statically included is not required to be an independent, translatable entity. It simply consists of text that will be copied into the including page. The including page, with the included text copied in, must then be translatable. And, in fact, the including page does not have to be translatable prior to having the included page copied into it. A sequence of statically included pages can be fragments unable to stand on their own.

Logistics of Dynamic Includes

A dynamic include does not significantly increase the size of the generated code for the including page, although method calls, such as to the request dispatcher, will be added. The dynamic include results in runtime processing being switched from the including page to the included page, as opposed to the text of the included page being physically copied into the including page.

A dynamic include does increase processing overhead, with the necessity of the additional call to the request dispatcher.

A page that is dynamically included must be an independent entity, able to be translated and executed on its own. Likewise, the including page must be independent as well, able to be translated and executed without the dynamic include.

Advantages, Disadvantages, and Typical Uses of Dynamic and Static Includes

Static includes affect page size; dynamic includes affect processing overhead. Static includes avoid the overhead of the request dispatcher that a dynamic include necessitates, but may be problematic where large files are involved. (The service method of the generated page implementation class has a 64 KB size limit. See "Workarounds for Large Static Content or Significant Tag Library Usage".)

Overuse of static includes can also make debugging your JSP pages difficult, making it harder to trace program execution. Avoid subtle interdependencies between your statically included pages.

Static includes are typically used to include small files whose content is used repeatedly in multiple JSP pages. For example:

  • Statically include a logo or copyright message at the top or bottom of each page in your application.

  • Statically include a page with declarations or directives, such as imports of Java classes, that are required in multiple pages.

  • Statically include a central "status checker" page from each page of your application. (See "Use of a Central Checker Page".)

Dynamic includes are useful for modular programming. You may have a page that sometimes executes on its own but sometimes is used to generate some of the output of other pages. Dynamically included pages can be reused in multiple including pages without increasing the size of the including pages.


Note:

OC4J offers global includes as a convenient way to statically include a file into multiple pages. See "Oracle JSP Global Includes".

When to Consider Creating and Using JSP Tag Libraries

Some situations dictate that the development team consider creating and using custom tags. In particular, consider the following situations:

  • JSP pages would otherwise have to include a significant amount of Java logic regarding presentation and format of output.

  • You want to provide convenient JSP programming access to functionality that would otherwise require the use of a Java API.

  • Special manipulation or redirection of JSP output is required.

Replacing Java Syntax

Because JSP developers might not be experienced in Java programming, they might not be ideal candidates for coding Java logic in the page—logic that dictates presentation and format of the JSP output, for example.

This is a situation where JSP tag libraries might be helpful. If many of your JSP pages will require such logic in generating their output, a tag library to replace Java logic would be a great convenience for JSP developers.

An example of this is the JavaServer Pages Standard Tag Library (JSTL), supported by OC4J. This library is discussed in the Oracle Application Server Containers for J2EE JSP Tag Libraries and Utilities Reference.

Providing Convenient JSP Programming Access to API Features

Instead of having Web application programmers rely on Java APIs for using product functionality or extensions from servlets or JSP scriptlets , you can provide a tag library. A tag library can make the programmer's task much more convenient, with appropriate API calls being handled automatically by the tag handlers.

For example, tags as well as JavaBeans are provided with OC4J for e-mail and file access functionality. There is also a tag library as well as a Java API provided with the OC4J Web Object Cache.

Manipulating or Redirecting JSP Output

Another common situation for custom tags is if special runtime processing of the response output is required. Perhaps the desired functionality requires an extra processing step, or redirection of the output to somewhere other than the browser.

An example is to create a custom tag that you can place around a body of text whose output will be redirected into a log file instead of to a browser, such as in the following example, where cust is the prefix for the tag library and log is one of the tags of the library:

<cust:log>
   Today is <%= new java.util.Date() %>
   Text to log.
   More text to log.
   Still more text to log.
</cust:log>

Additional JSP Programming Tips

In addition to the general programming strategies described earlier, there are a variety of programming tips to consider, as described in the following sections:

Hiding JSP Pages from Direct Invocation

There are situations, particularly in an architecture such as Model-View-Controller (MVC), where you would want to ensure that some JSP pages are accessible only to the application itself and cannot be invoked directly by users.

As an example, assume that the front-end or "view" page is index.jsp. The user starts the application through a URL request that goes directly to that page. Further assume that index.jsp includes a second page, included.jsp, and forwards to a third page, forwarded.jsp, and that you do not want users to be able to invoke these directly through a URL request.

A mechanism for this is to place included.jsp and forwarded.jsp in the application /WEB-INF directory. When located there, the pages cannot be directly invoked through URL request. Any attempt would result in an error report from the browser.

The page index.jsp would have the following statements:

<jsp:include page="WEB-INF/included.jsp"/>
...
<jsp:forward page="WEB-INF/forwarded.jsp"/>

The application structure would be as follows, including the standard classes directory for any servlets, JavaBeans, or other classes, and including the standard lib directory for any JAR files:

index.jsp
WEB-INF/
   web.xml
   included.jsp
   forwarded.jsp
   classes/
   lib/

Use of a Central Checker Page

For general management or monitoring of your JSP application, it might be useful to use a central "checker" page that you include from each page in your application. A central checker page could accomplish tasks such as the following during execution of each page:

  • Check session status.

  • Check login status, such as checking the cookie to see if a valid login has been accomplished.

  • Check usage profile if a logging mechanism has been implemented to tally events of interest, such as mouse clicks or page visits.

There are many more possible uses as well.

As an example, consider a session checker class, MySessionChecker, that implements the HttpSessionBindingListener interface. (See "Standard Session Resource Management: HttpSessionBindingListener".)

public class MySessionChecker implements HttpSessionBindingListener
{
   ...
   
   valueBound(HttpSessionBindingEvent event)
   {...}
   
   valueUnbound(HttpSessionBindingEvent event)
   {...}
   
   ...
}

You can create a checker page, suppose centralcheck.jsp, that contains something like the following:

<jsp:useBean id="sessioncheck" class="MySessionChecker" scope="session" />

In any page that includes centralcheck.jsp, the servlet container will call the valueUnbound() method implemented in the MySessionChecker class as soon as sessioncheck goes out of scope at the end of the session. Presumably this is to manage session resources. You could include centralcheck.jsp at the end of each JSP page in your application.


Notes:


Workarounds for Large Static Content or Significant Tag Library Usage

JSP pages with large amounts of static content (essentially, large amounts of HTML code without content that changes at runtime) might result in slow translation and execution.

There are two primary workarounds for this, either of which will speed translation:

  • Put the static HTML into a separate file and use a jsp:include tag to include its output in the JSP page output at runtime. See "Standard Actions: JSP Tags" for information about the jsp:include tag.


Important:

A static include directive would not work. It would result in the included file being included at translation-time, with its code being effectively copied back into the including page. This would not solve the problem.

  • Put the static HTML into a Java resource file.

    The JSP translator will do this for you if you enable the external_resource configuration parameter. This parameter is documented in "JSP Configuration Parameter Descriptions".

    For pretranslation, the -extres option of the ojspc tool offers equivalent functionality.


Note:

Putting static HTML into a resource file might result in a larger memory footprint than the jsp:include workaround mentioned above, because the page implementation class must load the resource file whenever the class is loaded.

Another possible problem with JSP pages that have large static content, or more commonly with JSP pages that have a great deal of tag library usage, is that most (if not all) JVMs impose a 64 KB size limit on the code within any single method. Although javac would be able to compile it, the JVM would be unable to execute it. Depending on the implementation of the JSP translator, this might become an issue for a JSP page because generated Java code from essentially the entire JSP page source file goes into the service method of the page implementation class. Java code is generated to output the static HTML to the browser, and Java code from any scriptlets is copied directly.

Similarly, it is possible for the Java scriptlets in a JSP page to be large enough to create a size limit problem in the service method. If there is enough Java code in a page to create a problem, however, then the code should be moved into JavaBeans.

If a large amount of tag library usage results in a size limit problem for a JSP page, a common solution is to break the page into multiple pages and use jsp:include tags as appropriate.

Method Variable Declarations Versus Member Variable Declarations

In "Scripting Elements", it is noted that JSP <%! ... %> declarations are used to declare member variables, while method variables must be declared in <% ... %> scriptlets.

Be careful to use the appropriate mechanism for each of your declarations, depending on how you want to use the variables:

  • A variable that is declared in <%! ... %> JSP declaration syntax is declared at the class level in the page implementation class that is generated by the JSP translator. In this case, if declaring an object instance, the object can be accessed simultaneously from multiple requests. Therefore, the object must be thread-safe, unless isThreadSafe="false" is declared in a page directive.

  • A variable that is declared in <% ... %> JSP scriptlet syntax is local to the service method of the page implementation class. Each time the method is called, a separate instance of the variable or object is created, so there is no need for thread safety.

Consider the following example, decltest.jsp:

<HTML>
<BODY>
<% double f2=0.0; %>
<%! double f1=0.0; %>
Variable declaration test.
</BODY>
</HTML>

This results in something like the following code in the page implementation class:

package ...;
import ...;

public class decltest extends ... {
   ...

   // ** Begin Declarations
   double f1=0.0;                  // *** f1 declaration is generated here ***
   // ** End Declarations

   public void _jspService
                (HttpServletRequest request, HttpServletResponse response) 
                throws IOException, ServletException {
      ...

      try {
         out.println( "<HTML>");
         out.println( "<BODY>");
         double f2=0.0;      // *** f2 declaration is generated here ***
         out.println( "");
         out.println( "");
         out.println( "Variable declaration test.");
         out.println( "</BODY>");
         out.println( "</HTML>");
         out.flush();
      }
      catch( Exception e) {
         try {
            if (out != null) out.clear();
         }
         catch( Exception clearException) {
         }
      finally {
         if (out != null) out.close();
      }
   }
}


Note:

This code is provided for conceptual purposes only. Most of the class is deleted for simplicity, and the actual code of a page implementation class generated by the JSP translator would differ somewhat.

Page Directive Characteristics

This section discusses the following page directive characteristics:

  • A page directive is static and takes effect during translation. You cannot specify parameter settings to be evaluated at runtime.

  • Beginning with the JSP 1.2 specification, duplicate settings of directive attributes are disallowed. In particular, this pertains to the page directive, although the page directive import attribute is exempt from this limitation.

  • Java import settings in page directives are cumulative within a JSP page or translation unit.

Page Directives Are Static

A page directive is static; it is interpreted during translation. You cannot specify dynamic settings to be interpreted at runtime. Consider the following examples.

Example 1

The following page directive is valid.

<%@ page contentType="text/html; charset=EUCJIS" %>
Example 2

The following page directive is not valid and will result in an error. (EUCJIS is hard-coded here, but the example also holds true for any character set determined dynamically at runtime.)

<% String s="EUCJIS"; %>
<%@ page contentType="text/html; charset=<%=s%>" %>

For some page directive settings there are workarounds. Reconsidering the second example, there is a setContentType() method that allows dynamic setting of the content type, as described in "Dynamic Content Type Settings".

Duplicate Settings of Page Directive Attributes Are Disallowed

The JSP specification states that a JSP container must verify that directive attributes, with the exception of the page directive import attribute, are not set more than once each within a single JSP translation unit (a JSP page plus anything it includes through include directives). In JSP 1.2, this effectively applies to page directives only, but in future JSP versions there might be additional relevant directives.

For backward compatibility to the JSP 1.1 standard, where duplicate settings of directive attributes are allowed, OC4J provides the forgive_dup_dir_attr configuration parameter. See "JSP Configuration Parameter Descriptions" for information about this parameter. You might have previously coded a page with multiple included segments that all set the page directive language attribute to "java", for example.

For clarity, be aware of the following points.

  • The JSP specification allows multiple page directives, as long as they set different attributes.

    The following are okay:

    <%@ page buffer="none" %>
    <%@ page session="true" %>
    
    

    or:

    ------------------------------
    <%@ page buffer="10kb" %>
    <%@ include file="b.jsp" %>
    ------------------------------
    ------------------------------
    b.jsp
    <%@ page session="false" %>
    ------------------------------
    
    

    The following are not okay:

    <%@ page buffer="none" %>
    <%@ page buffer="10kb" %>
    
    

    or:

    <%@ page buffer="none" buffer="10kb" %>
    
    

    or:

    ------------------------------
    <%@ page buffer="10kb" %>
    <%@ include file="b.jsp" %>
    ------------------------------
    ------------------------------
    b.jsp
    <%@ page buffer="3kb" %>
    ------------------------------
    
    
  • A translation unit consists of a JSP page plus anything it includes through include directives, but not pages it includes through jsp:include tags. Pages included through jsp:include tags are dynamically included at runtime, not statically included during translation. See "Static Includes Versus Dynamic Includes" for more information.

    Therefore, the following is okay:

    ------------------------------
    <%@ page buffer="10kb" %>
    <jsp:include page="b.jsp" />
    ------------------------------
    ------------------------------
    b.jsp
    <%@ page buffer="3kb" %>
    ------------------------------
    
    
  • As noted in the opening paragraph above, the page directive import attribute is exempt from the limitation against duplicate attribute settings. See the next section, "Page Directive import Settings Are Cumulative".

Page Directive import Settings Are Cumulative

The page directive import attribute is exempt from JSP 1.2 limitations on duplicate directive attributes. Java import settings in page directives within a JSP page or translation unit (a JSP page plus anything included through include directives) are cumulative.

Within any single JSP page or translation unit, the following two examples are equivalent:

<%@ page language="java" %>
<%@ page import="java.io.*, java.sql.*" %>

or:

<%@ page language="java" %>
<%@ page import="java.io.*" %>
<%@ page import="java.sql.*" %>

After the first page directive import setting, the import setting in the second page directive adds to the set of classes or packages to be imported, as opposed to replacing the classes or packages to be imported.

JSP Preservation of White Space and Use with Binary Data

JSP containers generally preserve source code white space, including carriage returns and linefeeds, in what is output to the browser. Insertion of such white space might not be what the developer intended, and typically makes JSP technology a poor choice for generating binary data.

White Space Examples

The following two JSP pages produce different HTML output, due to the use of carriage returns in the source code.

Example 1: No Carriage Returns

The following JSP page does not have carriage returns after the Date() and getParameter() calls. (The third and fourth lines, starting with the Date() call, actually form a single wraparound line of code.)

nowhitsp.jsp:

<HTML>
<BODY>
<%= new java.util.Date() %> <% String user=request.getParameter("user"); %> <%= (user==null) ? "" : user %>
<B>Enter name:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="user" SIZE=15>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>

This code results in the following HTML output to the browser. Note that there are no blank lines after the date.

<HTML>
<BODY>
Tue May 30 20:07:04 PDT 2000  
<B>Enter name:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="user" SIZE=15>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>
Example 2: Carriage Returns

The following JSP page does include carriage returns after the Date() and getParameter() calls.

whitesp.jsp:

<HTML>
<BODY>
<%= new java.util.Date() %>
<% String user=request.getParameter("user"); %>
<%= (user==null) ? "" : user %>
<B>Enter name:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="user" SIZE=15>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>

This code results in the following HTML output to the browser.

<HTML>
<BODY>
Tue May 30 20:19:20 PDT 2000


<B>Enter name:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="user" SIZE=15>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>

Note the two blank lines between the date and the "Enter name:" line. In this particular case the difference is not significant, because both examples produce the same appearance in the browser, as shown in Figure 6-1. However, this discussion nevertheless demonstrates the general point about preservation of white space.

Figure 6-1 Sample Browser Output for White Space Example

Description of Figure 6-1  follows
Description of "Figure 6-1 Sample Browser Output for White Space Example"

Reasons to Avoid Binary Data in JSP Pages

For the following reasons, JSP pages are a poor choice for generating binary data. Generally, you should use servlets instead.

  • JSP implementations are not designed to handle binary data. There are no methods in the JspWriter class for writing raw bytes.

  • During execution, the JSP container preserves white space. White space is sometimes unwanted, making JSP pages a poor choice for generating binary output (a .gif file, for example) to the browser or for other uses where white space is significant.

    Consider the following general example:

    ...
    <% response.getOutputStream().write(...binary data...) %>
    <% response.getOutputStream().write(...more binary data...) %>
    
    

    In this case, the browser will receive an unwanted newline character in the middle of the binary data or at the end, depending on the buffering of your output buffer. You can avoid this problem by not using a carriage return between the lines of code, but this is an undesirable programming style.


Note:

The preceding example is for illustrative purposes only and might not be portable to future Oracle JSP versions or other JSP containers.

Trying to generate binary data in JSP pages largely misses the point of JSP technology anyway, which is intended to simplify the programming of dynamic textual content.

Summary of JSP Best Practices

This section summarizes best practices and considerations, with cross-references to where details are discussed earlier in this chapter or elsewhere in this document.

Best Practices: JSP Coding

We recommend the following for your JSP code:

Best Practices: Translation and Compilation

We recommend the following for translation and compilation of your JSP pages:

  • Consider whether to precompile your JSP pages. Factors include application size on disk, control of the source code, and reducing first-access time. See "JSP Execution Models" for a discussion of the two approaches. Also see "The ojspc Pretranslation Utility".

  • Consider in-process versus out-of-process compilation. In-process compilation is generally faster and less error-prone, but out-of-process compilation allows you to conveniently use a different compiler if desired. See "JSP Compilation Considerations".

Best Practices: JSP Configuration

We recommend the following for your JSP configuration. See "JSP Configuration Parameters" for information about these parameters.

  • In a production environment, always set the main_mode flag to justrun.

  • Use parameters such as reduce_tag_code and tag_reuse_default to improve performance.