OracleJSP Support for JavaServer Pages Developer's Guide and Reference
Release 1.1.2.3

Part Number A90208-01
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback

Go to previous page Go to next page

4
Key Considerations

This chapter discusses important programming, configurational, and runtime considerations, as well as special considerations for particular execution environments. The following topics are covered:

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. The following assortment of topics are covered:

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 Data Access", 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.

Use of Enterprise JavaBeans in JSP Pages

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

For general information, 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 Oracle9i Servlet Engine. These two examples point out some significant advantages in using OSE.

These are followed by an example using the more modular approach of calling an EJB from a JavaBean wrapper.

For general information about the Oracle EJB implementation, see the Oracle9i 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 Oracle9i 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 Oracle9i.
        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 Oracle9i Servlet Engine

If you are deploying the JSP page to Oracle9i to execute in the OSE environment, the EJB lookup and invocation is much simpler and highly optimized. In this case, the bean lookup is done locally within the Oracle9i 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 Oracle9i.
        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>

Calling an EJB from a JavaBean Wrapper Called from a JSP Page

The following example provides a JSP page that calls a JavaBean wrapper, which in turn calls an EJB.

The JSP page uses an instance, employeeBean, of the EmployeeEJBWrapper JavaBean class. It calls the setServiceURL() method on the bean to set the database URL, according to the URL entered through the HTTP request object. It calls the doCallEJB() method on the bean to call the EJB.

The JavaBean implements the HttpSessionBindingListener interface. (See "Standard Session Resource Management--HttpSessionBindingListener" for information about this interface.) When the session expires, the valueUnbound() method is called to destroy the EJB instance.

JNDI setup, in the bean, is accomplished as in the preceding examples.

Following is the JSP page:

<HTML>
<%@ page import="beans.EmployeeEJBWrapper" %>

<jsp:useBean id="employeeBean" class="beans.EmployeeEJBWrapper" scope="session" 
/>

<HEAD> <TITLE> The CallEJB JSP  </TITLE> </HEAD>
<BODY BGCOLOR="white">
<BR>
<%  
    String empNum = request.getParameter("empNum");
    String surl = request.getParameter("surl");
    String inJServer = System.getProperty("oracle.jserver.version");
    // save the parameters in the bean instance
    if (surl != null) {
       employeeBean.setServiceURL(surl);
    }
    if (empNum != null) {
       employeeBean.setEmpNumber(empNum);
%>

      <h2><BLOCKQUOTE><BIG><PRE>
        Employee    Salary 
        <%= employeeBean.doCallEJB(Integer.parseInt(empNum), inJServer) %>
      </PRE></BIG></BLOCKQUOTE></h2>
      <HR>
<%  } 
  // show the defaults or the values last entered 
  String val1 = ((empNum == null) ? "7654" : employeeBean.getEmpNumber());
  String val2 = ((surl == null) ? "sess_iiop://localhost:2481:ORCL" 
                : employeeBean.getServiceURL());
%>

<P><B>Enter the following data:
   <FORM METHOD=get> 
     Employee Number: <INPUT TYPE=text NAME="empNum" SIZE=10 
                              VALUE= <%= val1 %>>
<%   if (inJServer == null) { 
      // not running in JServer, need a service URL 
%>
     <P> EJB Service URL: <INPUT TYPE=text NAME="surl" SIZE=40 
                              VALUE= <%= val2 %>>
<% 
     } %>
<INPUT TYPE=submit VALUE="Ask Oracle">
</FORM>
</BODY>
</HTML>

And here is the JavaBean code:

package beans;

import employee.Employee;
import employee.EmployeeHome;
import employee.EmpRecord;
import oracle.aurora.jndi.sess_iiop.ServiceCtx;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionBindingEvent;
import java.util.Hashtable;

