Chapter 1: Building Web Applications in WebLogic


Web applications are an important part of the Java 2 Enterprise Edition (J2EE) platform because the Web components are responsible for key client- facing presentation and business logic. A poorly designed Web application will ruin the best business- tier components and services. In this chapter, we will review key Web application concepts and technologies and their use in WebLogic Server, and we will provide a number of recommendations and best practices related to Web application design and construction in WebLogic Server.

This chapter also provides the foundation for the discussion of recommended Web application architectures in Chapter 2 and the construction and deployment of a complex, realistic Web application in Chapters 3, 4, and 5.

Java Servlets and JSP Key Concepts

In this section we will review some key concepts related to Java Servlets and JavaServer Pages. If you are unfamiliar with these technologies, or if you need additional background material, you should read one of the many fine books available on the subject. Suggestions include Java Servlet Programming Bible by Suresh Rajagopalan et. al. (John Wiley & Sons, 2002), Java Servlet Programming by Jason Hunter (O Reilly & Associates, 2001), and Core Servlets and JavaServer Pages by Marty Hall (Prentice Hall PTR, 2000).

Characteristics of Servlets

Java servlets are fundamental J2EE platform components that provide a request/response interface for both Web requests and other requests such as XML messages or file transfer functions. In this section, we will review the characteristics of Java servlets as background for a comparison of servlets with JavaServer Pages (JSP) technology and the presentation of best practices later in the chapter.

Servlets Use the Request/Response Model

Java servlets are a request/response mechanism: a programming construct designed to respond to a particular request with a dynamic response generated by the servlet s specific Java implementation. Servlets may be used for many types of request/response scenarios, but they are most often employed in the creation of HyperText Transfer Protocol (HTTP) responses in a Web application. In this role, servlets replace other HTTP request/response mechanisms such as Common Gateway Interface (CGI) scripts.

The simple request/response model becomes a little more complex once you add chaining and filtering capabilities to the servlet specification. Servlets may now participate in the overall request/response scenario in additional ways, either by preprocessing the request and passing it on to another servlet to create the response or by postprocessing the response before returning it to the client. Later in this chapter, we ll discuss servlet filtering as a mechanism for adding auditing, logging, and debugging logic to your Web application.

Servlets Are Pure Java Classes

Simply stated, a Java servlet is a pure Java class that implements the javax.servlet .Servlet interface. The application server creates an instance of the servlet class and uses it to handle incoming requests. The Servlet interface defines the set of methods that should be implemented to allow the application server to manage the servlet life cycle (discussed later in this chapter) and pass requests to the servlet instance for processing. Servlets intended for use as HTTP request/response mechanisms normally extend the javax.servlet.http.HttpServlet class, although they may implement and use the Servlet interface methods if desired. The HttpServlet class implements the Servlet interface and implements the init() , destroy() , and service() methods in a default manner. For example, the service() method in HttpServlet interrogates the incoming HttpServletRequest object and forwards the request to a series of individual methods defined in the HttpServlet class based on the type of request. These methods include the following:

  • doGet() for handling GET , conditional GET , and HEAD requests

  • doPost() for POST requests

  • doPut() for PUT requests

  • doDelete() for DELETE requests

  • doOptions() for OPTIONS requests

  • doTrace() for TRACE requests

The doGet() , doPost() , doPut() , and doDelete() methods in HttpServlet return a BAD_REQUEST (400) error as their default response. Servlets that extend HttpServlet typically override and implement one or more of these methods to generate the desired response. The doOptions() and doTrace() methods are typically not overridden in the servlet. Their implementations in the HttpServlet class are designed to generate the proper response, and they are usually sufficient.

A minimal HTTP servlet capable of responding to a GET request requires nothing more than extending the HttpServlet class and implementing the doGet() method.

WebLogic Server provides a number of useful sample servlets showing the basic approach for creating HTTP servlets. These sample servlets are located in the samples/server/examples/src/examples/servlets subdirectory beneath the Web-Logic Server home directory, a directory we refer to as $WL_HOME throughout the rest of the book. We will examine some additional example servlets in detail during the course of this chapter. These example servlets are available on the companion Web site for this book at http://www.wiley.com/compbooks/masteringweblogic.

