Oracle JavaServer Pages Developer's Guide and Reference Release 8.1.7 Part Number A83726-01 |
Library | Service | Contents | Index

## General JSP Programming Strategies, Tips, and Traps

This section discusses issues you should consider when programming JSP pages that will run in the OracleJSP container, regardless of the particular target environment.

Note: In addition to being aware of the topics in this section, you should be aware of OracleJSP translation and deployment issues and behavior. See Chapter 6, "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 logic in the JSP page itself, 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 Starter Sample for Database Access", although illustrative, is probably not an ideal design. Database 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.

### Use of Enterprise JavaBeans in JSP Pages

To use an Enterprise JavaBean (EJB) in a JSP page, choose either of the following approaches:

- Use a JavaBean wrapper for the EJB and call the JavaBean from the JSP page as you would any other JavaBean.

- Call the EJB directly from the JSP page.

This section provides two examples of calling an EJB from a JSP page--one where the JSP page runs in a middle-tier environment, and one where it runs in the Oracle Servlet Engine.

These examples point out some significant advantages in using the Oracle Servlet Engine.

For general information about the Oracle EJB implementation, see the Oracle8i Enterprise JavaBeans Developer's Guide and Reference.

#### Calling an EJB from a JSP Page in the Middle Tier

The following JSP page calls an EJB from a middle-tier environment such as the Oracle Internet Application Server. In this case, the service URL is specified as `sess_iiop://localhost:2481:ORCL` ( you may need to modify it to use your own hostname, IIOP port number and Oracle instance name). The JNDI naming context is set up through the `new InitialContext(env)` construction, where `env` is a hashtable defining the parameters for the context. Once the initial context (`ic`) is created, the code looks up the EJB home object using the service URL and the JNDI name for the EJB:

    EmployeeHome home = (EmployeeHome) ic.lookup (surl + "/test/employeeBean");

Then the `home.create()` method is called to create an instance of the bean, and the bean's `query()` method is called to get the name and salary for the employee whose number was entered through the HTML form in the JSP page.