public class EmployeeEJBWrapper
             implements HttpSessionBindingListener
{
  public EmployeeEJBWrapper() {}     // no arg bean constructor
  
  private Employee employeeEJB = null;
  private String empNumber = null; 
  private String serviceURL = null;

  public String doCallEJB(int empno, String inJServer) {
    try {
      if (employeeEJB == null) {
        Context ic = null;
        EmployeeHome home = null;
        if (inJServer == null) { // not running in JServer, usual client setup
          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);
          ic = new InitialContext (env);
          home = (EmployeeHome)ic.lookup (serviceURL + 
                           "/test/employeeBean");           
        }
        else { // in JServer, use simplified and optimized lookup
          ic = new InitialContext();
          home = (EmployeeHome)ic.lookup ("/test/employeeBean");
        }
        employeeEJB = home.create();
      }
      EmpRecord empRec = empRec = employeeEJB.query (empno);
      return  empRec.ename + "       $" + empRec.sal;
    } catch (Exception e) { return "Error occurred: " + e;}
  }   

  public void setServiceURL (String serviceURL) {
      this.serviceURL = serviceURL;
  }

  public String getServiceURL () {
     return serviceURL;
  }

  public void setEmpNumber(String empNo) {
      empNumber = empNo;
  }     

  public String getEmpNumber() {
      return empNumber;
  }

  public void valueBound(HttpSessionBindingEvent event) {
    // nothing to do here, EJB will be created when query is submitted
  } 
  
  public synchronized void valueUnbound(HttpSessionBindingEvent event) {
    if (employeeEJB != null) {
      try {
        employeeEJB.remove();   // destroy the bean instance
      } catch (Exception ignore) {}
      employeeEJB = null;
    }
  }
}

Use of JDBC Performance Enhancement Features

You can use the following performance enhancement features, supported through Oracle JDBC extensions, in JSP applications executed by OracleJSP:

Most of these performance features are supported by the ConnBean and ConnCacheBean data-access JavaBeans (but not by DBBean). "Oracle Data-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 data-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 Oracle9i JDBC Developer's Guide and Reference.

JDBC Statement Caching

Statement caching, an Oracle JDBC extension, 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 data-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 Oracle9i 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 "execute" 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 ten 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 data-access JavaBean. You can set this property through a jsp:setProperty statement or through the setter method of the bean. 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 Oracle9i 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 or middle-tier database cache 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 data-access JavaBean. You can set this property through a jsp:setProperty statement or through the setter method of the bean. 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 Oracle9i JDBC Developer's Guide and Reference.

Rowset Caching

A cached rowset provides a disconnected, serializable, and scrollable container for retrieved data. 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.

In Oracle9i, Oracle JDBC provides a cached rowset implementation. If you are using an Oracle JDBC driver, use code inside a JSP page to create and populate a cached rowset as follows:

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.

For more information about Oracle JDBC cached rowsets, see the Oracle9i JDBC Developer's Guide and Reference.

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

Here is an example of jsp:include 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 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, 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:

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:

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:

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):

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:

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:

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

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

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


Text description of whitesp.gif follows.
Text description of the illustration whitesp.gif

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.

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.

Key OracleJSP Configuration Issues

This section covers important effects of how you set key page directive parameters and OracleJSP configuration parameters. The discussion focuses on JSP page optimization, classpath issues, and class loader issues. The following topics are covered:

Optimization of JSP Execution

There are settings you can consider to optimize JSP performance, including the following:

Unbuffering a JSP Page

By default, a JSP page uses an area of memory known as a page buffer. This buffer (8KB by default) is required if the page uses dynamic globalization support content type settings, forwards, or error pages. If it does not use any of these features, you can disable the buffer in a page directive:

<%@ page buffer="none" %>

This will improve the performance of the page by reducing memory usage and saving an output step. Output goes straight to the browser instead of going through the buffer first.

Not Checking for Retranslation (Non-OSE Only)

When OracleJSP executes a JSP page, by default it will check whether a page implementation class already exists, compare the .class file timestamp against the .jsp source file timestamp, and retranslate the page if the .class file is older.

If comparing timestamps is unnecessary (as is the case in a typical deployment environment, where source code will not change), you can avoid the timestamp comparison by disabling the OracleJSP developer_mode flag (developer_mode=false).

The default setting is true. For information about how to set this flag in the Apache/JServ, JSWDK, and Tomcat environments, see "OracleJSP Configuration Parameter Settings".