Creating the HTML output within the servlet s service() or do XXX () method is very tedious . This deficiency was addressed in the J2EE specification by introducing a scripting technology, JavaServer Pages (JSP), discussed later in this chapter.

Servlets Have a Life Cycle

A servlet is an instance of the servlet class and has a life cycle similar to that of any other Java object. When the servlet is first required to process a request, the application server loads the servlet class, creates an instance of the class, initializes the instance, calls the servlet s init() method, and calls the service() method to process the request. In normal servlet operation, this same instance of the servlet class will be used for all subsequent requests.

Servlets may be preloaded during WebLogic Server startup by including the < load-on-startup > element in the web.xml file for the Web application. You can also provide initialization parameters in this file using < init-param > elements. WebLogic Server will preload and call init() on the servlet during startup, passing the specified initialization parameters to the init() method in the ServletConfig object.

An existing servlet instance is destroyed when the application server shuts down or intends to reload the servlet class and create a new instance. The server calls the destroy() method on the servlet prior to removing the servlet instance and unloading the class. This allows the servlet to clean up any resources it may have opened during initialization or operation.

Servlets Allow Multiple Parallel Requests

Servlets are normally configured to allow multiple requests to be processed simultaneously by a single servlet instance. In other words, the servlet s methods must be thread-safe. You must take care to avoid using class- or instance-level variables unless access is made thread-safe through synchronization logic. Typically, all variables and objects required to process the request are created within the service() or do XXX () method itself, making them local to the specific thread and request being processed.

Best Practice  

Servlets that allow multiple parallel requests must be thread-safe. Do not share class- or instance-level variables unless synchronization logic provides thread safety.

