BEA WebLogic Server 7.0: Working with Servlets
In yesterday's session you learned important concepts and technologies that form part of J2EE. You started the day with a brief introduction to J2EE and then moved on to understand the concepts of each of the J2EE technologies, such as Java servlets, JavaServer Pages, JDBC, JNDI, Enterprise JavaBeans, and Java Message Service API. In the final part of yesterday's session, you learned the problem statement of the Airline Ticket Booking System MVCapplication case study and then went on to design the class diagram and ER diagram for the application.
Before starting today's session, we recommend that you read Appendix B, which details the steps required to install BEA WebLogic Server 7.0, as provided in the CD-ROM. This will prepare the ground for the sample applications you will build during the next three weeks.
The next two days will cover the first server-side Java technology supported by WebLogic, the Java Servlet API 2.3 specification. You will study Java servlet concepts, the Java Servlet API, and different techniques for session handling; finally, you will write a sample Java servlet and deploy it in the WebLogic Server. In addition to the basics of Java servlets, in tomorrow's session, you will be studying the advanced concepts of Java servlets such as filters and listeners. At the end of tomorrow's session, you will be building the first element of the Airline Ticket Booking System MVC application case study, the Controller servlet.
Introduction to Servlets
A Java servlet is a server-side Java application to generate dynamic content for a Web application. Servlets are used to extend the server-side functionality of a Web server by enabling writing of powerful server-side applications. Since the Servlet API is a part of the J2EE framework, servlets are a Java extension to Web servers.
Servlets are Java components and, hence, platform-independent Java classes that are dynamically loaded by Java-enabled Web servers and application servers.
On its own, a Web server serves only static pages. This limits the usefulness of Web servers for enhancing the user experience via a browser. Consider what would happen if your favorite online shopping Web site were a set of static HTML pages. If the marketing department chose to offer a special price for a product, then their Web site administrator would have to edit the product file before you could see the price. Now, consider a scenario where the price change would have applied to a hundred products. It would be a nightmare for the Web site administrator!
To avoid these issues and keep the content of Web applications up to date, server-side Web applications are increasingly being introduced and deployed.
Servlets and CGI: A Comparison
Since dynamic content is generated by a server-side program executed by the Web server as a separate process, a consistent mechanism of interprocess communication between the Web server and the server-side program has had to be defined. This consistent interprocess communication mechanism is essentially a set of predefined environment variables that a Web server populates and that a server-side program, called a CGI program, expects. A Web server sets the values to these environment variables, which are then read by the separately spawned CGI program as input. The CGI program processes this input and returns the generated dynamic content to the Web server to be forwarded to the user's browser. CGI programs are primarily Unix shell scripts or programs written in the Perl language.
Even though CGI programs are the simplest ways to develop server-side Web applications, they have significant drawbacks. One of the major problems is the overhead for the Web server for executing the CGI programs for each browser request. The execution of a CGI program by the Web server for each browser request is essentially a new process that is spawned. This spawning of new processes per browser request adds a significant overhead to the Web server and the operating system in which the Web server is running. For a Web site with a lot of traffic, the Web server will end up giving a poor response because of this overhead. Moreover, there is a limited mechanism of communication between the CGI program and the Web server.
Java servlets address the problems associated with CGI. A servlet container provides the environment to execute Java servlets. A Web server forwards a request to execute a servlet to the servlet container. The servlet container then appropriately loads a servlet (if it is not loaded) and dispatches the request to the appropriate servlet running within the servlet container. Servlet containers that interact with Web servers are of three distinct types: in-process, out-of-process, and standalone. An in-process servlet container runs as a part of the overall Web server process. No separate process is launched to run the servlet container. WebLogic Server is a good example of an in-process servlet container. An out-of-process servlet container runs as a separate process from the Web server process. Such a servlet container is normally a third-party plug-in for Web servers. An example of this type is the JRun servlet engine. Interprocess communication between the Web server process and the servlet container process occurs using sockets. The third type of servlet container is a standalone servlet container. In this type, the servlet container is an all-inclusive application that contains the Web server within itself. Hence, no separate Web server is needed in this case. An example of this is the Tomcat servlet container. The important point to note here is that irrespective of the type of the servlet container, a servlet is not executed as a separate process but runs as a separate "thread" within the process boundaries of the servlet container. Hence, the new process overhead encountered in CGI programs is avoided.
The Java Servlet API is an extension to the standard Java packages and marks the first move of Java from the standard application domain to the server side.
NOTE
Proprietary extensions to the popular Web servers such as Netscape Web Server and the Microsoft Internet Information Server (IIS) have been defined to enable integration of server-side Web applications with the respective Web server. These extensions are NSAPI and ISAPI for the Netscape and Microsoft Web servers, respectively. The problem with these extensions is that they are proprietary, thus inhibiting developers from writing Web applications compatible with both the servers.
The Java Servlet API, on the other hand, relies on the platform-independent nature of Java. Since Java servlet engines are available for both of these Web servers, as well as the Open Source Web servers (such as Apache), this extends the platform independence of Java to server independence.
WebLogic's Support for HTTP Servlets
Now that you have an idea of what Java servlets are all about, you can take a look at the support for Java servlets provided by WebLogic Server.
Figure 3.1 WebLogic Server and its components.
From Figure 3.1 you can see that WebLogic Server contains the servlet engine to support the execution and deployment of servlets. The servlet engine in WebLogic Server version 7.0 supports the Java Servlet API version 2.3 specification. Part of this support includes support of the following important features:
FiltersFilters are intermediate preprocessors of a servlet request and response. A filter is a Java class registered with the WebLogic Server as a "filter" for URLs or servlets. On receiving a request for the registered URLs or servlets, the server intercepts the request or response and forwards it to the filter class. The filter class preprocesses the request or response contents and passes this on to the servlet.
Listeners and eventsListeners are modeled on the Java AWT event listener model. Listeners are special classes registered with the WebLogic Server that are invoked on every life-cycle stage of the servlet being monitored. For example, a listener listening for the initialization event of a servlet can perform logging of the initialization stage of the servlet.
Apart from these features, the Servlet 2.3 specification has also simplified and standardized the deployment process, allowing the registering of files to be deployed in a manifest file while creating the deployment .war file.
Life Cycle of Servlets
Since servlets are special Java programs executed by the Java-enabled Web server, there is a life cycle associated with servlets. As you can see in Figure 3.2, there are three stages in the life cycle of a servlet: initialization, managing request/response, and termination.
Figure 3.2 Life cycle of a servlet.
Initialization
The servlet is initialized by the WebLogic Server when the WebLogic Server is started. During initialization, any parameters required for the servlet initialization are passed to the servlet. Initialization in servlets can be performed in a declarative or programmatic fashion:
Declarative initializationIn declarative initialization, the initialization parameters and their values for a servlet are defined in the deployment descriptor file web.xml. The servlet can access these initialization parameters by calling the getInitParameter(String paramName) method of the GenericServlet base class.
Programmatic initializationIn programmatic initialization, the initialization code for the servlet is defined in the init() method. The WebLogic Server executes the init() method only once during initialization.
TIP
If you need to set any initialization parameters for your servlet, for example, opening a database connection for use in the servlet, do this in the init() method. Also, any initialization parameters or global properties for the servlet can be defined in the deployment descriptor file for the servlet (web.xml).
Manage Request and Response
Any requests received by the Web server are forwarded to the servlet to handle. The servlet contains a service() method to manage the request, process it, and send back the response. You will write your server-side application code in this method. The service() method contains a request object and response object as parameters. These are used by the servlet to process the request and send the response. The Web server packages the request data in the request object and uses the response object to send the response to the client application. The service() method is used throughout the life cycle of the servlet.
Termination
At the end of the life cycle of the servlet, the server shuts down the servlet and frees up resources. You as a developer can use the destroy() method to do any cleanup before the servlet is removed from the WebLogic Server's memory.
TIP
If you need to free up any resources, for example, closing a database connection (or any other open file such as a trace or log file) that has been used in the servlet, do this in the destroy() method.
Multithreaded and Single-Threaded Models of Servlets
Java is one of the few languages that support multithreading across different operating systems as long as the underlying operating system supports multithreading. Multithreaded support in the Java language means that you can develop pieces of code that can be executed concurrently by the Java interpreter (Java Virtual Machine, or JVM) as separate "threads" of execution within a single process. One example of writing a program with explicit separate threads of execution is using the java.lang.Thread class in the standard edition Java Development Kit (JDK). The enterprise edition of Java takes this support for multithreading further and incorporates the same multithreaded behavior in all the J2EE technologies. WebLogic Server 7 provides this support for multithreaded behavior in servlets.
What this implies is that when a Java servlet is loaded by the WebLogic Server's servlet engine, the Java servlet can potentially service concurrent user requests. The servlet container in WebLogic Server accomplishes this by creating and executing copies of a method of the servlet in separate threads. The implication for a developer is that any variables that have scope of the servlet class, that is, instance variables of the servlet, can be potentially modified by any of the different threads in which the copies of a method execute. Hence, you must be careful while designing the scope of variables for a servlet. This behavior of the servlet is called the multithreaded model and is the default behavior for all servlets.
If there are class variables that need to be kept safe in a concurrent-processing scenario, the Servlet API defines a thread-safe model called the single-threaded model. When a servlet is used in a single-threaded model, the WebLogic Server creates multiple instances of the servlet for each new user request. Once a servlet is associated with a browser, the WebLogic Server maintains this association and reuses the same servlet to process the request.
In order to make a servlet work in a single-threaded model, the servlet must implement the SingleThreadModel interface, as follows:
public class MyTestSingleThreadedServlet extends HttpServlet implements SingleThreadModel { ... }
There are no methods in the SingleThreadModel interface for you to implement. Once the servlet is declared to implement the SingleThreadModel interface, the servlet container in the WebLogic Server guarantees that the service() method of the servlet is not executed concurrently by two separate threads. The servlet container ensures that concurrency is maintained by either synchronizing access to the servlet's instance or by creating a separate instance of the servlet for each new user request.
TIP
WebLogic Server provides support for defining a pool of the instances for the servlet. This pool is initialized when the servlet is initialized for the first time by the server. If the pool size is less than the average number of concurrent requests received for the servlet, the WebLogic Server increases the pool count. This setting of the pool size can be done by setting the value for the SingleThreadedServletPoolSize parameter in the WebLogic Server using the server administration console.
Flowchart for Developing Servlets
You will be following the steps listed in the flowchart in Figure 3.3 for developing your sample servlets throughout Day 3 and Day 4, "Advanced Servlet Techniques."
Figure 3.3 Flowchart for developing servlets.
In step 1, you define the requirements for your sample application. This is essentially the problem statement for developing the servlet.
In step 2, you design the static and dynamic behavior of the servlet. The static design consists of the class diagram and the package diagram for the servlet. The dynamic behavior is modeled by the sequence diagram.
In step 3, you set up the deployment environment for the servlet. Since servlets are Web applications, they are deployed in the applications directory as a separate Web application. The actual components of the Web application, including the classes, static HTML files, images, and so on, are kept in the WEB-INF directory. Apart from this, you need to have the environment consisting of the PATH and CLASSPATH variables set up in the MS-DOS prompt, where you perform the next step.
In step 4, you compile the servlet and the support classes using the javac compiler. This step assumes that the relevant CLASSPATH is correctly set.
In step 5, you create the Web archive file, which contains all the components of this servlet application, including the servlet classes, static HTML pages, and images. The Web archive file is essentially a Java archive file renamed with the .war extension.
The final stage of deployment for the servlet application is copying this Web archive .war file in the target deployment directory, which is the applications directory in your WebLogic instance domain.