Not Using an HTTP Session

If a JSP page does not need an HTTP session (essentially, does not need to store or retrieve session attributes), then you can avoid using a session through the following page directive:

<%@ page session="false" %>

This will improve the performance of the page by eliminating the overhead of session creation or retrieval.

Note that although servlets by default do not use a session, JSP pages by default do use a session. For background information, see "Servlet Sessions".)

Classpath and Class Loader Issues (Non-OSE Only)

OracleJSP uses its own classpath, distinct from the Web server classpath, and by default uses its own class loader to load classes from this classpath. This has significant advantages and disadvantages.

The OracleJSP classpath combines the following elements:

If there are classes you want loaded by the OracleJSP class loader instead of the system class loader, use the OracleJSP classpath configuration parameter, or place the classes in the OracleJSP default classpath. See "Advantages and Disadvantages of the OracleJSP Class Loader" for related discussion.

OracleJSP Default Classpath

Oracle JSP defines standard locations on the Web server for locating .class files and .jar files for classes (such as JavaBeans) that it requires. OracleJSP will find files in these locations without any Web server classpath configuration.

These locations are as follows and are relative to the application root:

/WEB-INF/classes 
/WEB-INF/lib 
/_pages


Important:

If you want classes in the WEB-INF directories to be loaded by the system class loader instead of the OracleJSP class loader, place the classes somewhere in the Web server classpath as well. The system class loader takes priority--any class that is placed in both classpaths will always be loaded by the system class loader. 


The _pages directory is the default location for translated and compiled JSP pages (as output by the JSP translator).

The classes directory is for individual Java .class files. These classes should be stored in subdirectories under the classes directory, according to Java package naming conventions.

For example, consider a JavaBean called LottoBean whose code defines it to be in the oracle.jsp.sample.lottery package. OracleJSP will look for LottoBean.class in the following location relative to the application root:

/WEB-INF/classes/oracle/jsp/sample/lottery/LottoBean.class

The lib directory is for .jar files. Because Java package structure is specified in the .jar file structure, the .jar files are all directly in the lib directory (not in subdirectories).

As an example, LottoBean.class might be stored in lottery.jar, located as follows relative to the application root:

/WEB-INF/lib/lottery.jar

The application root directory can be located in any of the following locations (as applicable, depending on your Web server and servlet environment), listed in the order they are searched:

OracleJSP classpath Configuration Parameter

Use the OracleJSP classpath configuration parameter to add to the OracleJSP classpath.

For more information about this parameter, see "OracleJSP Configuration Parameters (Non-OSE)".

For information about how to set this parameter in the Apache/JServ, JSWDK, and Tomcat environments, see "OracleJSP Configuration Parameter Settings".

Advantages and Disadvantages of the OracleJSP Class Loader

Using the OracleJSP class loader results in the following advantages and disadvantages:

It follows that in a deployment environment, you will typically not want to use the OracleJSP classpath. By default, the classpath parameter is empty.

OracleJSP Runtime Page and Class Reloading (Non-OSE Only)

This section describes conditions under which OracleJSP retranslates pages, reloads pages, and reloads classes during runtime. This discussion does not apply to JSP pages running in the Oracle9i Servlet Engine.

Dynamic Page Retranslation

As a Web application is running, the OracleJSP container by default will automatically retranslate and reload a JSP page whenever the page source is modified.

OracleJSP checks whether the last-modified time of the page implementation class file, as indicated in the OracleJSP in-memory cache, is older than the last-modified time of the JSP page source file.

You can avoid the overhead of OracleJSP checking timestamps for retranslation by setting the OracleJSP developer_mode flag to false. This is advantageous in a deployment environment, where source and class files will typically not change. For more information about this flag, see "OracleJSP Configuration Parameters (Non-OSE)". For how to set it, see "OracleJSP Configuration Parameter Settings".


Notes:

  • Because of the usage of in-memory values for the class file last-modified time, note that removing a page implementation class file from the file system will not cause OracleJSP to retranslate the associated JSP page source. OracleJSP will only retranslate when the JSP page source file timestamp changes.

  • The class file will be regenerated when the cache is lost. This happens whenever a request is directed to this page after the server is restarted or after another page in this application has been retranslated.

 