Following is the sample code:

    <HTML>
    <%@ page import="employee.Employee, employee.EmployeeHome,
    employee.EmpRecord, oracle.aurora.jndi.sess_iiop.ServiceCtx,
    javax.naming.Context, javax.naming.InitialContext, java.util.Hashtable"
    %>

    <HEAD> <TITLE> The CallEJB JSP  </TITLE> </HEAD>
    <BODY BGCOLOR="white">
    <BR>
    <%  String empNum = request.getParameter("empNum");
        String surl = request.getParameter("surl");
        if (empNum != null) {
          try {
              Hashtable env = new Hashtable();
              env.put(Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
              env.put(Context.SECURITY_PRINCIPAL, "scott");
              env.put(Context.SECURITY_CREDENTIALS, "tiger");
              env.put(Context.SECURITY_AUTHENTICATION,
                      ServiceCtx.NON_SSL_LOGIN);
              Context ic = new InitialContext (env);
              EmployeeHome home = (EmployeeHome)ic.lookup (surl +
                               "/test/employeeBean");
              Employee testBean = home.create();
              EmpRecord empRec = testBean.query (Integer.parseInt(empNum));

    %>
    <h2><BLOCKQUOTE><BIG><PRE>
            Hello, I'm an EJB in Oracle8i.
            Employee <%= empRec.ename %> earns $ <%= empRec.sal %>
    <%  } catch (Exception e) { %>
            Error occurred: <%= e %>
    <%   }
       } %>
    </PRE></BIG></BLOCKQUOTE></h2>
          <HR>

    <P><B>Enter an employee number and EJB service URL:</B></P>
    <FORM METHOD=get>
    <INPUT TYPE=text NAME="empNum" SIZE=10 value="7654">
    <INPUT TYPE=text NAME="surl" SIZE=40 value="sess_iiop://localhost:2481:ORCL">
    <INPUT TYPE=submit VALUE="Ask Oracle">
    </FORM>
    </BODY>
    </HTML>

#### Calling an EJB from a JSP Page in the Oracle Servlet Engine

If you are deploying the JSP page to the Oracle Servlet Engine in Oracle8i, the EJB lookup and invocation is much simpler and highly optimized. In this case, the bean lookup is done locally within the Oracle8i JNDI namespace. An explicit service URL specification is not required. The naming context is initialized for the current session with the simple call :

    Context ic = new InitialContext();

Note that the constructor in this case does not require any arguments, unlike the middle-tier example. The bean is looked up using just its JNDI name (without the service URL):

    EmployeeHome home = (EmployeeHome)ic.lookup ("/test/employeeBean");

Following is the sample code:

    <HTML>
    <%@ page import="employee.Employee, employee.EmployeeHome,
    employee.EmpRecord, oracle.aurora.jndi.sess_iiop.ServiceCtx,
    javax.naming.Context, javax.naming.InitialContext,
    java.util.Hashtable"  %>

    <HEAD> <TITLE> The CallEJB JSP  </TITLE> </HEAD>
    <BODY BGCOLOR="white">
    <BR>
    <%  String empNum = request.getParameter("empNum");
        if (empNum != null) {
          try {
            Context ic = new InitialContext();
            EmployeeHome home = (EmployeeHome)ic.lookup("/test/employeeBean");
            Employee testBean = home.create();
            EmpRecord empRec =  testBean.query (Integer.parseInt(empNum));
    %>
    <h2><BLOCKQUOTE><BIG><PRE>
            Hello, I'm an EJB in Oracle8i.
            Employee <%= empRec.ename %> earns $ <%= empRec.sal %>
    <%  } catch (Exception e) { %>
            Error occurred: <%= e %>
    <%  }
      } %>
    </PRE></BIG></BLOCKQUOTE></h2>
          <HR>

    <P><B>Enter an employee number URL:</B></P>
    <FORM METHOD=get>
    <INPUT TYPE=text NAME="empNum" SIZE=10 value="7654">
    <INPUT TYPE=submit VALUE="Ask Oracle">
    </FORM>
    </BODY>
    </HTML>

### Use of JDBC Performance Enhancement Features

You can use the following performance enhancement features in JSP applications executed by OracleJSP:

- caching database connections (through Oracle extensions)

- caching JDBC statements (through Oracle extensions)

- batching update statements (through Oracle extensions)

- prefetching rows during a query (through Oracle extensions)

- caching rowsets (through Sun Microsystems extensions)

Most of these performance features are supported by the `ConnBean` and `ConnCacheBean` database-access JavaBeans (but not by `DBBean`). "Oracle Database-Access JavaBeans" describes these beans.

#### Database Connection Caching

Creating a new database connection is an expensive operation that you should avoid whenever possible. Instead, use a cache of database connections. A JSP application can get a logical connection from a pre-existing pool of physical connections, and return the connection to the pool when done.

You can create a connection pool at any one of the four JSP scopes--`application`, `session`, `page`, or `request`. It is most efficient to use the maximum possible scope--`application` scope if that is permitted by the Web server, or `session` scope if not.

The Oracle JDBC connection caching scheme, built upon standard connection pooling as specified in the JDBC 2.0 standard extensions, is implemented in the `ConnCacheBean` database-access JavaBean provided with OracleJSP. This is probably how most OracleJSP developers will use connection caching. For information, see "ConnCacheBean for Connection Caching".

It is also possible to use the Oracle JDBC `OracleConnectionCacheImpl` class directly, as though it were a JavaBean, as in the following example (although all `OracleConnectionCacheImpl` functionality is available through `ConnCacheBean`):

    <jsp:useBean id="occi" class="oracle.jdbc.pool.OracleConnectionCacheImpl"
                 scope="session" />

The same properties are available in `OracleConnectionCacheImpl` as in `ConnCacheBean`. They can be set either through `jsp:setProperty` statements or directly through the class setter methods.

For examples of using `OracleConnectionCacheImpl` directly, see "Connection Caching--ConnCache3.jsp and ConnCache1.jsp".

For information about the Oracle JDBC connection caching scheme and the `OracleConnectionCacheImpl` class, see the Oracle8i JDBC Developer's Guide and Reference.

#### JDBC Statement Caching

Statement caching, an Oracle JDBC extension that is available with release 8.1.7, improves performance by caching executable statements that are used repeatedly within a single physical connection, such as in a loop or in a method that is called repeatedly. When a statement is cached, the statement does not have to be re-parsed, the statement object does not have to be recreated, and parameter size definitions do not have to be recalculated each time the statement is executed.

The Oracle JDBC statement caching scheme is implemented in the `ConnBean` and `ConnCacheBean` database-access JavaBeans that are provided with OracleJSP. Each of these beans has a `stmtCacheSize` property that can be set through a `jsp:setProperty` statement or the bean's `setStmtCacheSize()` method. For information, see "ConnBean for a Database Connection" and "ConnCacheBean for Connection Caching".

Statement caching is also available directly through the Oracle JDBC `OracleConnection` and `OracleConnectionCacheImpl` classes. For information about the Oracle JDBC statement caching scheme and the `OracleConnection` and `OracleConnectionCacheImpl` classes, see the Oracle8i JDBC Developer's Guide and Reference.

Important: Statements can be cached only within a single physical connection. When you enable statement caching for a connection cache, statements can be cached across multiple logical connection objects from a single pooled connection object, but not across multiple pooled connection objects.

#### Update Batching

The Oracle JDBC update batching feature associates a batch value (limit) with each prepared statement object. With update batching, instead of the JDBC driver executing a prepared statement each time its `executeBatch()` method is called, the driver adds the statement to a batch of accumulated execution requests. The driver will pass all the operations to the database for execution once the batch value is reached. For example, if the batch value is 10, then each batch of 10 operations will be sent to the database and processed in one trip.

OracleJSP supports Oracle JDBC update batching directly, through the `executeBatch` property of the `ConnBean` database-access JavaBean. You can set this property through a `jsp:setProperty` statement or through the bean's setter method. If you use `ConnCacheBean` instead, you can enable update batching through Oracle JDBC functionality in the connection and statement objects you create. See "ConnBean for a Database Connection" and "ConnCacheBean for Connection Caching" for information about these JavaBeans.

For more information about Oracle JDBC update batching, see the Oracle8i JDBC Developer's Guide and Reference.

#### Row Prefetching

The Oracle JDBC row prefetching feature allows you to set the number of rows to prefetch into the client during each trip to the database while a result set is being populated during a query, reducing the number of round trips to the server.

OracleJSP supports Oracle JDBC row prefetching directly, through the `preFetch` property of the `ConnBean` database-access JavaBean. You can set this property through a `jsp:setProperty` statement or through the bean's setter method. If you use `ConnCacheBean` instead, you can enable row prefetching through Oracle JDBC functionality in the connection and statement objects you create. See "ConnBean for a Database Connection" and "ConnCacheBean for Connection Caching" for information about these JavaBeans.

For more information about Oracle JDBC row prefetching, see the Oracle8i JDBC Developer's Guide and Reference.

#### Rowset Caching

A cached rowset provides a disconnected, serializable, and scrollable container for data retrieved from the database. This feature is useful for small sets of data that do not change often, particularly when the client requires frequent or continued access to the information. By contrast, using a normal result set requires the underlying connection and other resources to be held. Be aware, however, that large cached rowsets consume a lot of memory on the client.

As of release 8.1.7, Oracle JDBC does not provide a cached rowset implementation; however, a reference implementation is available from Sun Microsystems. Download the file `rowset.jar` from the Sun Web site, include it in your Web server classpath, and import the package `sun.jdbc.rowset.*` in your code. Then use code to create and populate a cached rowset, such as in the following example:

    CachedRowSet crs = new CachedRowSet();
    crs.populate(rset); // rset is a previously created JDBC ResultSet object.

Once the rowset is populated, the connection and statement objects used in obtaining the original result set can be closed.

### 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` action, described in "JSP Actions and the <jsp: > Tag Set", dynamically includes output from the included page within the output of the including page, during runtime. 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 of you who are 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: Both static includes and dynamic includes can be used only within the same servlet context.

#### Logistics of Static Includes

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

A JSP page that is statically included does not need to stand as 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 each 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

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. (There is a 64K size limit on the service method of the generated page implementation class--see "Workarounds for Large Static Content in JSP Pages".)

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.

### 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.

- Special manipulation or redirection of JSP output is required.

#### Replacing Java Syntax

Because one cannot count on JSP developers being experienced in Java programming, they may 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 JML sample tag library provided with OracleJSP. This library includes tags that support logic equivalent to Java loops and conditionals. (See "Overview of the JSP Markup Language (JML) Sample Tag Library" for information.)

#### 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 library's tags):

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

See "Tag Handlers" for information about processing of tag bodies.

### Use of a Central Checker Page

For general management or monitoring of your JSP application, it may 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 could be many more 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 JSP page, suppose `centralcheck.jsp`, that includes 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.

### Workarounds for Large Static Content in JSP Pages

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

There are two primary workarounds for this (either workaround will speed translation):

- Put the static HTML into a separate file and use a dynamic `include` command (`jsp:include`) to include its output in the JSP page output at runtime. See "JSP Actions and the <jsp: > Tag Set" for information about the `jsp:include` command.

  Important: A static `<%@ include... %>` command 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.

  OracleJSP will do this for you if you enable the `external_resource` configuration parameter. This parameter is documented in "OracleJSP Configuration Parameters (Non-OSE)".

  For deployment to Oracle8i, the `-extres` and `-hotload` options of the `ojspc` pre-translation tool, and the `-hotload` option of the `publishjsp` session shell command, also offer this functionality.

  Note: Putting static HTML into a resource file may 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, though unlikely, problem with JSP pages that have large static content is that most (if not all) JVMs impose a 64K byte 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 may 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.)

