Oracle Application Server 10g Migrating from WebSphere 10g (9.0.4) Part Number B10426-01 |
|
This chapter discusses key servlet features and APIs, WebSphere support for servlet APIs and its extensions to standards, and OC4J support for servlet APIs. It also includes a step-by-step migration path for servlets deployed on WebSphere to Oracle Application Server OC4J container.
A servlet is an instance of Java class running in a web container and servlet engine. Servlets are used for generating dynamic web pages. Servlets receive and respond to requests from web clients, usually via the HTTP protocol.
Servlets have several advantages over traditional CGI programming:
The servlet API is specified in two java extension packages: javax.servlet
and javax.servlet.http
. Most servlets, however, extend one of the standard implementations of that interface, namely javax.servlet.GenericServlet
and javax.servlet.http.HttpServlet
. Of these, the classes and interfaces in javax.servlet
are protocol independent, while javax.servlet.http
contain classes specific to HTTP.
The servlet API provides support in four categories:
Table 3-1 identifies the servlet API classes according to the purpose they serve.
Servlets run on the web server platform as part of the same process as the web server itself. The web server is responsible for initializing, invoking, and destroying each servlet instance. A web server communicates with a servlet through a simple interface, javax.servlet.Servlet
.
This interface consists of three main methods
and two ancillary methods:
init()
Method
When a servlet is first loaded, its init()
method is invoked, and begins initial processing such as opening files or establishing connections to servers. If a servlet has been permanently installed in a server, it is loaded when the server starts.
Otherwise, the server activates a servlet when it receives the first client request for the services provided by the servlet. The init()
method is guaranteed to finish before any other calls are made to the servlet, such as a call to the service()
method. The init()
method is called only once; it is not called again unless the servlet is reloaded by the server.
The init()
method takes one argument, a reference to a ServletConfig
object, which provides initialization arguments for the servlet. This object has a method getServletContext()
that returns a ServletContext
object, which contains information about the servlet's environment.
service()
Method
The service()
method is the heart of the servlet. Each request from a client results in a single call to the servlet's service()
method. The service()
method reads the request and produces the response from its two parameters:
ServletRequest
object with data from the client. The data consists of name/value pairs of parameters and an InputStream
. Several methods are provided that return the client's parameter information. The InputStream
from the client can be obtained via the getInputStream()
method. This method returns a ServletInputStream
, which can be used to get additional data from the client. If you are interested in processing character-level data instead of byte-level data, you can get a BufferedReader
instead with getReader()
.
ServletResponse
represents the servlet's reply back to the client. When preparing a response, the method setContentType()
is called first to set the MIME type of the reply. Next, the method getOutputStream()
or getWriter()
can be used to obtain a ServletOutputStream
or PrintWriter
, respectively, to send data back to the client.
There are two ways for a client to send information to a servlet. The first is to send parameter values and the second is to send information via the InputStream
(or Reader
). Parameter values can be embedded into a URL. The service()
method's job is simple--it creates a response for each client request sent to it from the host server. However, note that there can be multiple service requests being processed simultaneously. If a service method requires any outside resources, such as files, databases, or some external data, resource access must be thread-safe.
destroy()
Method
The destroy()
method is called to allow the servlet to clean up any resources (such as open files or database connections) before the servlet is unloaded. If no clean-up operations are required, this can be an empty method.
The server waits to call the destroy()
method until either all service calls are complete, or a certain amount of time has passed. This means that the destroy()
method can be called while some longer-running service()
methods are still running. It is important that you write your destroy()
method to avoid closing any necessary resources until all service()
calls have completed.
HTTP is a stateless protocol, which means that every time a client requests a resource, the protocol opens a separate connection to the server, and the server doesn't preserve the context from one connection to another; each transaction is a isolated. However, most web applications aren't stateless. Robust Web applications need to interact with with users and remember the user the nature of a given user's requests, making data collected about the user in one request available to the next request from the same user. A classic example would be the shopping cart application, from internet commerce. The Servlet API provides techniques for identifying a session and associating data with it, even over multiple connections. These techniques include the following:
To eliminate the need for manually managing the session information within application code (regardless of the technique used), you use the HttpSession
class of the Java Servlet API. The HttpSession
interface allows servlets to:
Cookies are probably the most common approach for session tracking. Cookies store information about a session in a human-readable file on the client's machine. Subsequent sessions can access the cookie to extract information. The server associates a session ID from the cookie with the data from that session. This becomes more complicated when there are multiple cookies involved, when a decision must be made about when to expire the cookie, and when many unique session identifiers are needed. Also, a cookie has a maximum size of 4K, and no domain can have more than 20 cookies. Cookies pose some privacy concerns for users. Some people don't like the fact that a program can store and retrieve information from their local disk, and disable cookies or delete them altogether. Therefore, they are not dependable as a sole mechanism for session tracking.
The URL rewriting technique works by appending data to the end of each URL that identifies a session. The server associates the identifier with data it has stored about the session. The URL is constructed using an HTTP GET, and may include a query string containing pairs of parameters and values. For example:
http://www.server.com/getPreferences?uid=username&bgcolor=red&fgcolor=blue.
Hidden form fields are another way to store information about the session. The hidden data can be retrieved later by using the HTTPServletRequest object. When a form is submitted, the data is included in the GET or POST. A note of caution though: form fields can be used only on dynamically generated pages,so their use is limited. And there are security holes: people can view the HTML source to see the stored data.
HttpSession
object
No matter the technique(s) used to collect session data, it must be stored somewhere. The HttpSession
object can be used to store the session data from a servlet and associate it with a user.
The basic steps for using the HttpSession
object are:
A session persists for a certain time period, up to forever, depending on the value set in the servlet. A unique session ID is used to track multiple requests from the same client to the server. Persistence is valid within the context of the Web application, which may encompass multiple servlets. A servlet can access an object stored by another servlet; the object is distinguished by name and is considered bound to the session. These objects (called attributes when set and get methods are performed on them) are available to other servlets within the scope of a request, a session, or an application.
Servlets are used to maintain state between requests, which is cumbersome to implement in traditional CGI and many CGI alternatives. Only a single instance of the servlet is created, and each request simply results in a new thread calling the servlet's service
method (which calls doGet
or doPost
). So, shared data simply has to be placed in a regular instance variable (field) of the servlet. Thus,the servlet can access the appropriate ongoing calculation when the browser reloads the page and can keep a list of the N most recently requested results, returning them immediately if a new request specifies the same parameters as a recent one. Of course, the normal rules that require authors to synchronize multithreaded access to shared data still apply to servlets.
Servlets can also store persistent data in the ServletContext
object, available through the getServletContext
method. ServletContext
has setAttribute
and getAttribute
methods that enable storage of arbitrary data associated with specified keys. The difference between storing data in instance variables and storing it in the ServletContext
is that the ServletContext
is shared by all servlets in the servlet engine or in the Web application.
A Web application, as defined in the servlet specification, is a collection of servlets, JavaServer Pages (JSPs), Java utility classes and libraries, static documents such as HTML pages, images , client side applets, beans, and classes, and other Web resources that are set up in such a way as to be portably deployed across any servlet-enabled Web server. A Web applications, can be contained in entirety within a single archive file and deployed by placing the file into a specific directory.
Web application archive files have the extension .war
. WAR files are .jar
files (created using the jar
utility) saved with an alternate extension. The JAR format allows JAR files to be stored in compressed form and have their contents digitally signed. The .war
file extension was chosen over .jar
to distinguish them for certain operations. An example of a WAR file listing is shown below:
index.html howto.jsp feedback.jsp images/banner.gif images/jumping.gif WEB-INF/web.xml WEB-INF/lib/jspbean.jar WEB-INF/classes/MyServlet.class WEB-INF/classes/com/mycorp/frontend/CorpServlet.class WEB-INF/classes/com/mycorp/frontend/SupportClass.class
On install, a WAR file can be mapped to any URI prefix path on the server. The WAR file then handles all requests beginning with that prefix. For example, if the WAR file above were installed under the prefix /demo
, the server would use it to handle all requests beginning with /demo
. A request for /demo/index.html
would serve the index.html
file from the WAR file. A request for /demo/howto.jsp
or /demo/images/banner.gif
would also serve content from the WAR file.
WEB-INF
directory
The WEB-INF
directory is special. The files in it are not served directly to the client; instead, they contain Java classes and configuration information for the Web application. The directory behaves like a JAR file's META-INF
directory; it contains metainformation about the archive contents. The WEB-INF/classes
directory contains the class files for the Web application's servlets and supporting classes. WEB-INF/lib
contains classes stored in JAR files. For convenience, web server class loaders automatically look to WEB-INF/classes
and WEB-INF/lib
for their classes--no extra install steps are necessary.
The servlets under WEB-INF
in the example Web application listing can be invoked using URIs like /demo/servlet/MyServlet
and /demo/servlet/com.mycorp.frontend.CorpServlet
.
Note that every request for this application begins with /demo
, even requests for servlets.
The web.xml
file in the WEB-INF
directory defines descriptors for a Web Application. This file contains configuration information about the Web application in which it resides and is used to register your servlets, define servlet initialization parameters, register JSP tag libraries, define security constraints, and other Web Application parameters .
The Servlet API in the J2EE specification is continously evolving. In a span of two years Servlet API 2.0 , 2.1, 2.2 has been published; the most recent version as of this writing is Servlet API 2.3. The fundamental architecture of servlets has not changed much, so most of the API is still relevant. However, there are enhancements and some new functionality, and some APIs have been deprecated.
This section will cover the major difference between Servlet API 2.0 , 2.1 ,2.2 and 2.3 draft specification.
The Servlet 2.1 API highlights include:
A request dispatcher is a wrapper for resources that can process HTTP requests (such as servlets andJSPs) and files related to those resources (such as static HTML and GIFs). The servlet engine generatesa single request dispatcher for each servlet or JSP when it is instantiated. The request dispatcher receives client requests and dispatches the request to the resource.
In Servlet API 2.0, the servlet engine generated a single servlet context that was shared by all servlets. The Servlet API 2.1 provides a single servlet context per application, which facilitates partitioning applications. As explained in the description of the application programming model, applications on the same virtual host can access each other's servlet context.
The Servlet API 2.0 HttpSessionContext
interface grouped all of the sessions for a Web server into a single session context. Using the session context interface methods, a servlet could get a list of the session IDs for the session context and get the session associated with an ID. As a security safeguard, this interface has been deprecated in the Servlet API 2.1. The interface methods have been redefined to return null.
The Servlet API 2.2 specification changed the term 'servlet engine', replacing it with 'servlet container'. This change is indicative of the Java Servlet API is now a required API of the Java 2 Platform, Enterprise Edition (J2EE) specification and, throughout J2EE's terminology, container is preferred over engine. Servlet API 2.2 introduced the following new features:
The Servlet API 2.3 leaves the core of servlets relatively untouched. Additions and changes include:
HttpUtils
class has been deprecated
Filtering support is provided as a part of the Servlet 2.3 API. WebSphere Advanced Edition 3.5.3 achieves similar filtering functionality with a WebSphere-specific package. OC4J supports the Java servlet 2.3 filtering specification.
Filtering is a method of loading and invoking servlets in a web server. Both local and remote servlets can be part of a servlet chain (defined below). There are restrictions, however, on chaining the local internal servlets, and these restrictions are specific to the J2EE container used. For example, in WebSphere, if an internal servlet is used in a chain, it must be the first servlet in the chain. Internal servlets include: file
servlet, pageCompile
servlet, ssInclude
servlet, and template
servlet.
For some requests, a chain of ordered servlets can be invoked rather than just one servlet. The input from the browser is sent to the first servlet in the chain and the output from the last servlet in the chain is the response sent back to the browser. Each servlet in the chain receives inputs from, and transmits outputs to, the servlet before and after it, respectively. A chain of servlets can be triggered for an incoming request by using:
WebSphere versions 3.5.2 and 3.5.3 maintain compatibility with existing applications while simultaneously supporting the Java Servlet API 2.2 specification. But this support is partial, and you can choose only one. To ensure compatibility, a new option was added to servlet container properties in the Administrative console. This new option, the Select Servlet Engine Mode, is located on the Servlet Engine Properties view. The Select Servlet Engine Mode option toggles between the following two different 'runtime' modes:
This mode maintains behavior with existing WebSphere Application Server v3.5 and v3.5.1 applications at the expense of full compliance with the Java Servlet API 2.2 specification. In compatibility mode, the servlet engine is Servlet 2.2 specification level compliant, except for the method and behavior changes noted below. This capability is provided to allow existing WebSphere Advanced Edition v3.5 and v3.5.1 applications to successfully execute until they are migrated to fully compliant Servlet 2.2 level applications.
This mode maintains compliance with the Java Servlet API 2.2 specification at the expense of compatibility with existing WebSphere Application Server v3.5 and v3.5.1 applications.
The default mode is the Compatibility Mode. You select the desired mode using the Administrative Console, Servlet Engine General tab.
WebSphere Advanced Edition 3.5.3 has partial support for the Servlet 2.2 API. The supported API features are:
addHeader()
, getHeaders(name)
APIs)
getLocale()
, getLocales()
)
getServletName()
The following Servlet 2.2 API features are not supported:
The WebSphere Application Server includes its own packages that extends and adds to the Java Servlet API. The extensions and additions are provided to manage session state, create personalized Web pages, generate better servlet error reports, and access databases.
The Application Server API packages and classes are:
com.ibm.servlet.personalization.sessiontracking
Records the referral page that led a visitor to a web site, tracks the visitor's position within the site, and associates user identification with the session. IBM has also added session clustering support to the API.
com.ibm.websphere.servlet.session.IBMSession
interface
Extends HttpSession
for session support and increases Web administrators' control in a session cluster environment.
com.ibm.servlet.personalization.userprofile
package
Provides an interface for maintaining detailed information about web visitors and incorporate it in your applications, so that you can provide a personalized user experience. This information stored it in a database.
com.ibm.websphere.userprofile
package
User profile enhancements.
com.ibm.websphere.servlet.error.ServletErrorReport
class
Enables the application to provide more detailed and tailored messages to the client when errors occur.
com.ibm.websphere.servlet.event
package
Provides listener interfaces for notifications of application lifecycle events, servlet lifecycle events, and servlet errors. The package also includes an interface for registering listeners.
com.ibm.websphere.servlet.filter
package
Provides classes that support servlet chaining. The package includes the ChainerServlet
, the ServletChain
object, and the ChainResponse
object.
com.ibm.websphere.servlet.request
package
Provides an abstract class, HttpServletRequestProxy
, for overloading the servlet engine's HttpServletRequest
object. The overloaded request object is forwarded to another servlet for processing. The package also includes the ServletInputStreamAdapter
class for converting an InputStream
into a ServletInputStream
and proxying all method calls to the underlying InputStream
.
com.ibm.websphere.servlet.response
package
Provides an abstract class, HttpServletResponseProxy
, for overloading the servlet engine's HttpServletResponse
object. The overloaded response object is forwarded to another servlet for processing. The package includes the ServletOutputStreamAdapter
class for converting an OutputStream
into a ServletOutputStream
and proxying all method calls to the underlying OutputStream
.
The package also includes the StoredResponse
object that is useful for caching a servlet response that contains data that is not expected to change for a period of time, for example, a weather forecast.
Oracle Application Server OC4J is a fully compliant implementation of the Java Servlets 2.2 and 2.3 specifications. As such, standard Java Servlets 2.2 code will work correctly. WebSphere 3.5.3, on the other hand, has partial support for the Java Servlets 2.2 specification as described above. In particular, the security support remains at the Servlet 2.1 level, and there is no support for J2EE references that would normally be defined in the web.xml
file associated with the Web application. There is also no direct support for J2EE Web Abpplications.
Because of these differences in API support and WebSphere extensions, an application may require code level changes before it can be migrated if it uses extensions or deprecated method calls. Since WebSphere does not support J2EE deployment descriptors, existing applications must be packaged into the J2EE Web Application structure before deployment on Oracle Application Server OC4J.
We migrated example servlets provided with WebSphere Advanced Edition 3.5.3. Some of these examples were not migrated because they used WebSphere-specific extensions. For example, we did not migrate AbstractLoginServlet
because it uses a single sign-on package specific to WebSphere.
We migrated these servlets (located in in WebSphereInstallHome/Servlets
):
In addition to these, we migrated packaged Web Applications that use WebSphere- specific deployment descriptors.
These examples were migrated without code changes. All that was required was to place these servlets in
<ORACLE_HOME>
/j2ee/home/default-web-app/WEB-INF/classes
in UNIX
or
<ORACLE_HOME>\j2ee\home\default-web-app\WEB-INF\classes
in NT.
The OC4J servlet container loads these servlets automatically. You can invoke these servlets from a browser using an URL similar to http://
<hostname>:7777/j2ee/servlet/HelloWorldServlet
.
WebSphere provides another way of deploying standalone servlets (that is, servlets that require initialization parameters and configuration information). These servlets are deployed in WebSphere using a deployment descriptor whose name is the name of the servlet and ends with .servlet
. This WebSphere-specific deployment descriptor must be migrated to the J2EE Web application deployment descriptor before it can be deployed in OC4J.
<servlet> <name>snoop</name> <description>snoop servlet</description> <code>SnoopServlet</code> <servlet-path>/servlet/snoop/*</servlet-path> <servlet-path>/servlet/snoop2/*</servlet-path> <init-parameter> <name>param1</name> <value>test-value1</value> </init-parameter> <autostart>false</autostart> </servlet>
.servlet
file: SnoopServlet.servlet
The Snoop Servlet can be migrated by placing its .class
file in <ORACLE_HOME>
/j2ee/home/default-web-app/WEB-INF/classes
in UNIX or <ORACLE_HOME>\j2ee\home\default-web-app\WEB-INF\classes
in NT
and editing web.xml
located in the following directory:
UNIX:<ORACLE_HOME>
/j2ee/home/default-web-app/WEB-INF
NT:<ORACLE_HOME>
\j2ee\home\default-web-app\WEB-INF
The migrated SnoopServlet deployment descriptor looks like:
<web-app> <servlet> <servlet-name>snoop</servlet-name> <description>snoop servlet</description> <servlet-class>SnoopServlet</servlet-class> <servlet-path>/servlet/snoop/*</servlet-path> <servlet-path>/servlet/snoop2/*?/servlet-path? <init-param> <param-name>param1</param-name> <param-value>test-value1</param-value> </init-param> <autostart>false</autostart> </servlet> </web-app>
Clustering and load balancing are two key features of an enterprise application server. These features make the application server available, fault tolerant, and scalable. The load balancer replicates state of an individual node to the cluster of instances so that if a node fails, the state information is preserved elsewhere. The cluster configuration provided by OC4J accomplishes the following:
If an application cannot make full use of a machine's resources, OC4J can help make more efficient useof the processing power.
OC4J can dramatically increase the number of requests an application can serve concurrently.
OC4J builds redundancy into your configuration. If one instance fails, others can continue to process requests.
WebSphere and Oracle Application Server OC4J both provide clustering and load balancing session failover. OC4J also supports HTTP tunneling of RMI requests and responses without clustering. If you have a cluster-aware application running on WebSphere, it can be migrated to an OC4J instance (a set of OC4J processes, equivalent to a cluster).
The OC4J configuration incorporates the concept of islands. An island is a set of OC4J processes that have uniform application configuration and replicated application state. An island is a subset of processes within an OC4J instance.
The following steps explain how to configure an OC4J island:
orion-web.xml
deployment descriptor for the web application, located at the following directory:
UNIX:<ORACLE_HOME>
/j2ee/home/application-deployments/
application-name/web-app-name/
NT:<ORACLE_HOME>
\j2ee\home\application-deployments\
application-name\web-app-name\
orion-web.xml
of the global web application located at the following directory:
UNIX:<ORACLE_HOME>
/j2ee/home/config/
global-web-application.xml
NT:<ORACLE_HOME>
\j2ee\home\config\
global-web-application.xml
Add the following to the main body of the <orion-web-app>
tag:
<cluster-config/>
The HTTPSession
data will now be replicated (as long as it is serializable, or an EJB reference). Note, however, that if the EJBs are located on a server that goes down, the references might become invalid. The ServletContext
data is also replicated.
Islands are connected to a certain site rather than to a web-application. To configure an island:
web-site.xml
file for the website your web application is deployed on (for example, default-web-site.xml
if you are clustering the default web-site). Add the following to the <web-site>
tag:
cluster-island="1"
If your cluster has more than one island, you will specify different island values for the servers that belong to different islands. State is shared only within an island.
host="<hostname/ip address>"
attribute in the <web-site>
tag.
web-site.xml
for your web site, you also specify where the load balancer for the site is located.
/WEB-INF/web.xml
or NT equivalent of your application, put in the tag
</distributable>
This tag indicates that the application is distributable (a feature of the J2EE 1.2 specification).
To test the state replication, you can try accessing the servlet in the following directory:
UNIX:<ORACLE_HOME>
/j2ee/home/servlet/SessionServlet
NT:<ORACLE_HOME>
\j2ee\home\servlet\SessionServlet
Make the request once, and check which server becomes the primary server for the session. Stop that server and make the request again. The desired result is that the request is part of the same session as before but on a different node. And, the counter is updated correctly.
For all of the islands, there is a single load balancer OC4J instance that dispatches requests to the application clones.
dontuseIP
" switch, a powerful feature of OC4J islands.
-dontUseKeepalives
as command line option or use-keepalives="false"
in load-balancer.xml
|
![]() Copyright © 2003 Oracle Corporation. All Rights Reserved. |
|