Dynamic Page Reloading

The OracleJSP container will automatically reload a JSP page (in other words, reload the generated page implementation class) in the following circumstances:

Dynamic Class Reloading

By default, before OracleJSP dispatches a request that will execute a Java class that was loaded by the OracleJSP class loader, it checks to see if the class file has been modified since it was first loaded. If the class has been modified, then the OracleJSP class loader reloads it.

This applies only to classes in the OracleJSP classpath, which includes the following:

As mentioned in the preceding section, "Dynamic Page Reloading", reloading a class results in the dynamic reloading of JSP pages that reference that class.


Important:

  • Remember that classes must be in the JSP classpath, not the system classpath, to be dynamically reloaded. If they are in the system classpath as well, the system class loader may take precedence in some circumstances, possibly interfering with JSP automatic-reloading functionality.

  • Dynamic class reloading can be expensive in terms of CPU usage. You can disable this feature by setting the OracleJSP developer_mode parameter to false. This is appropriate in deployment environments where classes are not expected to change.

 

For information about the classpath and developer_mode configuration parameters and how to set them, see "OracleJSP Configuration Parameters (Non-OSE)" and "OracleJSP Configuration Parameter Settings".

Considerations for the Oracle9i Servlet Engine

The Oracle9i Servlet Engine (OSE) is integrated with the Oracle9i database and middle-tier database cache. To run in OSE, a JSP page must be deployed (loaded and published) into Oracle9i. The details of deploying JSP pages into Oracle9i are discussed in Chapter 6, "JSP Translation and Deployment". This section discusses special programming considerations for the OSE environment and provides an overview of key OSE characteristics.

A JSP application can run in OSE by using the Oracle HTTP Server, powered by Apache, as a front-end Web server (generally recommended), or by using OSE as the Web server directly. See "Oracle Web Application Data-Access Strategies". When installing Oracle9i, Oracle HTTP Server is set as the default Web server. Refer to your installation instructions if you want to change this setting.

It is assumed that JSP pages running in the Oracle9i Servlet Engine are intended for data access, so some background is provided on database connections through Java.

JSP code is generally completely portable between OSE and other environments where OracleJSP is used. The exception is that connecting through the JDBC server-side internal driver is different (for example, does not require a connect string), as mentioned in "Database Connections Through Java".

Aside from connecting through the server-side internal driver or using any other features specific to the Oracle JVM, JSP pages written for OSE are portable to other environments running OracleJSP. The original code has to be modified and re-translated only if Oracle9i-specific features were used.

The following topics are covered here:

Introduction to the Oracle JVM and JDBC Server-Side Internal Driver

Each Oracle session through Java invokes its own dedicated Java virtual machine. This one-to-one correspondence between sessions and JVMs is important to keep in mind.

Any Java program running inside a JVM in the target Oracle9i database or middle-tier database cache typically uses the JDBC server-side internal driver to access the local SQL engine. This driver is intrinsically tied to Oracle9i and the Oracle JVM. The driver runs as part of the same process as the database. It also runs within a default Oracle session--the same session in which the JVM was invoked.

The server-side internal driver is optimized to run within the database or database cache and provide direct access to SQL data and PL/SQL subprograms. The entire JVM operates in the same address space as the database or database cache and the SQL engine. Access to the SQL engine is a function call--there is no network. This enhances the performance of your JDBC programs and is much faster than executing a remote Oracle Net call to access the SQL engine.

Database Connections Through Java

The information here is applicable for connections to either the middle-tier database cache or the back-end database. (Both are referred to as simply "the database" for this discussion.)

Because the JDBC server-side internal driver runs within a default Oracle session, you are already "connected" to the database implicitly. There are two JDBC methods you can use to access the default connection:

Using the defaultConnection() method is generally recommended.

It is also possible to use the server-side Thin driver for an internal connection (a connection to the database in which your Java code is running), but this is not typical.


