Skip Headers

Oracle9i Support for JavaServer Pages Reference
Release 2 (9.2)

Part Number A96657-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

3
Basics

This chapter discusses key basic issues for JSP development, followed by a JSP "starter sample" for data access.

The following topics are included:

Application Root and Doc Root Functionality

This section provides an overview of application roots and doc roots, distinguishing between servlet 2.2 functionality and servlet 2.0 functionality.

Application Roots in Servlet 2.2 Environments

As mentioned earlier, the servlet 2.2 specification provides for each application to have its own servlet context. Each servlet context is associated with a directory path in the server file system, which is the base path for modules of the application. This is the application root. Each application has its own application root.

This is similar to how a Web server uses a doc root as the root location for HTML pages and other files belonging to a Web application.

For an application in a servlet 2.2 environment, there is a one-to-one mapping between the application root (for servlets and JSP pages) and the doc root (for static files, such as HTML files)--they are essentially the same thing.

Note that a servlet URL has the following general form:

http://host[:port]/contextpath/servletpath

When a servlet context is created, a mapping is specified between the application root and the context path portion of a URL.

For example, consider an application with the application root /home/dir/mybankappdir, which is mapped to the context path mybank. Further assume the application includes a servlet whose servlet path is loginservlet. This servlet can be invoked as follows:

http://host[:port]/mybank/loginservlet

(The application root directory name itself is not visible to the end-user.)

To continue this example for an HTML page in this application, the following URL points to the file /home/dir/mybankappdir/dir1/abc.html:

http://host[:port]/mybank/dir1/abc.html

For each servlet environment there is also a default servlet context. For this context, the context path is simply "/", which is mapped to the default servlet context application root.

For example, assume the application root for the default context is /home/mydefaultdir, and a servlet with the servlet path myservlet uses the default context. Its URL would be as follows (again, the application root directory name itself is not visible to the user):

http://host[:port]/myservlet

(The default context is also used if there is no match for the context path specified in a URL.)

Continuing this example for an HTML file, the following URL points to the file /home/mydefaultdir/dir2/def.html:

http://host[:port]/dir2/def.html

Oracle Implementation of Application Root Functionality in Servlet 2.0 Environments

Apache JServ and other servlet 2.0 environments have no concept of application roots, because there is only a single application environment. The Web server doc root is effectively the application root.

For Apache, the doc root is typically some .../htdocs directory. In addition, it is possible to specify "virtual" doc roots through alias settings in the httpd.conf configuration file.

In a servlet 2.0 environment, the Oracle JSP container offers the following functionality regarding doc roots and application roots:

Overview of JSP Applications and Sessions

This section provides a brief overview of how JSP applications and sessions are supported by the Oracle JSP container.

General Application and Session Support in the Oracle JSP Container

The Oracle JSP container uses underlying servlet mechanisms for managing applications and sessions. For servlet 2.1 and servlet 2.2 environments, these underlying mechanisms are sufficient, providing a distinct servlet context and session object for each JSP application.

Using the servlet mechanisms becomes problematic, however, in a servlet 2.0 environment such as JServ. The concept of a Web application was not well defined in the servlet 2.0 specification, so in a servlet 2.0 environment there is only one servlet context per servlet container. Additionally, there is one session object only per servlet container. However, for JServ and other servlet 2.0 environments, Oracle provides extensions to optionally allow distinct servlet contexts and session objects for each application. (This is unnecessary for Web servers hosting just a single application.)


Note:

For additional information relevant to JServ and other servlet 2.0 environments, see "Considerations for JServ Servlet Environments" and "Overview of globals.jsa Functionality".


JSP Default Session Requests

Generally speaking, servlets do not request an HTTP session by default. However, JSP page implementation classes do request an HTTP session by default. You can override this by setting the session parameter to false in a JSP page directive, as follows:

<%@ page ... session="false" %>

JSP-Servlet Interaction

Although coding JSP pages is convenient in many ways, some situations call for servlets. One example is when you are outputting binary data, as discussed in "Reasons to Avoid Binary Data in JSP Pages".

Therefore, it is sometimes necessary to go back and forth between servlets and JSP pages in an application. This section discusses how to accomplish this, covering the following topics:

Invoking a Servlet from a JSP Page

As when invoking one JSP page from another, you can invoke a servlet from a JSP page through the jsp:include and jsp:forward action tags. (See "JSP Actions and the <jsp: > Tag Set".) Following is an example:

<jsp:include page="/servlet/MyServlet" flush="true" />

When this statement is encountered during page execution, the page buffer is output to the browser and the servlet is executed. When the servlet has finished executing, control is transferred back to the JSP page and the page continues executing. This is the same functionality as for jsp:include actions from one JSP page to another.

And as with jsp:forward actions from one JSP page to another, the following statement would clear the page buffer, terminate the execution of the JSP page, and execute the servlet:

<jsp:forward page="/servlet/MyServlet" />


Important:

You cannot include or forward to a servlet in JServ or other servlet 2.0 environments; you would have to write a JSP wrapper page instead. For information, see "Dynamic Includes and Forwards in JServ".


Passing Data to a Servlet Invoked from a JSP Page

When dynamically including or forwarding to a servlet from a JSP page, you can use a jsp:param tag to pass data to the servlet (the same as when including or forwarding to another JSP page).

A jsp:param tag is used within a jsp:include or jsp:forward tag. Consider the following example:

<jsp:include page="/servlet/MyServlet" flush="true" >
   <jsp:param name="username" value="Smith" />
   <jsp:param name="userempno" value="9876" />
</jsp:include>

For more information about the jsp:param tag, see "JSP Actions and the <jsp: > Tag Set".

Alternatively, you can pass data between a JSP page and a servlet through an appropriately scoped JavaBean or through attributes of the HTTP request object. Using attributes of the request object is discussed later, in "Passing Data Between a JSP Page and a Servlet".


Note:

The jsp:param tag was introduced in the JSP 1.1 specification.


Invoking a JSP Page from a Servlet

You can invoke a JSP page from a servlet through functionality of the standard javax.servlet.RequestDispatcher interface. Complete the following steps in your code to use this mechanism.

  1. Get a servlet context instance from the servlet instance:

    ServletContext sc = this.getServletContext();
    
    
  2. Get a request dispatcher from the servlet context instance, specifying the page-relative or application-relative path of the target JSP page as input to the getRequestDispatcher() method:

    RequestDispatcher rd = sc.getRequestDispatcher("/jsp/mypage.jsp");
    
    

    Prior to or during this step, you can optionally make data available to the JSP page through attributes of the HTTP request object. See "Passing Data Between a JSP Page and a Servlet" below for information.

  3. Invoke the include() or forward() method of the request dispatcher, specifying the HTTP request and response objects as arguments. For example:

    rd.include(request, response);
    
    

    or:

    rd.forward(request, response);
    
    

    The functionality of these methods is similar to that of jsp:include and jsp:forward actions. The include() method only temporarily transfers control; execution returns to the invoking servlet afterward.

    Note that the forward() method clears the output buffer.


    Notes:
    • The request and response objects would have been obtained earlier using standard servlet functionality, such as the doGet() method specified in the javax.servlet.http.HttpServlet class.
    • This functionality was introduced in the servlet 2.1 specification.

Passing Data Between a JSP Page and a Servlet

The preceding section, "Invoking a JSP Page from a Servlet", notes that when you invoke a JSP page from a servlet through the request dispatcher, you can optionally pass data through the HTTP request object.

You can accomplish this using either of the following approaches.

JSP-Servlet Interaction Samples

This section provides a JSP page and a servlet that use functionality described in the preceding sections. The JSP page Jsp2Servlet.jsp includes the servlet MyServlet, which includes another JSP page, welcome.jsp.

Code for Jsp2Servlet.jsp
<HTML>
<HEAD> <TITLE> JSP Calling Servlet Demo </TITLE> </HEAD>
<BODY>

<!-- Forward processing to a servlet -->
<% request.setAttribute("empid", "1234"); %>
<jsp:include page="/servlet/MyServlet?user=Smith" flush="true"/>

</BODY>
</HTML>

Code for MyServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.PrintWriter;
import java.io.IOException;

public class MyServlet extends HttpServlet {
    public void doGet (HttpServletRequest request,
                       HttpServletResponse response) 
      throws IOException, ServletException {
      PrintWriter out= response.getWriter(); 
      out.println("<B><BR>User:" + request.getParameter("user"));
      out.println
          (", Employee number:" + request.getAttribute("empid") + "</B>");
      this.getServletContext().getRequestDispatcher("/jsp/welcome.jsp").
        include(request, response);
    }
}

Code for welcome.jsp
<HTML>
<HEAD> <TITLE> The Welcome JSP  </TITLE> </HEAD>
<BODY>

<H3> Welcome! </H3>
<P><B> Today is <%= new java.util.Date() %>.  Have a nice day! </B></P>
</BODY>
</HTML>

JSP Resource Management

The javax.servlet.http package offers a standard mechanism for managing session resources. Additionally, Oracle provides extensions for managing application, session, page, and request resources.

Standard Session Resource Management with HttpSessionBindingListener

A JSP page must appropriately manage resources acquired during its execution, such as JDBC connection, statement, and result set objects. The standard javax.servlet.http package provides the HttpSessionBindingListener interface and HttpSessionBindingEvent class to manage session-scoped resources. Through this mechanism, a session-scoped query bean could, for example, acquire a database cursor when the bean is instantiated and close it when the HTTP session is terminated. (The example in "JSP Starter Sample for Data Access" opens and closes the connection for each query, which adds overhead.)

This section describes use of the HttpSessionBindingListener valueBound() and valueUnbound() methods.


Note:

The bean instance must register itself in the event notification list of the HTTP session object, but the jsp:useBean statement takes care of this automatically.


The valueBound() and valueUnbound() Methods

An object that implements the HttpSessionBindingListener interface can implement a valueBound() method and a valueUnbound() method, each of which takes an HttpSessionBindingEvent instance as input. These methods are called by the servlet container--the valueBound() method when the object is stored in the session; the valueUnbound() method when the object is removed from the session or when the session times-out or becomes invalid. Usually, a developer will use valueUnbound() to release resources held by the object (in the example below, to release the database connection).


Note:

Oracle9i release 2 provides extensions for additional resource management, allowing you to program JavaBeans to manage page-scoped, request-scoped, or application-scoped resources as well as session-scoped resources. See "Oracle JSP Event Handling with JspScopeListener".


"JDBCQueryBean JavaBean Code" below provides a sample JavaBean that implements HttpSessionBindingListener and a sample JSP page that calls the bean.

JDBCQueryBean JavaBean Code

Following is the sample code for JDBCQueryBean, a JavaBean that implements the HttpSessionBindingListener interface. (It uses the JDBC OCI driver for its database connection; use an appropriate JDBC driver and connection string if you want to run this example yourself.)

JDBCQueryBean gets a search condition through the HTML request (as described in "The UseJDBCQueryBean JSP Page"), executes a dynamic query based on the search condition, and outputs the result.

This class also implements a valueUnbound() method (as specified in the HttpSessionBindingListener interface) that results in the database connection being closed at the end of the session.

package mybeans;

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

public class JDBCQueryBean implements HttpSessionBindingListener
{
  String searchCond = "";
  String result = null;
  
  public void JDBCQueryBean() {
  }
  
  public synchronized String getResult() {
    if (result != null) return result;
    else return runQuery();
  }
  
  public synchronized void setSearchCond(String cond) {
    result = null;
    this.searchCond = cond;
  }
  
  private Connection conn = null;
  
  private String runQuery() {
    StringBuffer sb = new StringBuffer(); 
    Statement stmt = null; 
    ResultSet rset = null;
    try {
      if (conn == null) {
        DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
        conn = DriverManager.getConnection("jdbc:oracle:oci8:@",
                                           "scott", "tiger");

      }
      
      stmt = conn.createStatement();
      rset = stmt.executeQuery ("SELECT ename, sal FROM scott.emp "+ 
            (searchCond.equals("") ? "" : "WHERE " + searchCond ));
      result = formatResult(rset);
      return result;

    } catch (SQLException e) { 
      return ("<P> SQL error:  " + e + "  </P>\n");
    }
    finally {
      try {
        if (rset != null) rset.close();
        if (stmt != null) stmt.close();
      }
      catch (SQLException ignored) {}
    }
  }
  
  private String formatResult(ResultSet rset) throws SQLException  {
    StringBuffer sb = new StringBuffer();
    if (!rset.next())    
      sb.append("<P> No matching rows.<P>\n");
    else {  
      sb.append("<UL><B>"); 
      do {  sb.append("<LI>" + rset.getString(1) + 
            " earns $ " + rset.getInt(2) + "</LI>\n");
      } while (rset.next());
      sb.append("</B></UL>"); 
    }
    return sb.toString();
  }
  
  public void valueBound(HttpSessionBindingEvent event) {
    // do nothing -- the session-scoped bean is already bound
  }
  
  public synchronized void valueUnbound(HttpSessionBindingEvent event) {
    try { 
      if (conn != null) conn.close();
    }
    catch (SQLException ignored) {}
  }
}


Note:

The preceding code serves as a sample only. This is not necessarily an advisable way to handle database connection pooling in a large-scale Web application.


The UseJDBCQueryBean JSP Page

The following JSP page uses the JDBCQueryBean JavaBean defined in "JDBCQueryBean JavaBean Code" above, invoking the bean with session scope. It uses JDBCQueryBean to display employee names that match a search condition entered by the user.

JDBCQueryBean gets the search condition through the jsp:setProperty command in this JSP page, which sets the searchCond property of the bean according to the value of the searchCond request parameter input by the user through the HTML form. (The HTML INPUT tag is what specifies that the search condition entered in the form be named searchCond.)

<jsp:useBean id="queryBean" class="mybeans.JDBCQueryBean" scope="session" />
<jsp:setProperty name="queryBean" property="searchCond" />

<HTML>
<HEAD> <TITLE> The UseJDBCQueryBean JSP  </TITLE> </HEAD>
<BODY BGCOLOR="white">

<% String searchCondition = request.getParameter("searchCond"); 
   if (searchCondition != null) { %>
      <H3> Search results for : <I> <%= searchCondition %> </I> </H3>
      <%= queryBean.getResult() %>
      <HR><BR>
<% }  %>

<B>Enter a search condition for the EMP table:</B>

<FORM METHOD="get"> 
<INPUT TYPE="text" NAME="searchCond" VALUE="ename LIKE 'A%' " SIZE="40">
<INPUT TYPE="submit" VALUE="Ask Oracle">
</FORM>

</BODY>
</HTML>

Following is sample input and output for this page:

Text description of jdbcquer.gif follows.

Text description of the illustration jdbcquer.gif

Advantages of HttpSessionBindingListener

In the preceding example, an alternative to the HttpSessionBindingListener mechanism would be to close the connection in a finalize() method in the JavaBean. The finalize() method would be called when the bean is garbage-collected after the session is closed. The HttpSessionBindingListener interface, however, has more predictable behavior than a finalize() method. Garbage collection frequency depends on the memory consumption pattern of the application. By contrast, the valueUnbound() method of the HttpSessionBindingListener interface is called reliably at session shutdown.

Overview of Oracle Extensions for Resource Management

Oracle provides the following extensions for managing application and session resources as well as page and request resources:

JSP Runtime Error Processing

While a JSP page is executing and processing client requests, runtime errors can occur either inside the page or outside the page (such as in a called JavaBean). This section describes the JSP error processing mechanism and provides a simple example.

Using JSP Error Pages

Any runtime error encountered during execution of a JSP page is handled using the standard Java exception mechanism in one of two ways:

You can specify the URL of an error page by setting the errorPage parameter in a page directive in the originating JSP page. (For an overview of JSP directives, including the page directive, see "Directives".)

An error page must have a page directive setting the isErrorPage parameter to true.

The exception object describing the error is a java.lang.Exception instance that is accessible in the error page through the implicit exception object.

Only an error page can access the implicit exception object. (For information about JSP implicit objects, including the exception object, see "Implicit Objects".)

See "JSP Error Page Example" below for an example of error page usage.


Note:

There is ambiguity in the JSP 1.1 specification regarding exception types that can be handled through the JSP mechanism.

In the Oracle JSP container, a page implementation class generated by the translator can handle an instance of the java.lang.Exception class or a subclass, but cannot handle an instance of the java.lang.Throwable class or any subclass other than Exception. A Throwable instance will be thrown by the JSP container to the servlet container.

The ambiguity is expected to be addressed in the JSP 1.2 specification. The Oracle behavior will be modified appropriately in a future release.


JSP Error Page Example

The following example, nullpointer.jsp, generates an error and uses an error page, myerror.jsp, to output contents of the implicit exception object.

Code for nullpointer.jsp
<HTML>
<BODY>
<%@ page errorPage="myerror.jsp" %>
Null pointer is generated below:
<%
   String s=null;
   s.length();
%>
</BODY>
</HTML>

Code for myerror.jsp
<HTML>
<BODY>
<%@ page isErrorPage="true" %>
Here is your error:
<%= exception %>
</BODY>
</HTML>

This example results in the following output:

Text description of myerror.gif follows.

Text description of the illustration myerror.gif


Note:

The line "Null pointer is generated below:" in nullpointer.jsp is not output when processing is forwarded to the error page. This shows the difference between jsp:include and jsp:forward functionality--with jsp:forward, the output from the "forward-to" page replaces the output from the "forward-from" page.


JSP Starter Sample for Data Access

Chapter 1, "General Overview", provides a couple of simple JSP examples; however, if you are using the Oracle JSP container, you presumably want to access an Oracle database. This section offers a more interesting sample that uses standard JDBC code in a JSP page to perform a query.

Because the JDBC API is simply a set of Java interfaces, JavaServer Pages technology directly supports its use within JSP scriptlets.


Notes:
  • Oracle JDBC provides several driver alternatives: 1) the JDBC OCI driver for use with an Oracle client installation; 2) a 100%-Java JDBC Thin driver that can be used in essentially any client situation, including applets; 3) a JDBC server-side Thin driver to access one Oracle database from within another Oracle database; and 4) a JDBC server-side internal driver to access the database within which the Java code is running (such as from a Java stored procedure). For more information about Oracle JDBC, see the Oracle9i JDBC Developer's Guide and Reference.
  • The Oracle JSP container also supports SQLJ (embedded SQL in Java) for static SQL operations. This is discussed in "Oracle JSP Support for Oracle SQLJ".

The following example creates a query dynamically from search conditions the user enters through an HTML form (typed into a box and entered with an Ask Oracle button). To perform the specified query, it uses JDBC code in a method called runQuery() that is defined in a JSP declaration. It also defines a method formatResult() within the JSP declaration to produce the output. The runQuery() method uses the scott schema with password tiger.

The HTML INPUT tag specifies that the string entered in the form be named cond. Therefore, cond is also the input parameter to the getParameter() method of the implicit request object for this HTTP request, and the input parameter to the runQuery() method (which puts the cond string into the WHERE clause of the query).


Notes:
  • Another approach to this example would be to define the runQuery() method in <%...%> scriptlet syntax instead of <%!...%> declaration syntax.
  • This example uses the JDBC OCI driver, which requires an Oracle client installation. If you want to run this sample, use an appropriate JDBC driver and connection string.

<%@ page language="java" import="java.sql.*" %>
<HTML>
<HEAD> <TITLE> The JDBCQuery JSP  </TITLE> </HEAD>
<BODY BGCOLOR="white">
<% String searchCondition = request.getParameter("cond"); 
   if (searchCondition != null) { %>
      <H3> Search results for  <I> <%= searchCondition %> </I> </H3>
      <B> <%= runQuery(searchCondition) %> </B> <HR><BR>
<% }  %>
<B>Enter a search condition:</B>
<FORM METHOD="get"> 
<INPUT TYPE="text" NAME="cond" SIZE=30>
<INPUT TYPE="submit" VALUE="Ask Oracle");
</FORM>
</BODY>
</HTML>
<%-- Declare and define the runQuery() method. --%>
<%! private String runQuery(String cond) throws SQLException {
     Connection conn = null; 
     Statement stmt = null; 
     ResultSet rset = null; 
     try {
        DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
        conn = DriverManager.getConnection("jdbc:oracle:oci8:@",
                                           "scott", "tiger");
        stmt = conn.createStatement();
        // dynamic query
        rset = stmt.executeQuery ("SELECT ename, sal FROM scott.emp "+ 
                           (cond.equals("") ? "" : "WHERE " + cond ));
       return (formatResult(rset));
     } catch (SQLException e) { 
         return ("<P> SQL error:  " + e + "  </P>\n");
     } finally {
         if (rset!= null) rset.close(); 
         if (stmt!= null) stmt.close();
         if (conn!= null) conn.close();
     }
  }
  private String formatResult(ResultSet rset) throws SQLException {
    StringBuffer sb = new StringBuffer();
    if (!rset.next())
      sb.append("<P> No matching rows.<P>\n");
    else {  sb.append("<UL>"); 
            do {  sb.append("<LI>" + rset.getString(1) + 
                            " earns $ " + rset.getInt(2) + ".</LI>\n");
            } while (rset.next());
           sb.append("</UL>"); 
    }
    return sb.toString();
  }
%>

The graphic below illustrates sample output for the following input:

sal >= 2500 AND sal < 5000

Text description of jdbcresu.gif follows.

Text description of the illustration jdbcresu.gif


Go to previous page Go to next page
Oracle
Copyright © 2000, 2002 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