Oracle9iAS Containers for J2EE Support for JavaServer Pages Reference Release 2 (9.0.2) Part Number A95882-01 |
|
This chapter discusses basic programming issues for JSP pages, followed by a JSP "starter sample" for data access.
The following topics are included:
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:
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". |
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).
You can use a jsp:param
tag 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".
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:
ServletContext sc = this.getServletContext();
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.
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
tags. The include()
method only temporarily transfers control; execution returns to the invoking servlet afterward.
Note that the forward()
method clears the output buffer.
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:
name
=
value
pairs. For example:
RequestDispatcher rd = sc.getRequestDispatcher("/jsp/mypage.jsp?username=Smith");
In the target JSP page (or servlet), you can use the getParameter()
method of the implicit request
object to obtain the value of a parameter set in this way.
setAttribute()
method of the HTTP request object. For example:
request.setAttribute("username", "Smith"); RequestDispatcher rd = sc.getRequestDispatcher("/jsp/mypage.jsp");
In the target JSP page (or servlet), you can use the getAttribute()
method of the implicit request
object to obtain the value of a parameter set in this way.
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
.
<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>
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); } }
<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>
This section discusses standard features and Oracle value-added features for resource management:
JspScopeListener
for servlet 2.3 environments, globals.jsa
for servlet 2.0 environments)
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-scope resources. Through this mechanism, a session-scope 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.
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).
"JDBCQueryBean JavaBean Code" below provides a sample JavaBean that implements HttpSessionBindingListener
and a sample JSP page that calls the bean.
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: <PRE> " + e + " </PRE> </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-scope bean is already bound } public synchronized void valueUnbound(HttpSessionBindingEvent event) { try { if (conn != null) conn.close(); } catch (SQLException ignored) {} } }
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
tag 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 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:
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.
OC4J JSP provides the following features for managing application and session resources as well as page and request resources:
JspScopeListener
interface--for managing application-scope, session-scope, page-scope, or request-scope resources in a servlet 2.3 environment such as OC4J
This mechanism adheres to servlet and JSP standards in supporting objects of page
, request
, session
, or application
scope. To create a class that supports session scope as well as other scopes, you can integrate JspScopeListener
with HttpSessionBindingListener
by having the class implement both interfaces. For page
scope in OC4J or JServ environments, you also have the option of using an Oracle-specific runtime implementation.
For information about configuration and how to integrate with HttpSessionBindingListener
, see the Oracle9iAS Containers for J2EE JSP Tag Libraries and Utilities Reference.
globals.jsa
file--for start and end events for application-scope and session-scope objects in a servlet 2.0 environment such as JServ
See "The globals.jsa Event-Handlers" for information.
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 an elementary example.
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".)
In a servlet 2.2 or higher environment, you can also specify a default error page in the web.xml
deployment descriptor with instructions such as the following:
<error-page> <error-code>404</error-code> <location>/error404.html</location> </error-page>
See the Sun Microsystems Java Servlet Specification, Version 2.2 (or higher) for more information about default error pages.
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.
The following example, nullpointer.jsp
, generates an error and uses an error page, myerror.jsp
, to output contents of the implicit exception
object.
<HTML> <BODY> <%@ page errorPage="myerror.jsp" %> Null pointer is generated below: <% String s=null; s.length(); %> </BODY> </HTML>
<HTML> <BODY> <%@ page isErrorPage="true" %> Here is your error: <%= exception %> </BODY> </HTML>
This example results in the following output:
Chapter 1, "General JSP Overview", provides a couple of elementary JSP examples; however, if you are using OC4J, you presumably want to access a 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.
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 or Enterprise JavaBean). For more information about Oracle JDBC, see the Oracle9i JDBC Developer's Guide and Reference.
The OC4J JSP container also supports EJB calls, as well as SQLJ (embedded SQL in Java) for static SQL operations. These and other data-access considerations are covered in "JSP Data-Access Considerations and Features".
There are also custom JavaBeans and custom SQL tags for data access, documented in the Oracle9iAS Containers for J2EE JSP Tag Libraries and Utilities Reference.
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
. (JDBC is used because SQLJ is primarily for static SQL, although Oracle SQLJ adds extensions for dynamic SQL.)
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).
<%@ 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: <PRE> " + e + " </PRE> </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
|
Copyright © 2000, 2002 Oracle Corporation. All Rights Reserved. |
|