Notes:

  • Alternatively, you can connect using custom JavaBeans provided with OracleJSP. See "Oracle Data-Access JavaBeans".

  • You are not required to register the OracleDriver class for connecting with the server-side internal driver, although there is no harm in doing so. This is true whether you are using getConnection() or defaultConnection() to make the connection.

 

For more information about server-side connections through Oracle JDBC, see the Oracle9i JDBC Developer's Guide and Reference.

Connecting with the OracleDriver Class defaultConnection() Method

The oracle.jdbc.driver.OracleDriver class defaultConnection() method is an Oracle extension you can use to make an internal database connection. This method always returns the same connection object. Even if you invoke this method multiple times, assigning the resulting connection object to different variable names, a single connection object is reused.

The defaultConnection() method does not take a connect string. For example:

import java.sql.*; 
import oracle.jdbc.driver.*; 
  
class JDBCConnection 
{ 
  public static Connection connect() throws SQLException 
  { 
    Connection conn = null; 
    try {  
      // connect with the server-side internal driver
         OracleDriver ora = new OracleDriver(); 
         conn = ora.defaultConnection(); 
      } 
 
    } catch (SQLException e) {...}
    return conn; 
  } 
}

Note that there is no conn.close() call in the example. When JDBC code is running inside the target server, the connection is an implicit data channel, not an explicit connection instance as from a client. It should typically not be closed.

If you do call the close() method, be aware of the following:

Connecting with the DriverManager.getConnection() Method

Instead of using the defaultConnection() method to make an internal database connection, you can use the static DriverManager.getConnection() method with either of the following connect strings:

Connection conn = DriverManager.getConnection("jdbc:oracle:kprb:");

or:

Connection conn = DriverManager.getConnection("jdbc:default:connection:");

Any user name or password you include in the URL string is ignored in connecting to the server default connection.

The DriverManager.getConnection() method returns a new Java Connection object every time you call it. Note that although the method is not creating a new physical connection (only a single implicit connection is used), it is returning a new object.

The fact that DriverManager.getConnection() returns a new connection object every time you call it is significant if you are working with object maps, known as "type maps". A type map, for mapping Oracle SQL object types to Java classes, is associated with a specific Connection object and with any state that is part of the object. If you want to use multiple type maps as part of your program, then you can call getConnection() to create a new Connection object for each type map. For general information about type maps, see the Oracle9i JDBC Developer's Guide and Reference.

Connecting with the Server-Side Thin Driver

The Oracle JDBC server-side Thin driver is generally intended for connecting to one database from within another database. It is possible, however, to use the server-side Thin driver for an internal connection. Specify a connect string as you would for any usage of the Oracle JDBC Thin driver.

This feature offers the possible advantage of code portability between the Oracle9i Servlet Engine and other servlet environments; however, the server-side internal driver offers more efficient performance.

No Auto-Commit in Server-Side Internal Driver

The JDBC auto-commit feature is disabled in the server-side internal driver. You must commit or roll back changes manually.

No Connection Pooling or Caching with Server-Side Internal Driver

Connection pooling and caching is not applicable when using the server-side internal driver, because it uses a single implicit database connection. Attempts to use these features through the internal driver may actually degrade performance.

Use of JNDI by the Oracle9i Servlet Engine

The Oracle9i Servlet Engine uses a JNDI mechanism to look up "published" JSP pages and servlets, although this mechanism is generally invisible to the JSP developer or user. Publishing a JSP page, which you accomplish during deployment to OSE, involves either running the Oracle session-shell publishjsp command (for deployment with server-side translation) or running the session-shell publishservlet command (for deployment with client-side translation).

The publishservlet command requires you to specify a virtual path name and a servlet name for the page implementation class. The virtual path name is then used to invoke the page through a URL, or to include or forward to the page from any other page running in OSE.

The publishjsp command can either take a virtual path name and servlet name on the command line, or will infer them from the JSP source file name and directory path that you specify.

Both the servlet name and the virtual path name are entered into the Oracle9i JNDI namespace, but the JSP developer or user need only be aware of the virtual path name.