Another possible, though rare, scenario is 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.

### 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.

- A variable that is declared in `<% ... %>` JSP scriptlet syntax is local to the service method of the page implementation class.

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 oracle.jsp.runtime.HttpJsp {
       ...

       // ** 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 OracleJSP 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.

- Java `import` settings in `page` directives are cumulative within a JSP page.

#### 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 Example 2, there is a `setContentType()` method that allows dynamic setting of the content type, as described in "Dynamic Content Type Settings".

#### Page Directive Import Settings Are Cumulative

Java `import` settings in `page` directives within a JSP page are cumulative.

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

    <%@ page language="java" %>
    <%@ page import="sqlj.runtime.ref.DefaultContext, java.sql.*" %>

or:

    <%@ page language="java" %>
    <%@ page import="sqlj.runtime.ref.DefaultContext" %>
    <%@ 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

OracleJSP (and JavaServer Pages implementations in general) preserves source code white space, including carriage returns and linefeeds, in what is output to the browser. Insertion of such white space may 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 (nowhitsp.jsp)

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 comprise a single wrap-around line of code.)

    <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 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 (whitesp.jsp)

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

    <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 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 below. However, this discussion nevertheless demonstrates the general point about preservation of white space.

#### 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 for writing raw bytes in the `JspWriter` object.

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

  Consider the following example:

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

  In this case, the browser will receive an unwanted newline characters 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 of course this is an undesirable programming style.

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.

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index