Oracle® Application Server Migrating from WebSphere 10g Release 3 (10.1.3.1.0) Part Number B16025-02 |
|
|
View PDF |
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 a 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:
Each servlet does not run in a separate process. This removes the overhead of creating a new process for each request.
A servlet stays in memory between requests. A CGI program (and probably also an extensive runtime system or interpreter) needs to be loaded and started for each CGI request.
There is only a single instance which answers all requests concurrently. This saves memory and allows a servlet to easily manage persistent data.
A servlet can be run by a servlet engine in a restrictive sandbox (similar to how an applet runs in a web browser's sandbox), which allows for secure use of servlets.
Servlets are scalable, providing support for a multi-application server configuration. Servlets also enable data caching, database access, and data sharing with other servlets, JSP files and (in some environments) Enterprise JavaBeans.
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:
Servlet life cycle management
Access to servlet context
Utility classes
HTTP-specific support classes
identifies the servlet API classes according to the purpose they serve.
Purpose | Class or Interface |
---|---|
Servlet implementation |
|
Servlet configuration |
|
Servlet exceptions |
|
Request/response |
|
Session tracking |
|
Servlet context |
|
Servlet collaboration |
|
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
init()
service()
destroy()
and two ancillary methods:
getServletConfig()
getServletInfo()
init()
MethodWhen 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()
MethodThe 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:
A 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()
.
A 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()
MethodThe 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 isolated. However, most web applications aren't stateless. Robust Web applications need to interact with with the user, remember the nature of the user's requests, make 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:
Cookies
URL rewriting
Hidden form fields
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:
View and manage information about a session
Preserve information across multiple user connections, to include multiple page requests as well as connections
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 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
objectNo 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:
Obtain a session object
Read or write to it
Terminate the session by expiring it, or allowing it to expire on its own
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 application 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
directoryThe 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 meta-information 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 covers the major differences between Servlet API 2.0 , 2.1 ,2.2 and 2.3 draft specification.
The Servlet 2.1 API highlights include:
A request dispatcher wrapper for each resource (servlet)
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.
A servlet context for each application
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.
Deprecated HTTP session 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:
Web Applications (as discussed above)
References to external data sources, such as JNDI. Enables adding resources into the JNDI lookup table, such as database connections. Allows the resources to be located by servlets using a simple name lookup.
Parameter information for the application (initiallization parameters for the application).
Registered servlet names. Provides a place to register servlets and give them names. Previously, each server had a different process for registering servlets, making deployment difficult.
Servlet initialization parameters. Enables passing parameters to servlets parameters at initialization time. This is a new, standard way to accomplish what used to be a server dependent process.
Servlet load order. Specifies which servlets are preloaded, and in what order.
Security constraints. Dictate which pages must be protected, and by what mechanism. Include built-in form-based authentication.
The Servlet API 2.3 leaves the core of servlets relatively untouched. Additions and changes include:
JDK 1.2 or later is required
A filter mechanism has been created
Application lifecycle events have been added
Additional internationalization support has been added
The technique to express inter-JAR dependencies has been formalized
Rules for class loading have been clarified
Error and security attributes have been added
The HttpUtils class has been deprecated
Several DTD behaviors have been expanded and clarified
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:
Servlet aliasing to indicate a chain of servlets for a request
MIME types to trigger the next servlet in the chain
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:
Response Buffering
Multiple Error page support
Welcome File Lists
New request mapping logic
Session Timeout per web application
Mime mapping table per web application
Request Dispatchers by name
Request Dispatchers by relative path
Duplicate Header support (addHeader()
, getHeaders(name)
APIs)
Initialization parameters on a web application
Internationalization improvements (getLocale()
, getLocales()
)
New APIs 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 Applications.
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
):
Custom Login Servlet
HelloWorldServlet
SessionServlet
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.
Example 3-1 SnoopServlet.servlet Deployment Descriptor
<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:
Maximizes use of resources
If an application cannot make full use of a machine's resources, OC4J can help make more efficient useof the processing power.
Maximize throughput
OC4J can dramatically increase the number of requests an application can serve concurrently.
Minimize risks of single points of failure
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.
Note:
The instructions in this section show you how to configure a island manually. This can be done in a development environment where OC4J is running in standalone mode. If you are configuring an island in an OracleAS Cluster, use the Oracle Enterprise Manager 10g Application Server Control Console web pages or the dcmctl command line utility. Information on using these can be found in Oracle Application Server Administrator's Guide and Oracle Application Server Containers for J2EE User's GuideThe following steps explain how to configure an OC4J island:
Install your web application on all of the nodes in your cluster.
First, make sure that the nodes you are using in your cluster have the same web application installed. If you do not want to install the application in two places, you can place it on a shared drive that both servers access.
Start all your nodes and check that the web-applications are working correctly on all of them.
Set up your web-application to replicate its state to the cluster.
Edit the 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\
If you want to add clustering for all web applications in the site, edit the 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/>
Optional: Specify the multicast host and IP address on which to transmit and receive cluster data.
Optional: Specify the port on which to transmit and receive cluster data.
Specify the ID (number) of the node to identify itself within the cluster. The default is localhost.
Optional: Repeat steps 4, 5 and 6 for all the nodes in your cluster.
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.
Note:
It is important to understand that load balancing, in this case, is implemented for the web-component, not the EJB (EJBs have a different way of load balancing using client stubs). When using multiple islands, you may want to use different multicast IP addresses, to enable smart routing of multicast packets in your network, and just send traffic on certain IP addresses to certain servers.Configure your islands.
Islands are connected to a certain site rather than to a web-application. To configure an island:
Edit the 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.
Specify the host the Web site is serving using the host="<hostname/ip address>"
attribute in the <web-site>
tag.
Tell the servers about the load balancer. In the same file, the web-site.xml
for your web site, you also specify where the load balancer for the site is located.
In the main body of the <website>
tag, add:
<frontend host="balancer_hostname" port="balancer_port" />
where balancer_hostname
and balancer_port
are the hostname and port of the server that will be running the load balancer.
In the /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).
Access the load balancer's host and port with a browser. You will notice how the request is sent to a server. If you request the same page again from the same client, your request will probably be sent to the same server again, but if you request the same page from different clients, you will see that the client requests get balanced.
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.
If a new request is made from an IP address that has not connected to the site before, and has no session associated with it, it is sent to a random OC4J instance. If more than one island in the cluster is capable of serving the same site, an island is chosen at random. Thereafter, a random node is picked within the selected island.
All state replication occurs within the island of this selected node. If a request is made from an IP address that has connected to to the website before, the request will be sent to the same server as the previous request (unless the configuration specifies that requests not be routed based on IP address).
By default, load balancing is based on client, not on request. In other words, statistically speaking, default load balancing is expected to send off an equal number of clients to each node in the island. Note that an equal number of clients to nodes in the island does not equate to an equal number of requests to the server, since each client makes a different number of requests.
To make load balancing request based, you can use the "dontuseIP
" switch, a powerful feature of OC4J islands.
If a request is made within a keep-alive socket, the request will get sent to the same server as the previous request, unless you have specified that keep-alives should not be used (-dontUseKeepalives
as command line option or use-keepalives="false"
in load-balancer.xml
.
If a request is made from a user in a session, the request is sent to the primary server for that session. If the primary server for the session does not respond, the request will be sent to another server in the same island. Since the state has been replicated, the other server has the same user state.