For more information about publishing a JSP page for OSE, see "Translating and Publishing JSP Pages in Oracle9i (Session Shell publishjsp)", for deployment with server-side translation, or "Publishing Translated JSP Pages in Oracle9i (Session Shell publishservlet)", for deployment with client-side translation.

For general information about how the Oracle9i Servlet Engine uses JNDI, see the Oracle9i Servlet Engine Developer's Guide.

Equivalent Code for OracleJSP Runtime Configuration Parameters

Some OracleJSP configuration parameters take effect during translation; others take effect during runtime. When you deploy JSP pages to Oracle9i to run in the Oracle9i Servlet Engine, you can make appropriate translation-time settings through command-line options of the OracleJSP pre-translation tool.

At runtime, however, OSE does not support execution-time configuration parameters. The most significant runtime parameter is translate_params, which relates to globalization support. For a discussion of equivalent code, see "Code Equivalent to the translate_params Configuration Parameter".

Considerations for Apache/JServ Servlet Environments

There are special considerations in running OracleJSP in Apache/JServ-based platforms, including Oracle9i Application Server release 1.0.x, because this is a servlet 2.0 environment. The servlet 2.0 specification lacked support for some significant features that are available in servlet 2.1 and 2.2 environments.

For information about how to configure an Apache/JServ environment for OracleJSP, see the following sections:

(If you use Apache/JServ through an Oracle platform, see the installation and configuration documentation for that platform instead.)

The rest of this section, after summarizing the use of Apache/JServ by the Oracle9i Application Server, discusses the following Apache-specific considerations:

Use of Apache/JServ in the Oracle9i Application Server

As of Oracle9i Application Server release 1.0.x, this product uses Apache/JServ as its servlet environment. As in any Apache/JServ or other servlet 2.0 environment, there are special considerations relating to servlet and JSP usage. These are detailed in the sections that follow.


Notes:

  • The Oracle9i Application Server includes the Oracle HTTP Server, powered by Apache, as its Web server. Be aware that if you use the Oracle HTTP Server mod_ose Apache mod to run your JSP application in the Oracle9i Servlet Engine, you are using the OSE servlet 2.2 environment, not the Oracle9i Application Server Apache/JServ servlet 2.0 environment.

  • Future releases of the Oracle HTTP Server and Oracle9i Application Server may use a servlet environment other than Apache/JServ.

 

For a brief overview of the Oracle9i Application Server and its use of the Oracle HTTP Server, see "Support for OracleJSP in Oracle Environments".

Dynamic Includes and Forwards in Apache/JServ

JSP dynamic includes (the jsp:include action) and forwards (the jsp:forward action) rely on request dispatcher functionality that is present in servlet 2.1 and 2.2 environments but not in servlet 2.0 environments.

OracleJSP, however, provides extended functionality to allow dynamic includes and forwards from one JSP page to another JSP page or to a static HTML file in Apache/JServ and other servlet 2.0 environments.

This OracleJSP functionality for servlet 2.0 environments does not, however, allow dynamic forwards or includes to servlets. (Servlet execution is controlled by the JServ or other servlet container, not the OracleJSP container.)

If you want to include or forward to a servlet in Apache/JServ, however, you can create a JSP page that acts as a wrapper for the servlet.

The following example shows a servlet, and a JSP page that acts as a wrapper for that servlet. In an Apache/JServ environment, you can effectively include or forward to the servlet by including or forwarding to the JSP wrapper page.

Servlet Code

Presume that you want to include or forward to the following servlet:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class TestServlet extends HttpServlet {

    public void init(ServletConfig config) throws ServletException
    {
      super.init(config);
      System.out.println("initialized");
    }

    public void destroy()
    {
      System.out.println("destroyed");
    }

    public void service 
        (HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<HTML><BODY>");
        out.println("TestServlet Testing");
        out.println("<H3>The local time is: "+ new java.util.Date());
        out.println("</BODY></HTML>");
    }
}

JSP Wrapper Page Code

You can create the following JSP wrapper (wrapper.jsp) for the preceding servlet.