Servlets may be configured to disallow multiple parallel requests by defining the servlet class as implementing the SingleThreadModel interface:

 ... public class TrivialSingleThreadServlet      extends HttpServlet  implements SingleThreadModel  {     public void init(ServletConfig config) throws ServletException     {         super.init(config);         System.out.println("Here!");     } ... 

This simple change informs the application server that it may not process multiple requests through the same servlet instance simultaneously. The application server can honor this restriction in multiple ways: It may block and queue up requests for processing through a single instance, or it may create multiple servlet instances as needed to fulfill parallel requests. The servlet specification does not dictate how application servers should avoid parallel processing in the same instance.

WebLogic Server satisfies the single-threaded requirement by creating a small pool of servlet instances (the default pool size is five) that are used to process multiple requests. In older versions of WebLogic Server, multiple parallel requests in excess of the pool size would block waiting for the first available servlet instance. This behavior changed in WebLogic Server 7.0. The server now creates, initializes, and discards a new instance of the servlet for each request rather than blocking an execute thread under these conditions. Set the pool size properly to avoid this extra servlet creation and initialization overhead.

You can configure the size of the pool at the Web application level using the single-threaded-servlet-pool-size element in the weblogic.xml deployment descriptor. If you choose to employ single-threaded servlets in high-volume applications, consider increasing the pool size to a level comparable to the number of execute threads in the server to eliminate the potential overhead required to create extra servlet instances on the fly to process requests.

Although instance variables are safe to use in single-threaded servlets, class-level static variables are shared between these instances, so access to this type of static data must be thread-safe even when using the SingleThreadModel technique. Deploying and executing this TrivialSingleThreadServlet example verifies this pooling behavior in WebLogic Server. The first servlet request causes WebLogic Server to create five instances of the servlet, as evidenced by five separate invocations of the init() method and the subsequent writing of five Here! messages in the log.

Best Practice  

In general, you should avoid using single-threaded servlets. If you find that you need to use servlets that implement the SingleThreadModel, use the single-threaded-servlet-pool-size element to set the pool size properly to avoid the overhead of creating and initializing extra servlet instances to handle peaks in the number of concurrent requests to the servlet.

Servlets May Access Request Data

The HttpServletRequest parameter passed in to the service() or do XXX () method contains a wealth of information available to the servlet during the processing of the request. Useful data in the HttpServletRequest is summarized in Table 1.1.

Table 1.1: Information Available in the HttpServletRequest

Type of Information

Access Methods

Parameters passed in the query string or through form input fields

getParameterNames() , getParameter() , getParameterValues() , getQueryString()

Server information

getServerName() , getServerPort()

Client characteristics

getRemoteAddr() , getRemoteHost() , getAuthType() , getRemoteUser()

Request information

getContentType() , getContentLength() , getProtocol() , getScheme() , getRequestURI()

HTTP headers

getHeaderNames() , getHeader() , getIntHeader() , getDateHeader()

Cookies sent by browser

getCookies()

Session information

getSession() , getRequestedSessionId() , isRequestedSessionIdValid() , ...

This is not an exhaustive list of the methods available on the HttpServletRequest class or its superclass, ServletRequest . Refer to the servlet javadocs at http://java.sun.com/products/servlet/2.3/javadoc/index.html or a good reference book on servlets for a complete list including parameter types, return types, and other details.

A useful servlet packaged with the WebLogic Server examples, SnoopServlet , illustrates the use of many of the methods available on the HttpServletRequest object. For example, this section of SnoopServlet illustrates how to retrieve and display the names and values of all parameters passed to the servlet:

 ... Enumeration e = req.getParameterNames(); if (e.hasMoreElements()) {     out.println(<h1>Servlet parameters (Single Value style):</h1>);     out.println(<pre>);     while (e.hasMoreElements()) {         String name = (String)e.nextElement();         out.println(+ name +  =  + req.getParameter(name));     }     out.println(</pre>); } ... 

This servlet can be very useful for debugging HTML forms during development. Specify SnoopServlet as the action for an HTML form to view all of the parameters, cookies, and headers sent by the browser during submission of the form. Nothing is more frustrating than spending time debugging a servlet only to find that the HTML form had an improperly named input item.

Best Practice  

Use the SnoopServlet as an action target during development and debugging to inspect request information and verify HTML forms.

Note that SnoopFilter , a servlet filter discussed later in this chapter, provides a superior mechanism for viewing request information for some or all pages in the Web application.

Servlets Use Session Tracking

A servlet is a request/response mechanism that treats each incoming request as an independent processing event with no relationship to past or future requests. In other words, the processing is stateless. The HTTP protocol is also a stateless protocol: Each request from the Web browser is independent of previous or subsequent requests. Linking current requests to previous requests from the same client requires a mechanism for preserving context or state information from request to request. There are a number of HTML-based techniques for preserving context or state information:

  • Cookies may be set in previous requests and passed back to the server on subsequent requests.

  • URL-rewriting may be used to encode small amounts of context information on every hyperlink on the generated page.

  • Hidden form fields containing context information may be included in forms.

These techniques all have limitations, and none provides the robust data types and flexibility needed to implement true state management. Fortunately, the session tracking capability defined in the J2EE servlet model provides an excellent solution.

Session tracking provides a flexible hash-table-like structure called an HttpSession that can be used to store any serializable Java object and make it available in subsequent requests. To identify the specific client making the request and look up its session information, session tracking uses a cookie or URL-encoded session ID passed to the server on subsequent requests. In WebLogic Server, this session ID has the name JSESSIONID by default and consists of a long hash identifying the client plus creation-time and cluster information. The format of the session ID is

 JSESSIONID=SESSION_ID!PRIMARY_JVMID_HASH!SECONDARY_JVM_HASH!CREATION_TIME 

WebLogic Server uses exclamation marks to separate portions of the session ID. The first portion is used by the session tracking implementation in WebLogic Server to look up the client s HttpSession object in the Web application context. Subsequent portions of the session ID are used to identify primary and secondary servers for this client in a WebLogic Server cluster and to track the creation time for this session. Chapter 11 will discuss WebLogic Server clustering in detail as part of the discussion of administration best practices.

Using session tracking in a servlet is as simple as calling the getSession() method to retrieve or create the HttpSession object for this client and then utilizing the HttpSession interface to get and set attributes in the session. For a good example, see the SessionServlet example provided in the WebLogic Server examples.

WebLogic Server supports several forms of session persistence, a mechanism for providing session failover. The two most commonly used forms are in-memory replication and JDBC persistence. When using these types of session persistence, be careful not to place very large objects in the HttpSession . WebLogic Server tracks changes to the session object through calls to the setAttribute() method. At the end of each request, the server will serialize each new or modified attribute, as determined by the arguments to any setAttribute() calls, and persist them accordingly .

Recognize that persisting a session attribute will result in WebLogic Server serializing the entire object graph, starting at the root object placed in the HttpSession . This can be a significant amount of data if the application stores large, coarse-grained objects in the session. Multiple fine-grained objects can provide superior performance, provided that your application code updates only a subset of the fine-grained objects (using setAttribute ) in most cases. We will talk more about in-memory session replication and clustering in Chapter 11.

Best Practice  

Use session tracking to maintain state and contextual information between servlet requests. When using session persistence, avoid placing large objects in the session if your application tends to update only a small portion of these objects for any particular request. Instead, use multiple fine-grained objects to reduce the cost of session persistence.

To summarize, servlets are a reliable pure-Java mechanism for processing HTTP requests. It can be tedious to generate the HTML response through the simple println() methods available on the response Writer object, however. As we will discuss in Chapter 2, servlets are better suited for processing incoming requests and interacting with business objects and services than for the generation of HTTP responses.

If servlets are a tedious way to create HTML, what is available in the J2EE specification for efficiently creating HTML responses? JavaServer Pages technology, the subject of the next section of this chapter, is specifically design to be a powerful tool for creating HTML.

Characteristics of JavaServer Pages

JavaServer Pages (JSP) technology was introduced in the J2EE platform to provide an alternative to servlets for the generation of server-side HTML content. Although a detailed discussion of JSP technology is beyond the scope of this book, some key concepts and characteristics are worth a brief review.

JSP Is a Scripting Technology

Recall that one of the important characteristics of servlets is their pure Java nature. Servlets are Java classes that are written, compiled, and debugged much like any Java class. JavaServer Pages, on the other hand, are a script-based technology similar to Microsoft s Active Server Pages (ASP) technology or Allaire s Cold Fusion scripting language. Like these scripting languages, special tags and script elements are added to a file containing HTML to produce a combination of static and dynamic content. In the case of JSP, these added elements are Java code or special JSP tags that interact with Java beans and other J2EE components in the application.

JSP Pages Are Converted to Servlets

The key to understanding JSP pages is to recognize that the JSP file itself is simply the input for a multistep process yielding a servlet. In the key processing step, the JSP page is parsed by the application server and converted to the equivalent pure- Java servlet code. All text that is not part of JSP tags and scripting elements is assumed to be part of the HTTP response. This text is placed in out.print() calls within the generated servlet request-processing method. All Java scripting elements and tags become additional Java code in the servlet. The generated servlet is then compiled, loaded, and used to process the HTTP request in a manner identical to a normal servlet.

Figure 1.1 depicts this process for a trivial sample JSP page with a small amount of scripted Java code embedded on the page. The sample.jsp page is converted to the equivalent pure-Java servlet code, compiled into a servlet class, and used to respond to the original and subsequent HTTP requests.

click to expand
Figure 1.1:  JSP page is converted to a servlet.

The parsing, conversion, compiling, and classloading steps required to accomplish this transformation are handled by the application server. You don t have to perform any of these steps ahead of time or register the resulting servlet ”all of this is done automatically by the server. Note that the processing and compiling can be done prior to deployment using utilities provided by WebLogic Server, a technique known as precompiling the JSP pages. We will discuss this technique in detail later in this chapter.

In WebLogic Server, the resulting servlet is a subclass of weblogic.servlet .jsp.JspBase by default. JspBase is a WebLogic-provided class that extends HttpServlet and forwards service() calls to a method called _ jspService() . You may also create a custom base class for JSP-generated servlets to replace the default JspBase class, a technique discussed at end of this chapter.

Many Tags and Scripting Elements Are Available

JSP technology provides a rich set of scripting elements and tags for creating dynamic content. Table 1.2 lists some of the important elements available.

Table 1.2:  JSP Syntax Elements

Element

Syntax

Description

Scriptlet

< % scriptlet code % >

Java code placed directly in _jspservice() method at this location.

Declaration

< %! declaration % >

Java code placed within the generated servlet class above the _jspservice() method definition. This usually defines class-level methods and variables.

Expression

< %= expression % >

Java expression evaluated at run time and placed in the HTML output.

page directive

< %@ page attribute = value ... % >

Controls many page-level attributes and behaviors. Important attributes include import , buffer , errorPage , and extends .

Include

< %@ include file = filename % >

Inserts the contents of the specific file in the JSP page and parses/compiles it.

Taglib

< %@ taglib uri= ... prefix= ... % >

Defines a tag library and sets the prefix for subsequent tags.

jsp:include

< jsp:include page= ... / >

Includes the response from a separate page in the output of this page.

jsp:forward

< jsp:forward page= ... / >

Abandons the current response and passes the request to a new page for processing.

jsp:useBean

< jsp:useBean id= ... scope= ... class= ... / >

Declares the existence of a bean with the given class, scope, and instance name.

Many more elements and tags are available. A detailed discussion of these elements is beyond the scope of this book. Consult one of the books listed at the beginning of this chapter for a complete list of JSP elements and tags, or browse Sun s JSP area at http://java.sun.com/products/jsp/ for more information.

All Servlet Capabilities Are Available

Because JSP pages are converted to servlets, all of the capabilities and techniques available in servlets are also available in JSP pages. The HttpServletRequest and HttpServletResponse parameters are available, along with a number of predefined variables available in the JSP page, as listed in Table 1.3.

Table 1.3:  JSP Implicit Objects

Object

Type

Description

request

javax.servlet.http.HttpServletRequest

Provides access to request information and attributes set at the request scope.

response

javax.servlet.http.HttpServletResponse

Reference to the response object being prepared for return to the client.

pageContext

javax.servlet.jsp.PageContext

Provides access to attributes set at the page scope.

session

javax.servlet.http.HttpSession

Session object for this client; provides access to attributes set at the session scope.

application

javax.servlet.ServletContext

Application context; provides access to attributes set at the application scope.

out

javax.servlet.jsp.JspWriter

PrintWriter object used to place text output in the HTTP response.

config

javax.servlet.ServletConfig

Reference to the servlet configuration object set during initialization; provides access to initialization parameters.

JSP scriptlet code may make use of all implicit objects because scriptlet code is placed in the generated _jspService() method after these objects are defined, as shown in this partial listing:

 ... public void _jspService(javax.servlet.http.HttpServletRequest request,                         javax.servlet.http.HttpServletResponse response)          throws java.io.IOException, javax.servlet.ServletException  {       // declare and set well-known variables:     javax.servlet.ServletConfig config = getServletConfig();     javax.servlet.ServletContext application =        config.getServletContext();     Object page = this;     javax.servlet.jsp.JspWriter out;     javax.servlet.jsp.PageContext pageContext =        javax.servlet.jsp.JspFactory.getDefaultFactory().getPageContext(this, request, response, null, true, 8192, true);          out = pageContext.getOut();          javax.servlet.http.HttpSession session = request.getSession(true);     ...  // scriptlet code and generated out.print() statements go here  ... } 

You should recognize that these implicit objects are available in scriptlet code but are not automatically available in methods defined using the < %! ... % > declaration scripting element or in methods in a custom base class used for the JSP page. It is common to pass the necessary implicit objects to these methods as parameters.

Session tracking is available by default in JSP pages, providing the session implicit object throughout the scriptlet code. If your application is not using session tracking, you should disable it to avoid unnecessary session persistence. Although there is no explicit way to disable session tracking for the entire Web application, servlets will not create sessions unless the servlet code calls the getSession() method. JSP pages may disable sessions using the page directive:

 <%@ page session=false %> 

Even if your JSP does nothing with the session information, WebLogic Server must persist the last access time for the session at the end of the request processing. It is best to explicitly disable session tracking in JSP pages that do not use it.

Best Practice  

Disable session tracking in JSP pages that do not require this feature to avoid unnecessary session persistence.

Like servlets, JSP pages are normally multithreaded and may process multiple requests simultaneously. The same thread-safety restrictions that apply to servlets also apply to JSP pages unless the JSP is configured to be single threaded. In a JSP page a special page directive is used to configure this attribute:

 <%@ page isThreadSafe=false %> 

If the isThreadSafe attribute is set to false , the resulting servlet will implement the SingleThreadModel interface, and WebLogic Server will create a pool of servlet instances and synchronize access to them in the same manner it uses for a pure-Java servlet that implements this interface.

Best Practice  

As with servlets, you should generally avoid declaring JSP pages to be single threaded. If you find yourself needing to do that, make sure that the pool size is large enough to avoid creating and initializing new instances on the fly to process concurrent requests.

JSP Response Is Buffered

As we said, servlets and JSP pages are request/response mechanisms: An HTTP request is made by the browser, and an HTML response is generated by the servlet or JSP page. In both cases, this response is normally buffered , or held in memory on the server temporarily, and sent back to the calling browser at the end of the processing.

By default, output created using the print() and println() methods on the implicit JspWriter object ( out ) are buffered, along with HTTP headers, cookies, and status codes set by the page. Buffering provides you with these important benefits:

  • Buffered content may be discarded completely and replaced with new content. The jsp:forward element relies on this capability to discard the current response and forward the HTTP request to a new page for processing. Note that the errorPage directive uses jsp:forward to send the processing to the error page if an error is caught in the JSP page, so buffering is also required for proper error-page handling.

  • Buffering allows the page to add or change HTTP headers, cookies, and status codes after the page has begun placing HTML content in the response. Without buffering, it would be impossible to add a cookie in the body of the JSP page or change the response to be a redirect (302) to a different page once print() or println() has been called because the headers and cookies have already been sent.

When the buffer fills, the response is committed, and the first chunk of information is sent to the browser. Once this commit occurs, the server will no longer honor jsp:forward , HTTP header changes (such as redirects), or additional cookies. The server will generate an IllegalStateException if any of these operations is attempted after the buffer fills and the response is committed.

The default size of the JSP output buffer is 8KB in WebLogic Server, which you can control using the page directive in each JSP page:

 <%@ page buffer=32kb %> 

Output buffering may also be turned off using this directive by specifying none for a size, but this practice is not recommended.

Output buffers should be set to at least 32KB in most applications to avoid filling the buffer and committing the response before the page is complete. The minor additional memory requirement (32KB times the number of threads) is a small price to pay for correct error-page handling and the ability to add cookies and response headers at any point in large pages.

Best Practice  

Always use output buffering in JSP pages. Increase the size of the buffer to at least 32KB to avoid redirect, cookie, jsp:forward , and error-page problems.

JSP Pages Have Unique Capabilities

Unique capabilities are available in JSP pages that are not present in servlets. Two important JSP-only capabilities are custom tags and jsp:useBean elements.

Custom tags provide a mechanism to interact with a custom-developed Java class that encapsulates business logic, presentation logic, or both. Custom tag elements are placed in the JSP page by the developer and then parsed and preprocessed by the application server during the conversion from JSP to servlet. The tag elements are converted by the server to the Java code required to interact with the tag class and perform the desired function. Later in this chapter we will discuss custom tags in more detail and present best practices for their use in WebLogic Server.

The jsp:useBean element provides a mechanism to declare and establish the existence of a bean instance for use in scriptlet code or in conjunction with jsp: getProperty and jsp:setProperty tags. The jsp:useBean syntax allows the developer to specify the class of the bean, the name of the reference to the bean, the type of the reference, and the scope in which the bean should be created. We will discuss the strengths and weaknesses of the jsp:useBean element later in this chapter during the discussion of best practices.

To summarize, JavaServer Pages technology is a scripting language used to create HTML responses. JSP pages are converted to pure-Java servlets by the application server during processing, and they can perform nearly any task a pure-Java servlet can perform. JSP pages also have unique directives, features, and customization capabilities unavailable to servlets.

Why not use JSP for everything and forget servlets completely? Although it is possible to do so, servlets often provide a better mechanism for implementing presentation-tier business logic. Chapter 2 will address this issue in detail and provide guidance for the proper use of each technology.




Mastering BEA WebLogic Server. Best Practices for Building and Deploying J2EE Applications
Mastering BEA WebLogic Server: Best Practices for Building and Deploying J2EE Applications
ISBN: 047128128X
EAN: 2147483647
Year: 2003
Pages: 125

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net