<%-- wrapper.jsp--wraps TestServlet for JSP include/forward --%>
<%@ page isThreadSafe="true" import="TestServlet" %>
<%! 
  TestServlet s=null;
  public void jspInit() {
    s=new TestServlet();
    try {
      s.init(this.getServletConfig());
    } catch (ServletException se)
    {
      s=null;
    }
  }
  public void jspDestroy() {
    s.destroy();
  }
%>
<% s.service(request,response); %>

Including or forwarding to wrapper.jsp in a servlet 2.0 environment has the same effect as directly including or forwarding to TestServlet in a servlet 2.1 or 2.2 environment.


Notes:

  • Whether to set isThreadSafe to true or false in the wrapper JSP page depends on whether the original servlet is thread-safe.

  • As an alternative to using a wrapper JSP page for this situation, you can add HTTP client code to the original JSP page (the one from which the include or forward is to occur). You can use an instance of the standard java.net.URL class to create an HTTP request from the original JSP page to the servlet. (Note that you cannot share session data or security credentials in this scenario.) Alternatively, you can use the HTTPClient class from Innovation GmbH. The Oracle JVM provides a modified version of this class that supports SSL, directly or through a proxy, when you use https:// for the URL. (See http://www.innovation.ch/java/HTTPClient for general information about this class. Click "Getting Started" for information that includes how to replace the JDK HTTP client with the HTTPClient class.) Details of these alternatives are outside the scope of this document, however, and this approach is generally not recommended.

 

Application Framework for Apache/JServ

The servlet 2.0 specification does not provide the full servlet context framework for application support that is provided in later specifications.

For servlet 2.0 environments, including Apache/JServ, OracleJSP supplies its own application framework using a file, globals.jsa, that you can use as an application marker.

For more information, see "Distinct Applications and Sessions Through globals.jsa".

JSP and Servlet Session Sharing

To share HTTP session information between JSP pages and servlets in an Apache/JServ environment, you must configure your environment so that oracle.jsp.JspServlet (the servlet that acts as the front-end of the OracleJSP container) is in the same zone as the servlet or servlets with which you want your JSP pages to share a session. Consult your Apache documentation for more information.

To verify proper zone setup, some browsers allow you to enable a warning for cookies. In an Apache environment, the cookie name includes the zone name.

Additionally, for applications that use a globals.jsa file, the OracleJSP configuration parameter session_sharing should be set to true (the default) for JSP session data to be accessible to servlets. See these sections for related information:

Directory Alias Translation

Apache supports directory aliasing by allowing you to create a "virtual directory" through an Alias command in the httpd.conf configuration file. This allows Web documents to be placed outside the default doc root directory.

Consider the following sample httpd.conf entry:

Alias /icons/ "/apache/apache139/icons/"

This command should result in icons being usable as an alias for the /apache/apache139/icons/ path. In this way, for example, the file /apache/apache139/icons/art.gif, could be accessed by the following URL:

http://host[:port]/icons/art.gif

Currently, however, this functionality does not work properly for servlets and JSP pages, because the Apache/JServ getRealPath() method returns an incorrect value when processing a file under an alias directory.

OracleJSP provides an Apache-specific configuration parameter, alias_translation, that works around this limitation when you set alias_translation=true (the default setting is false).

Be aware that setting alias_translation=true also results in the alias directory becoming the application root. Therefore, in a dynamic include or forward command where the target file name starts with "/", the expected target file location will be relative to the alias directory.

Consider the following example, which results in all JSP and HTML files under /private/foo being effectively under the application /mytest:

Alias /mytest/ "/private/foo/"

And assume there is a JSP page located as follows:

/private/foo/xxx.jsp

The following dynamic include command will work, because xxx.jsp is directly below the aliased directory, /private/foo, which is effectively the application root:

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

JSP pages in other applications or in the general doc root cannot forward to or include JSP pages or HTML files under the /mytest application. It is only possible to forward to or include pages or HTML files within the same application (per the servlet 2.2 specification).


Notes:

  • An implicit application is created for the Web server document root and each aliasing root.

  • For information about how to set OracleJSP configuration parameters in an Apache/JServ environment, see "Setting OracleJSP Parameters in Apache/JServ".

 


Go to previous page Go to next page
Oracle
Copyright © 1996-2001, Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback