Using WebLogic HTTP Servlets
Overview of HTTP Servlet Support in Weblogic Server
How WebLogic Server Implements Servlets
WebLogic HTTP Servlet API Reference
Steps to Write a Basic HTTP servlet
The Complete HelloWorldServlet Example
Initializing a Servlet at Server Startup
Using Initialization Parameters
Other Methods of HttpServletRequest
Example: Retrieving Input by Using Query Parameters
Using Session Tracking From a Servlet
Tracking a Session with the HttpSession Object
Detecting the Start of a Session
Setting and Getting Session Name/Value Attributes
ClassCastException and HTTP Sessions
Logging Out and Ending a Session
URL rewriting and Wireless Access Protocol (WAP)
Scenarios To Avoid When Using Sessions
Use Serializable Attribute Values
Configuring Session Persistence
Setting Cookies in an HTTP servlet
Retrieving Cookies in an HTTP Servlet
Using Cookies that Will Be Transmitted by Both HTTP and HTTPS
Your Application Security and Cookies
Using WebLogic Services from an HTTP Servlet
Accessing Databases-Using Connection Pools in a Servlet
Setting up the Registration for a Connection Pool
Using a Connection Pool in a Servlet
Threading Issues in HTTP Servlets
Passing the Request to Another HTTP Servlet
Administration and Configuration
Setting up ACLs for Servlets in the WebLogic Realm
Setting ACLs for Groups of Servlets
Using the ServletServlet -- a Developer's Shortcut
Disadvantages of Using the ServletServlet
Tips for Using the Servlet Classpath
Overview
In generic terms, a servlet is any class that can be invoked and executed on a server, most likely on behalf of a client. Unlike applets, which do their work on the client, servlets do their work on the server and are often used to replace Common Gateway Interface (CGI) or other server-side programming models. Another way of phrasing what servlets do is "server-side Java." Since servlets are written in Java and are part of the J2EE specification, they have access to all the functionality and cross-platform portability of the Java programming language.
So, what is an HTTP servlet? An HTTP servlet is a Java class that handles an HTTP request and delivers an HTTP response. HTTP servlets live in an HTTP server and must extend the javax.servlet.http.HttpServlet class, so that they can run in a generic servlet engine framework.
WebLogic Server can be configured as a fully functional HTTP Server that delivers any arbitrary MIME type to HTTP clients. For more information on setting this up, see the Administrators Guide, Setting up WebLogic as an HTTP Server. To provide more complex Web pages that accept input from the client and provide dynamic responses, you must write your own custom HTTP servlets. You can develop sophisticated Web sites, such as shopping-carts or online booking forms by combining WebLogic Server's built-in services such as EJB, JDBC, and JSP with HTTP servlets.
When you write HTTP servlets and register them with WebLogic Server, the servlets operate within the security framework of WebLogic Server, and are used to service HTTP requests from clients. The work performed by HTTP servlets can be compared to that of CGI scripts, but HTTP servlets are more effective for the following reasons:
WebLogic Server implements the Java HTTP servlet 2.2 API, available at: http://java.sun.com/products/servlet/2.2/index.html. message URL
Servlets and JSP
This document details how to use HTTP servlets to perform server-side Java tasks in response to HTTP requests. For Web services that require more sophisticated presentation, you should use Java Server Pages. With JSP you write the static HTML content directly, and embed Java code into the HTML page, as opposed to servlets which can embed HTML code inside of Java code to produce an HTML page. These two technologies are often used together as integral parts of a Web application.
Servlets and Web Applications
The HTTP servlet 2.2 specification introduces the new concept of a Web Application, which allows resources for a server-side application to be bundled together and deployed as a unit. For details on developing and deploying Web Applications on WebLogic Server, see the developers guide Writing a Web Application.
Overview of HTTP Servlet Support in Weblogic Server
The code in your HTTP servlets can use all of WebLogic Server's server-side services, including EJB, RMI, and JDBC. Below is an overview of the support services available to HTTP servlets:
How WebLogic Server Implements Servlets
HTTP servlets are a major part of WebLogic Server's HTTP capabilities. In fact, WebLogic Server fulfills all its HTTP requirements using a set of pre-built HTTP servlets that are implemented and registered exactly as you would write and register your own custom servlets. For instance, in WebLogic Server:
These internal servlets are registered in the weblogic.properties file. You can call these servlets from an HTTP client and integrate their features in to your Web application. For a more detailed description of these servlets, see Registering the WebLogic Servlets.
After you write your own HTTP servlets, you register them in the weblogic.properties file in exactly the same way as the standard internal servlets that are shipped with WebLogic Server. Your custom servlets are treated exactly like the standard HTTP servlets that provide the HTTP capabilities.
Each HTTP servlet is registered against a specific URL pattern, so that when a matching URL is requested, the corresponding servlet is called upon to handle the request. For details on registering HTTP servlets with WebLogic Server, see the WebLogic Administrators Guide, Registering user-written servlets.
WebLogic HTTP Servlet API Reference
WebLogic supports the javax.servlet.http package in the Java Servlet 2.2 API. You can find documentation for the package at Sun.
Introduction to Programming
Steps to Write a Basic HTTP servlet
The section contains a description of the basic steps for writing an HTTP servlet. A complete code example (the HelloWorldServlet) illustrating these steps is included at the end of this chapter. Additional information on using various J2EE and Weblogic Server services such as JDBC, RMI, and JMS in your servlet are discussed later in this document.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HelloWorldServlet extends HttpServlet{
You may have seen other servlet examples implement the doPost() and/or doGet() methods. These reply only to POST or GET requests; If you want to handle all request types from a single method, your servlet can simply implement the service() method. (However, if you choose to implement the service() method, you will not be able to implement the doPost() or doGet() methods -- unless you call super.service() at the beginning of the service() method.) The HTTP servlet specification describes other methods used to handle other less-common request types, however all of these methods are collectively referred to as service methods.
All of the service methods take the same parameter arguments; an HttpServletRequest provides information about the request, and an HttpServletResponse, is used by your servlet to reply to the HTTP client.
public void service(HttpServlet Request req,
HttpServletResponse res) throws IOException
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html><head><title>Hello World!</title></head>");
out.println("<body><h1>Hello World!</h1></body></html>");
}
}
$ javac -d %SERVLET_CLASSES% myservlet.java
The servlet classpath is set up to point to the %SERVLET_CLASSES% directory in the weblogic.properties file, with the property:
weblogic.httpd.servlet.classpath=\
c:/weblogic/myserver/servletclasses
Search for the property in the weblogic.properties file and uncomment it if necessary.
Here are a number of ways you can deploy servlets that will suit different situations:
weblogic.httpd.register.hello=\
examples.servlets.HelloWorldServlet
You may also set ACLs for servlets deployed via the weblogic.properties file. This is described in more detail in the Administrators Guide Setting WebLogic Properties.
You may temporarily deploy or un-deploy a servlet from the WebLogic Console without stopping WebLogic Server. See the Deployment Guide Using WebLogic Server hot deploy. To make this a permanent configuration, you must also register the servlet in the weblogic.properties file, as described above.
The ServletServlet allows you to call any servlet class on the server, even if it is not registered or hot-deployed. This has security and performance disadvantages, but is useful while you are prototyping in the development phase. We recommend that you do not register the ServletServlet in a production system. For more information, see Using the ServletServlet -- a Developer's Shortcut.
To invoke a servlet from a browser you encode the servlet's URL into a page link, or an HTML form. However, you can test your HTTP servlet directly by typing the servlet URL into the URL location bar on a Web browser, after the pattern:
http://host:port/virtualName?servletArgs
For our example, running on a WebLogic Server at the default location, enter this URL:
http://localhost:7001/Hello
Advanced Features
The above procedures create a basic servlet. You will probably want to use some of the more advanced features of servlets, which are described briefly below:
This is the complete Java source code for the example used in the above steps. The example is a simple servlet that provides a response to an HTTP request. Later, this example will be expanded to illustrate how to use HTTP parameters, cookies, and session tracking.
You can find the source and instructions on how to compile and run all the examples used in this document in the examples/servlets directory of your WebLogic Server distribution. The WebLogic Server examples are also available as a zip archive.
Listing 3-1 HelloWorldServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HelloWorldServlet extends HttpServlet {
public void service(HttpServletRequest req,
HttpServletResponse res)
throws IOException
{
// Must set the content type first
res.setContentType("text/html");
// Now obtain a PrintWriter to insert HTML into
PrintWriter out = res.getWriter();
out.println("<html><head><title>" +
"Hello World!</title></head>");
out.println("<body><h1>Hello World!</h1></body></html>");
}
}
Programming Tasks
When a servlet is initialized, WebLogic Server executes the servlet's init() method. Once the servlet has been initialized, it is not initialized again until you re-start WebLogic Server, unless the servlet is modified and reloaded. You can have your servlet perform certain tasks, such as establishing database connections, at initialization by overriding the init() method.
Normally, WebLogic Server initializes a servlet when the first request is made for the servlet. Subsequently, if the servlet is modified, the destroy() method is called on the existing version of the servlet, then, after a re4quest is made for the modified servlet, the modified servlet's init() method is executed.
Initializing a Servlet at Server Startup
You can also configure WebLogic Server to initialize a servlet immediately after the server is started by adding the following lines to the weblogic.properties file. Use this feature if your servlet initialization has a noticeable delay the first time it is called, or if your servlet needs to be active upon server startup.
The servlet will be initialized at startup only if it is found in the weblogic.class.path. If it is in the weblogic.servlet.class.path, a noClassDefFound exception will be thrown.
# Here we register the myservletclass servlet class
weblogic.httpd.register.MyServlet=\
examples.servlets.myservletclass
# Configure the ServletStartup class to run MyServlet's init()
# method at startup
weblogic.system.startupClass.StartMyServlet=\
weblogic.servlet.utils.ServletStartup
weblogic.system.startupArgs.StartMyServlet=\
servlet=MyServlet
where myservletclass is the servlet you want to initialize when you start WebLogic Server, associated here with the virtual name MyServlet.
At startup, the initialization process works as follows:
To initialize more than one servlet at server startup time, you must register the ServletStartup class multiple times, using a different virtual name for each servlet. It is a good idea to follow a naming convention, such as that used above, so that you do not use conflicting virtual names and can keep track of registrations.
Using Initialization Parameters
You can use the weblogic.properties file to pass parameters to an HTTP servlet at its initialization. This allows you to customize the behavior of your servlet without having to recompile it. You associate the parameters with the servlet via its virtual name. For example, if the HelloWorldServlet is registered with the virtual name Hello, you can pass it initialization arguments using:
weblogic.httpd.register.Hello=examples.servlets.HelloWorld
weblogic.httpd.initArgs.Hello=greeting=howdy,person=stranger
For more information on registering servlets, read the Administrators Guide, Setting WebLogic Properties.
You retrieve initialization parameters by calling the getInitParameter(String name) method from the parent javax.servlet.GenericServlet class. When passed the name of the parameter, this method returns the parameter's value as a String.
You can have your servlet perform actions at initialization time by overriding the init() method. It is important that you call the overridden init() method in the super class, so that it may parse the initialization arguments. It is generally a good idea to make this the first line in your implementation of the init() method.
The code fragment below reads initArgs that define a greeting, and a default name that can be customized from the weblogic.properties file.
String defaultGreeting;
String defaultName;
public void init(ServletConfig config)
throws ServletException {
super.init(config);
if ((defaultGreeting = getInitParameter("greeting")) == null)
defaultGreeting = "Hello";
if ((defaultName = getInitParameter("person")) == null)
defaultName = "World";
}
The values of each parameter are stored in the class instance variables defaultGreeting and defaultName. Note that the code provides default values for these variables if the initArgs property is missing from the weblogic.properties file by testing to see if the getInitParameter() method returns null.
You can then use the service() method to use these variables in the response. For example:
out.print("<body><h1>");
out.println(defaultGreeting + " " + defaultName + "!");
out.println("</h1></body></html>");
The full source code and instructions for compiling, installing, and trying out an example called HelloWorld2, which illustrates the use of the init() method can be found in the WebLogic distribution examples/servlets directory. Do not forget to add the initArgs property to the servlet registration in the properties file:
weblogic.httpd.register.Hello2=examples.servlets.HelloWorld2
weblogic.httpd.initArgs.Hello2=\
greeting=howdy,person=stranger
After you restart WebLogic Server, view the servlet in your browser with this URL:
http://localhost:7001/Hello2
This section describes how your HTTP servlet provides a response to the client. All responses should be delivered using the HttpServletResponse object that is passed as a parameter to the service() method of your servlet.
You can set several servlet properties through the HttpServletResponse object that translate into HTTP header information. At a minimum, set the content type using the setContentType() method, even before you obtain the output stream to which you write the page contents. For HTML pages, set the content type to "text/html". For example:
res.setContentType("text/html");
You can also use the setContentType() method to set the character encoding. For example:
res.setContentType("text/html;ISO-88859-4");
You can set header attributes using the setHeader() method. For dynamic responses, it is useful to set the "pragma" attribute to "no-cache", which causes the browser to always reload the page and ensures the data is current.
res.setHeader("Pragma", "no-cache");
The response that your servlet sends back to the client must look like regular HTTP content. For the most part, this means you must send back the contents of an HTML page. Your servlet sends back an HTTP response via an output stream that you obtain using the response parameter of the service() method. To send an HTTP response:
PrintWriter out = res.getWriter();
/or
ServletOutputStream out = res.getOutputStream();
You can use both PrintWriter and ServletOutputStream in the same servlet (or in another servlet that is included in a servlet). The output of both is written to the same buffer.
out.print("<html><head><title>My Servlet</title>");
out.print("</head><body><h1>");
out.print("Welcome");
out.print("</h1></body></html>");
Do not close the output stream using the close() method and avoid flushing the stream's contents. Not closing or flushing the output stream, allows WebLogic Server to take advantage of persistent HTTP connections, as described in the next step.
WebLogic Server attempts to use HTTP persistent connections by default whenever possible. A persistent connection attempts to reuse the same HTTP TCP/IP connection for subsequent communications between client and server. Application performance improves because new connections need not be opened for immediate subsequent requests. This is a common requirement for HTML pages containing many in-line images, where each request image would otherwise require a TCP/IP connection.
You can configure the amount of time that WebLogic Server keeps an HTTP connection open with the KeepAlive properties. For more information, see Configuring persistent HTTP connections.
WebLogic Server must know the length of the HTTP response in order to establish a persistent connection and automatically adds a Content-Length property to the HTTP response header. In order to determine the content length, WebLogic Server must buffer the response. However, if your servlet explicitly flushes the ServletOutputStream, WebLogic Server will be unable to use persistent connections. For this reason, you should avoid explicitly flushing the HTTP response in your servlets.
You may decide that in some cases, it is better to flush the response early to display information in the client before the page has completed, for example to display a banner advertisement while some time-consuming page content is calculated. Conversely, you may want to increase the size of the buffer used by the servlet engine to accommodate a larger response before flushing the response. You can manipulate the size of the response buffer by using the related methods of the javax.servlet.ServletResponse interface .
The HTTP servlet API provides a clean interface for retrieving user input from Web pages.
An HTTP request from a Web browser can be accompanied by other information besides the URL, such as information about the client, the browser, cookies, and user query parameters. Query parameters are used to carry user input from the browser, and are either appended to the URL address (the GET method) or included in the HTTP request body (the POST method).
HTTP servlets need not deal with these details; all of the information in the request is automatically available through the HttpServletRequest object and accessible by using the request.getParameters() method, regardless of the send method.
You can send query parameters from the client in a number of ways:
<a
href="http://localhost:7001/ColorServlet?color=purple">
Click Here For Purple!</a>
Query parameters are always sent in name/value pairs, and are accessed through the HttpServletRequest object. You can obtain an Enumeration of all parameter names in the query, and fetch each parameter value using its parameter name. A parameter usually has only one value, but can hold an array of values. Parameter values are always interpreted as Strings, so you may need to cast them to a more appropriate type.
This sample from a service() method examines query parameter names and their values from a form. Note that request is the HttpServletRequest object.
Enumeration params = request.getParameterNames();
String paramName = null;
String[] paramValues = null;
while (params.hasMoreElements()) {
paramName = (String) params.nextElement();
paramValues = request.getParameterValues(paramName);
System.out.println("\nParameter name is " + paramName);
for (int i = 0; i < paramValues.length; i++) {
System.out.println(", value " + i + " is " +
paramValues[i].toString());
}
}
Other Methods of HttpServletRequest
Example: Retrieving Input by Using Query Parameters
In this example, the HelloWorld2 servlet example is modified to accept a username as a query parameter, to build in a more personal greeting. The modified example is called HelloWorld3.java. The source code for the HelloWorld3.java example is included in the distribution in the examples\servlets directory. The service() method from the HellowWorld2 example is implemented as shown here:
public void service(HttpServletRequest req,
HttpServletResponse res)
throws IOException
{
String name, paramName[];
if ((paramName = req.getParameterValues("name"))
!= null) {
name = paramName[0];
}
else {
name = defaultName;
}
// Set the content type first
res.setContentType("text/html");
// Obtain a PrintWriter as an output stream
PrintWriter out = res.getWriter();
out.print("<html><head><title>" +
"Hello World!" + </title></head>");
out.print("<body><h1>");
out.print(defaultGreeting + " " + name + "!");
out.print("</h1></body></html>");
}
The getParameterValues() method retrieves the value of the name parameter from the HTTP query parameters. You retrieve these values in an array of type String. A single value for this parameter is returned, which is assigned to the first element in the name array. If the parameter is not present in the query data, null is returned; in this case, name is assigned to the default name that was read from the initArgs property by the init() method.
Compile and install the servlet example, then invoke it using the ServletServlet and the servlet classpath, using this URL in your browser (on one line):
http://localhost:7001/servlets/examples/servlets/
HelloWorld3?name=yourNameHere
Your code should never assume that parameters are included in an HTTP request. Since the deprecation of the getParameter() method, you might be tempted to shorthand the getParameterValues() method by tagging an array subscript to the end. However, this method can return null if the parameter is not available, resulting in a NullPointerException. For example:
String myStr = res.getParameterValues("paramName")[0];
if ((String myStr[] =
res.getParameterValues("paramName"))!=null) {
// Now you can use the myStr[0];
}
else {
// paramName was not in the query parameters!
}
Using Session Tracking From a Servlet
Session tracking enables you to track a user's progress over multiple servlets or HTML pages, which by nature are stateless. A "session" is defined as a series of browser requests that come from the same client, and are often related, during a certain time period. Session tracking ties together a series of browser requests-think of these as pages-that may have some meaning as a whole, such as a shopping cart application.
Before session tracking matured conceptually, developers tried to build state into their pages by stuffing information into hidden fields on a page or embedding user choices into URLs used in links with a long string of appended characters. You can see good examples of this at most search engine sites, many of which still depend on CGI. These sites track user choices with URL parameter name/value pairs that are appended to the URL, after the reserved HTTP character "?". This can result in a very long URL that the CGI script must carefully parse and manage. The problem with this approach is that you cannot pass this information from session to session. Once you lose control over the URL-that is, once the user leaves one of your pages-the user information is lost forever.
Later, Netscape introduced browser cookies, which you can use to store user-related information on the client for each server. However, some browsers still do not fully support cookies, and some users prefer to turn off the "cookie" option in their browsers. Another factor that should be considered is that most browsers limit the amount of data that can be stored with a cookie.
The HTTP servlet specification defines a solution that allows the server to store user details in a tangible place on the server, and protects your code from the complexities of tracking sessions. Your servlets can use an HttpSession object to track a user's input over the span of a single session and share session details between multiple servlets.
Tracking a Session with the HttpSession Object
HttpSession session = request.getSession(true);
An HttpSession object is created if one doesn't already exist for that client when the request.getSession(true) method is called with the argument true. The session object lives on WebLogic Server for the lifetime of the session, during which the session object accumulates information related to that client. Your servlet adds to or removes information from the session object as necessary. A session is associated with a particular client, although that user might not be identified as anything other than anonymous. Each time the client visits your servlet, the same associated HttpSession object is retrieved when the getSession() method is called.
For more details on the methods supported by the HttpSession, refer to the HttpServlet API.
This example service() method counts how many times a user has requested the servlet in a session.
public void service(HttpServletRequest request,
HttpServletResponse, response)
throws IOException
{
// Get the session and the counter param attribute
HttpSession session = request.getSession (true);
Integer ival = (Integer)
session.getAttribute("simplesession.counter");
if (ival == null) // Initialize the counter
ival = new Integer (1);
else // Increment the counter
ival = new Integer (ival.intValue () + 1);
// Set the new attribute value in the session
session.setAttribute("simplesession.counter", ival);
// Output the HTML page
out.print("<HTML><body>");
out.print("<center> You have hit this page ");
out.print(ival + " times!");
out.print("</body></html>");
}
A session tracks a user's selections over a series of pages in a single transaction, such as browsing for an item, adding it to a shopping cart, then billing by credit card. A session is transient, and its lifetime ends when:
For more persistent long term storage of data your servlet should write details to a database using JDBC or EJB and associate the client with this data using a long-lived cookie and/or username and password. Although this document describes that sessions use cookies and persistence internally, you should not use sessions as a general mechanism for storing data about a user.
How does WebLogic Server know which session is associated with each client? When an HttpSession is created in a servlet, it is associated with a unique ID. The browser must provide this session ID with its request in order for the server to find the session data again. The server attempts to store this ID by setting a cookie on the client. Each time the client sends a request to the server from then onwards, it includes the cookie containing the ID. The server automatically parses the cookie, and supplies the session data when your servlet calls the getSession() method.
If the client does not accept cookies, the only alternative is to encode the ID into the URL links in the pages sent back to the client. For this reason, always use the encodeURL() method when you include URLs in your servlet response. WebLogic Server knows whether the browser accepts cookies and will not unnecessarily encode URLs. WebLogic automatically parses the session ID from an encoded URL, and retrieves the correct session data when you call the getSession() method. Using the encodeURL() method ensures no disruption to your servlet code regardless of the procedure used to track sessions. For more information, see Using URL Rewriting.
Detecting the Start of a Session
After you obtain a session using the getSession(true) method, you can tell if the session has just been created by calling the HttpSession.isNew() method. If this method returns true, then the client does not already have a valid session, and at this point is unaware of the new session. The client will not become aware of the new session until a reply is posted back from the server.
Design your application to accommodate new or existing sessions in a way that suits your business logic. For example, your application might redirect the client's URL to a login/password page if you determine that the session hasn't yet started. Here is a code example:
HttpSession session = request.getSession(true);
if (session.isNew()) {
response.sendRedirect(welcomeURL);
}
On the login page, provide an option to log in to the system or create a new account.
Setting and Getting Session Name/Value Attributes
You can store data in an HttpSession object using name/value pairs. Data stored in a session is available through the session. Use these methods from the HttpSession interface:
getAttribute()
getAttributeNames()
setAttribute()
removeAttribute()
The following code fragment shows how to get all of the existing name/value pairs:
Enumeration sessionNames = session.getAttributeNames();
String sessionName = null;
Object sessionValue = null;
whlie (sessionNames.hasMoreElements()) {
sessionName = (String)sessionNames.nextElement();
sessionValue = session.getAttribute(sessionName);
System.out.println("Session name is " + sessionName +
", value is " + sessionValue);
}
To add or overwrite a named attribute, you use the setAttribute() method. To remove a named attribute altogether, use the removeAttribute() method.
Note: You can add any Java descendant of Object as a session attribute and associate it with a name. However, if you are using session persistence, your attribute "value"
objects must implement java.io.Serializable.
ClassCastException and HTTP Sessions
You might encounter a ClassCastException while developing servlets that use HTTP sessions. This could happen as a result of the following set of events:
Note: If you are using session persistence, the class contents must be serialized, and you will not encounter this exception.
Here are some suggested work-arounds to this problem:
You may also get a ClassCastException using JavaBeans with Servlets. The servlet puts the JavaBean in the session and the JSP gets that JavaBean from the session. When the Bean class is in the WebLogic Classpath (/myserver/serverclasses) and the Bean's source code is in that same directory, you will encounter a ClassCastException .
Note: The ClassCastException generally occurs while you are developing your servlets, and should not be an issue in a stable production system. If you are upgrading your system online, you might wish to warn your customer base.
Logging Out and Ending a Session
If your application deals with sensitive information you might consider offering the ability to log out of the session. This is a common feature with shopping carts and Internet email accounts. When the same browser returns to the service, the user must log back into the system. To achieve this, you can invalidate the current session by calling:
session.invalidate()
Do not reference an invalidated session after you have called this method. If you do, an IllegalStateException will be thrown. The next time a user visits your servlet from the same browser, the session data will be missing, and a new session will be created when the getSession(true) method. At this point you might want to send the user to the login page again.
WebLogic Server provides many configurable properties that determine how WebLogic Server handles session tracking. For details on configuring these session tracking properties, see the Administrators Guide, Setting up session management.
In some situations, a browser may not accept cookies, which makes session tracking using cookies impossible. URL rewriting is a work-around to this scenario that can be substituted automatically when WebLogic Server detects that the browser does not accept cookies. URL rewriting involves encoding the session ID into the hyper-links on the Web pages that your servlet sends back to the browser. When the user subsequently clicks these links, WebLogic Server extracts the ID from the URL address and finds the appropriate HttpSession when your servlet calls the getSession() method.
To enable URL rewriting in WebLogic Server, you must set the following property in your weblogic.properties file:
weblogic.httpd.session.URLRewriting.enable=true
Note that in order to preserve authenticated status when using weblogic.serlvet.security.ServletAuthentication, WebLogic checks the status of the HttpSession from the request. If weblogic.httpd.session.URLRewriting.enable is true this causes the post data to be consumed. So, if you intend to send post data to the server and you expect to be able to read the raw post data, you should set the content type to something other than the default value of application/x-www-form-urlencoded.
There are some general guidelines for how your code should handle URLs in order to support URL rewriting. You should avoid writing a URL straight to the output stream, as shown here:
out.println("<a href=\"/myshop/catalog.jsp\">catalog</a>");
Instead, use the HttpServletResponse.encodeURL() method instead, For example:
out.println("<a href=\""
+ response.encodeURL("myshop/catalog.jsp")
+ "\">catalog</a>");
Calling the encodeURL() method determines if the URL needs to be rewritten, and if so, it rewrites it, by including the session ID in the URL.
In addition to URLs that are returned as a response to WebLogic Server, also encode URLs that send redirects. For example:
if (session.isNew())
response.sendRedirect (response.encodeRedirectUrl(welcomeURL));
WebLogic Server will use URL rewriting when a session is new, even if the browser does accept cookies, because the server cannot tell if a browser accepts cookies in the first visit of a session.
Your servlet may determine if a given session was determined from a cookie by checking the boolean returned from the HttpServletRequest.isRequestedSessionIdFromCookie() method. Your application may respond appropriately, or simply rely on URL rewriting by WebLogic Server.
URL rewriting and Wireless Access Protocol (WAP)
If you are writing a WAP application, you will need to use URL rewriting because the WAP protocol does not support cookies. In addition, some WAP devices have a 128 character limit on the length of a URL (including parameters), which limits the amount of data that can be transmitted using URL re-writing. To allow more space for parameters, you can limit the size of the session ID that is randomly generated by WebLogic Server by specifying the following property in the weblogic.properties file:
weblogic.httpd.session.sessionIDLength=bytes
The minimun value is 10 bytes, the default value is 52 bytes. The maximum value is Integer.MAX_VALUE.
You can set up WebLogic Server to record session data in a persistent store. If you are using session persistence, you can expect the following characteristics:
Scenarios To Avoid When Using Sessions
Do not use session persistence for storing long term data between sessions. In other words, do not rely on a session still being active when a client returns to a site at some later date. Instead, your application should record long-term or important information in a database.
Sessions are not a convenience wrapper around cookies. Do not attempt to store long term or limited term client-data in a session. Instead, your application should create and set its own cookies on the browser. Examples include an auto-login feature where the cookie might live for a long period, or an auto-logout feature where the cookie might expire after a short period of time. Here, you should not attempt to use HTTP sessions, but instead write your own application-specific logic.
The format of the session id is specified internally, and may change from one version of WebLogic Server to another. For this reason, BEA Systems recommends that you do not create applications which require a specific session id format.
Use Serializable Attribute Values
When you use persistent sessions, all attribute "value" objects that you add to the session must implement java.io.Serializable. For more details on writing serializable classes, refer to the online java tutorial about serializable objects. If you add your own serializable classes to a persistent session, be careful that each instance variable of your class is also serializable. Otherwise, you can declare it as transient, and WebLogic will not attempt to save that variable to persistent storage. One common example of an instance variable that must be made transient is the HttpSession object. (See the notes on using serialized objects in sessions in the section Making Sessions Persistent )
Configuring Session Persistence
For details on setting up persistent sessions, see the Administrators Guide Setting up WebLogic as an HTTP server: Configuring session persistence.
A cookie a piece of information that the server asks the client browser to save locally on the user's disk. Each time the browser visits the same server, it sends all cookies relevant to that server with the HTTP request. Cookies are useful for identifying clients as they return to the server.
Each cookie has a name and a value. A browser that supports cookies generally allows each server domain to store up to 20 cookies at up to 4k per cookie.
Setting Cookies in an HTTP servlet
To set a cookie on a browser, you create the cookie, give it a value, and add it to the HttpServletResponse object that is the second parameter in your servlet's service method. For example:
Cookie myCookie = new Cookie("ChocolateChip", "100");
myCookie.setMaxAge(Integer.MAX_VALUE);
response.addCookie(myCookie);
This examples shows adding a cookie called "ChocolateChip" with a value of "100" to the browser client when the response is sent. The expiration of the cookie is set to the largest possible value, which effectively makes the cookie last forever. Setting the setMaxAge to -1, or any other negative value, means that the cookie is not stored persistently and will be deleted when the Web browser exits. Setting setMaxAge to 0 will cause the cookie to be be immediately deleted, setting the cookie's max age to that of the server. Note that this causes the cookie to be immediately invalidated, regardless of any discrepancy in the time on the user's browser. All times are relative to the current time on the server, and thus if the browser's clock is different, this may have undesired effects.
Because cookies only accept string-type values, you should cast to and from the desired type that you want to store in the cookie. A common practice is to use the handle ID of an EJB instance for the cookie value and store the user's details in the EJB.
Retrieving Cookies in an HTTP Servlet
You can retrieve a cookie object from the HttpServletRequest that is passed to your servlet as an argument to the service() method. The cookie itself is presented as a javax.servlet.http.Cookie object.
In your servlet code, you can retrieve all the cookies sent from the browser by calling:
Cookie[] cookies = request.getCookies();
This method returns an array of all cookies sent from the browser, or null if no cookies were sent by the browser. Your servlet needs to process the array in order to find the correct named cookie. You can get the name of a cookie using the Cookie.getName() method. It is possible to have more that one cookie with the same name, but different path attributes. If your servlets set multiple cookies with the same names, but different path attributes, you also need to compare the cookies using the Cookie.getPath() method. The following code illustrates how to access the details of a cookie sent from the browser. It assumes that all cookies sent to this server have unique names, and that your are looking for a cookie called "ChocolateChip" that may have been previously set in a browser client. For example:
Cookie[] cookies = request.getCookies();
boolean cookieFound = false;
for(int i=0; i < cookies.length; i++) {
thisCookie = cookies[i];
if (thisCookie.getName().equals("ChocolateChip")) {
cookieFound = true;
break;
}
}
if (cookieFound) {
// We found the cookie! Now get its value
int cookieOrder = String.parseInt(thisCookie.getValue());
}
For more details on cookies, see The Cookie API and The Java Tutorial: Using Cookies.
Using Cookies that Will Be Transmitted by Both HTTP and HTTPS
Because HTTP and HTTPS requests are sent to different ports, some browsers may not include the cookie sent in an HTTP request with a subsequent HTTPS request (or vice-versa). This may cause new sessions to be created when servlet requests alternate between HTTP and HTTPS. To ensure that all cookies set by a specific domain are sent to the server every time a request in a session is made, set the following property in the weblogic.properties file for the server (or cluster) that hosts the servlet:
weblogic.httpd.session.cookie.domain=myserver.com
This property will instruct the browser to include the proper cookie(s) for all requests to hosts in the domain specified in place of "myserver.com". For more information on this property or configuring session cookies, see Setting up WebLogic as an HTTP Server.
Secure Cookies
As of Service Pack 12, we will have introduced a new parameter that can be used to mark the sessionCookie as secure. If set, the client's browser will only send the cookie back over an HTTPS connection. This ensures that the cookie ID is secure and should only be used on websites that exclusively use HTTPS. Once this feature is enabled, session cookies over HTTP will no longer work; if your client is directed to a non-HTTPS location the session will not be sent. It is highly advisable to turn off URLRewriting if you use this feature; if your application attempts to encode URLs, the session ID will be shared over HTTP. Add the following to your weblogic.xml to use this feature:
<session-param>
<param-name>CookieSecure</param-name>
<param-value>true</param-value>
</session-param>
<session-param>
Your Application Security and Cookies
Using cookies that enable automatic account access on a machine is convenient, but can be undesirable from a security perspective. When you design your application, follow these guidelines:
Automatically login from this computer?
If you write a browser client using server-side Java, your client has access to many of the rich features of WebLogic Server such as factory methods-like JNDI, RMI, EJB, JDBC connections, etc.-as a WebLogic server-side process, rather than as a Java client application. You can do this with a static method from the weblogic.common.T3Services class, as shown here:
T3ServicesDef t3s =
T3Services.getT3Services();
Once you have a T3ServicesDef object, you can call any of the factory methods from that interface to get access to WebLogic services. For example, here is how you might submit an event registration from a servlet (where request is the HttpServletRequest object):
ParamSet eventParameters = new ParamSet();
String name;
Enumeration names = request.getHeaderNames();
while (names.hasMoreElements()) {
name = (String)names.nextElement();
try {
eventParameters.setParam(name, request.getHeader(name));
}
catch (Exception e) {;}
}
EventMessageDef ev = T3Services.getT3Services().events()
.getEventMessage("HTTPWATCH", eventParameters);
ev.submit();
Here is another example of how you might use WebLogic services from a servlet, through the log() and config() services:
T3ServicesDef t3s = T3Services.getT3Services();
String consoleEnabled =
t3s.config().getProperty("weblogic.system.enableConsole");
String logmsg = "Console enabled was set to " +
consoleEnabled + " at " +
new java.util.Date();
LogServicesDef logger = t3s.log();
logger.log(logmsg);
Accessing Databases-Using Connection Pools in a Servlet
WebLogic Server supports the use of JDBC connection pools from server-side Java classes, including servlets, using two server-side JDBC drivers: one for routine use for most database operations, and another for transactional operations such as Enterprise JavaBeans (EJB). Because WebLogic Server's servlet persistence is EJB-based, connection pools are used as part of your configuration setup for persistence.
A connection pool is a named group of identical JDBC connections to a database that are created when the connection pool is registered, usually when starting up WebLogic Server. Your servlets "borrow" a connection from the pool, use it, then return it to the pool by closing it. This is far more efficient than creating a new connection for each client each time they need to access the database. Another advantage is that you do not need to hard-code details about the database your application uses.
WebLogic supplies special JDBC "pool" drivers that give server-side Java access to connection pools that are registered on WebLogic Server.
WebLogic's JDBC pool drivers include:
Driver URL: jdbc:weblogic:pool
Driver package name: weblogic.jdbc.pool.Driver
This driver, which is most often used with servlets, is documented here.
Driver URL: jdbc:weblogic:jts
Driver package name: weblogic.jdbc.jts.Driver
For more about using the JTS-based JDBC pool driver for EJBeans, read The WebLogic EJB Environment and Using the JTS Driver.
Setting up the Registration for a Connection Pool
To configure a connection pool, you add a registration for it to the weblogic.properties file. The connection pool is created each time you start WebLogic Server and exists until the server is shut down. There are more details on setting properties for JDBC connection pools in the document Creating and Using Connection Pools.
You configure most aspects of the connection pool from the properties file, such as:
It is easy to use a connection from the pool in your servlet code. Your servlet code is abstracted from administration details of the pool. You can configure the pool, or even point the named connection pool at a completely different database, all without changing or recompiling any code.
The following example of a registration from a weblogic.properties file is for a connection pool named sales and its ACL (the ACL is specified with the property weblogic.allow.reserve.weblgoic.jdbc.connectionPool.sales). This pool uses WebLogic jDriver for Oracle to connect to an Oracle database.
weblogic.jdbc.connectionPool.sales=\
url=jdbc:weblogic:oracle,\
driver=weblogic.jdbc.oci.Driver,\
initialCapacity=2,\
maxCapacity=10,\
capacityIncrement=2,\
props=user=scott;password=tiger;server=goldengate
weblogic.allow.reserve.weblogic.jdbc.connectionPool.sales=\
joeuser,maryuser
If you do not set an ACL for a connection pool, or one is not provided by the context of your code (such as the properties of a t3 Client), it defaults to "everyone"-that means any user can grab a connection. If you want to restrict access to the pool to certain users:
weblogic.allow.reserve.weblogic.jdbc.connectionPool.sales=\
joeuser,maryuser
Properties props = Properties();
props.set("user", "joeuser");
props.set("password", "dP3m*spQc!");
Driver myDriver = (Driver) Class.forName
("weblogic.jdbc.pool.Driver").newInstance();
conn = myDriver.connect("jdbc:weblogic:pool:sales",props);
Note that this username and password is the valid username and password that matches a user registered in the weblogic.properties file, and not a database username and password. At runtime, the username and password supplied by the application is checked against the list of T3Users established in the access control list for the connection pool.
weblogic.password.joeuser=dP3m*spQc!
Using a Connection Pool in a Servlet
Here is a simple servlet that selects all of the records from a database table using dbKona (a proprietary BEA API that creates high-level abstractions for database operations), and displays them using htmlKona (a BEA proprietary API for creating HTML in Java code).
Driver myDriver = (Driver)
Class.forName("weblogic.jdbc.pool.Driver").newInstance();
You can identify the pool in one of two ways:
Connection conn =
myDriver.connect("jdbc:weblogic:pool:sales", null);
Properties props = new Properties();
props.put("connectionPoolID", "myConnectionPool");
Connection conn =
myDriver.connect("jdbc:weblogic:pool", props);
Note that the Driver.connect() method is used in these examples instead of the DriverManger.getConnection() method. Although you may use DriverManger.getConnection() to obtain a database connection, BEA recommends that you use Driver.connect() because this method is not synchronized and provides better performance.
Note that the Connection returned by connect() is an instance of weblogic.jdbc.pool.Connection.
Here is the code for the entire servlet. This servlet displays the contents of the "emp" database table in an HTML table on a Web page:
Listing 4-1 simpleselect.java
package examples.jdbc.pool;
import java.io.*;
import java.sql.*;
import java.util.Properties
import javax.servlet.*;
import javax.servlet.http.*;
import weblogic.db.jdbc.*;
import weblogic.html.*;
public class simpleselect extends HttpServlet {
public synchronized void service(HttpServletRequest req,
HttpServletResponse res)
throws IOException
{
Connection conn = null;
try {
Properties props = Properties();
props.set("user", "joeuser");
props.set("password", "dP3m*spQc!");
Driver myDriver = (Driver) Class.forName
("weblogic.jdbc.pool.Driver").newInstance();
conn = myDriver.connect("jdbc:weblogic:pool:sales",props);
res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("text/html");
TableDataSet ds = new TableDataSet(conn, "emp");
TableElement tbl = new TableElement(ds);
ServletPage hp = new ServletPage("Simple select");
hp.getBody()
.addElement(MarkupElement.HorizontalLine)
.addElement(tbl);
ds.close();
conn.close();
hp.output(res.getOutputStream());
}
catch (Exception e) {
ServletPage hp =
new ServletPage("An Exception occurred");
ByteArrayOutputStream ostr =
new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(ostr));
hp.getBody()
.addElement(new
HeadingElement("An Exception occurred:", 2))
.addElement(new LiteralElement(ostr.toString()));
hp.output(res.getOutputStream());
}
finally {
conn.close();
}
}
}
The htmlKona class TableElement automatically generates a formatted HTML table from a TableDataSet.
This example may be compiled and run from the distribution directory examples/jdbc/pool.
Threading Issues in HTTP Servlets
When you design a servlet, consider how the servlet is invoked by WebLogic Server under high load. It is inevitable that more than one client will hit your servlet simultaneously. Therefore, write your servlet code to guard against sharing violations on shared resources or instance variables. The following tips will help you to design around this issue.
As of the WebLogic 4.5 release, the SingleThreadModel is supported, as specified in the JSDK2.1. An instance of a class that implements the SingleThreadModel is guaranteed not to be invoked by multiple threads simultaneously. Multiple instances of a SingleThreadModel servlet are used to service simultaneous requests, each running in a single thread.
To efficiently use the SingleThreadModel, WebLogic Server creates a pool of servlet instances for each servlet that implements SingleThreadModel. WebLogic Server creates the pool of servlet instances when the first request is made to the servlet and increments the number of servlet instances in the pool as needed.
When designing your servlet, consider how you use shared resources outside of the servlet class such as file and database access. Because there will be multiple instances of servlets that are identical, and may use exactly the same resources, there are still synchronization and sharing issues that must be resolved, even if you do implement the SingleThreadModel. For instance, the SurveyServlet example (distributed with the JSDK) writes to a file and the SingleThreadModel will not protect against multiple servlet instances writing to the same file.
BEA recommends that shared resource issues be handled by the developer on an individual servlet basis. Consider the following guidelines:
When a servlet is requested, the servlet can conditionally pass that request on to be handled by another servlet. This process is sometimes referred to as "servlet chaining". A common use of servlet chaining is where the application requires that the user be logged in before performing a certain function. If the servlet is requested and the user is not logged in, the request is redirected to a login servlet. A token might be saved in the HTTP session to note where the original request was made so that control can return there after a successful login.
A servlet passes a request to another servlet using the RequestDispatcher. This avoids the need to send an HTTP-redirect response back to the client. The RequestDispatcher correctly passes the HTTP request to the HTTP servlet it represents. To obtain the appropriate RequestDispatcher for a particular HTTP servlet, use one of the following methods from the ServletContext, which your servlet may access via the call:
ServletContext sc = getServletConfig().getServletContext();
Your servlet can look up the RequestDispatcher for a servlet using one of these methods:
The RequestDispatcher has two methods that allow you either to forward the entire servlet request to a servlet, or include the output from another servlet in your servlet's response. These methods are discussed in the next two sections.
You can obtain a RequestDispatcher for any HTTP resource within a context, including HTTP Servlets, JSP pages, or plain HTML pages. Simply request the appropriate URL path for the resource in the getRequestDispatcher() method.
Forwarding a Request
Once you have the correct RequestDispatcher, your servlet forwards a request using the RequestDispatcher.forward() method, passing the HTTPServletRequest and HTTPServletResponse as arguments.
The servlet must not attempt to write any previous output to the response. If the servlet retrieves the ServletOutputStream or the PrintWriter for the response prior to forwarding the request, an IllegalStateException will be thrown.
All other output from the original servlet is ignored after the request has been forwarded.
Including a Request
Your servlet can include the output from another resource by using the RequestDispatcher.include() method, and passing the HTTPServletRequest and HTTPServletResponse as arguments.
Any attempt to set the response status code, or any HTTP header information from the included servlet response is ignored. In effect, you can use this method to achieve a server-side-include of another HTTP resource from your servlet code.
Note: Note: It is recommend that you use JavaServer Pages and the JSP include directive to achieve the same effect as Server-Side Includes in WebLogic Server. With JSPs, you can write plain HTML into a JSP page without using the more sophisticated features of JSP. JSP allows you to include data in a JSP page in two ways; these procedures are described concisely in section 2.7 of the JSP specification. For more details, please see the Developers Guide Using WebLogic JSP.
Server-side includes are scheduled for deprecation in a future release of WebLogic Server.
WebLogic supports a subset of server-side includes (.shtml files) that uses an internal WebLogic servlet called the ServerSideIncludeServlet. Server-side includes allow you to incorporate templates in your HTML pages. You can define the templates in separate files, and then include them in other Web pages to make maintenance easier. For example, you might define a header and a footer for all of your Web pages. When you want to change the headers, you can make the change in the single template file to take effect on all other pages that include the template file.
You may also invoke a servlet using the servlet tag to generate dynamic content within your Web page, although for new projects we recommend you consider using JSP.
HTML files containing server-side includes traditionally have an .shtml extension. The ServerSideIncludeServlet is registered in the weblogic.properties file to handle all requests for files with this extension. Like the FileServlet, the ServerSideIncludeServlet searches for files below the document root. For details on setting up the ServerSideIncludeServlet, see Using server-side includes.
WebLogic supports two Server-side include directives:
<!--#include virtual=filename-->
Note: Note: WebLogic only implements the virtual tag from the NCSA specification, where virtual gives a file that is relative to the document root. Currently, the included files are not interpreted for sub-ServerSideInclude directives.
To use the <servlet> tag, set the name attribute to the virtual name of the registered servlet (for more about registering servlets for use with WebLogic, read Setting up WebLogic as an HTTP server). For example:
<servlet name=servletVirtualName>
<param name=paramName value=paramValue>
</servlet>
Note: Note: Due to limitations in the HTTP specification, your embedded servlet may not set header information in the page response. This includes setting cookie data to be sent back to the client.
Administration and Configuration
The required steps for deploying servlets in a production environment differ form those used in a development environment. Deployment in a development environment can be done in a less secure, but more functional environment suitable for testing and debugging. Deployment methods for development environments include using the ServletServlet and the WebLogic Console to deploy your servlet.
Deploying a servlet in a production environment requires registering the servlet in the weblogic.properties file and setting various parameters that tune the servlet's performance. There are also several options for securing access to your servlet. All of these options are discussed in this section.
Setting up ACLs for Servlets in the WebLogic Realm
Note: Note: Although you may use the methodology described below to set up ACLs for your servlets, BEA recommends instead that you define security for your servlets by incorporating your servlet into a web application. ACLs for a web application are defined using a deployment descriptor. This procedure is described in Writing a Web Application
WebLogic Server controls access to internal resources like HTTP servlets through access control lists (ACLs) that are set up in the WebLogic Realm. Entries for ACLs in the WebLogic Realm are listed as properties in the weblogic.properties file. (For more info on the properties file, see the WebLogic Administrators Guide, Setting WebLogic properties.
You can set the execute permission for an HTTP servlet by adding a property to the weblogic.properties file. The ACL named weblogic.servlet controls access to all registered servlets. Setting the execute permission for the weblogic.servlet ACL to everyone allows anyone to execute any servlet without entering a password, except those servlets with more specific ACLs.
To limit access to an individual servlet, set its execute permission to a list of one or more users. For example, setting the weblogic.servlet.AdminProperties ACL to the user system allows general access (without a password) to all registered servlets except AdminProperties; only the system user would be able to execute that servlet. (The user "system" always has access to all servlets, but in this case setting the permission for this servlet effectively denies permission to everyone else.) For example:
weblogic.allow.execute.weblogic.servlet=everyone
weblogic.allow.execute.weblogic.servlet.AdminProperties=system
Setting ACLs for Groups of Servlets
You can organize servlets into groups using a delimited virtual name, then set a single ACL for those virtual names. The example below registers all administration servlets against the virtual name pattern Admin.xxxx. One ACL is set to allow access to all servlets, and another ACL to limits access to all servlets beginning with the virtual name pattern Admin. The second ACL is more specific than the first, so it effectively limits administration abilities to the system user.
weblogic.httpd.register.Admin.events=admin.AdminEvents
weblogic.httpd.register.Admin.clients=admin.AdminClients
weblogic.httpd.register.Admin.connections=\
admin.AdminConnections
weblogic.httpd.register.Admin.jdbc=admin.AdminJDBC
weblogic.httpd.register.Admin.license=admin.AdminLicense
weblogic.httpd.register.Admin.main=admin.AdminMain
weblogic.httpd.register.Admin.props=admin.AdminProps
weblogic.httpd.register.Admin.threads=admin.AdminThreads
weblogic.httpd.register.Admin.version=admin.AdminVersion
# Allow anyone to execute registered servlets
weblogic.allow.execute.weblogic.servlet=everyone
# Allow only 'system' to execute any 'Admin' servlets
weblogic.allow.execute.weblogic.servlet.Admin=system
Note: The following property has been deprecated:
weblogic.httpd.requireAuthentication=false
Its equivalent property is:
weblogic.allow.execute.weblogic.servlet=everyone
It is recommended that you upgrade your weblogic.properties file immediately, because it is not possible to guarantee how long deprecated properties will be supported.
Using the ServletServlet -- a Developer's Shortcut
As you develop servlets, you may find the ServletServlet useful for prototyping. The ServletServlet allows you to invoke servlets that are not registered in the weblogic.properties file.
To use the ServletServlet, you must register it in the weblogic.properties file with the following line:
weblogic.httpd.register.servlet=\
weblogic.servlet.ServletServlet
You may find it easier to use if you set a permissive ACL (access control list) on the ServletServlet using:
weblogic.allow.execute.weblogic.servlet.ServletServlet=\
everyone
Now you can invoke the ServletServlet from an HTTP request to serve another servlet. You specify the non-registered servlet by its full package name, which is given as the PATH_INFO to the ServletServlet. The PATH_INFO is the remainder of the URL used to reference the servlet. For instance, to invoke the HelloWorldServlet from the ServletServlet, you would use (entered on one line):
http://localhost:7001/servlet/examples/servlets/
HelloWorldServlet
The ServletServlet parses the PATH_INFO, and attempts to match it to a given class in the system CLASSPATH of WebLogic Server or in the servlet classpath, where the slash ("/") is interpreted as a dot (".").
If a class does not match the full PATH_INFO name, WebLogic Server tries to match a class to the next least specific classname by truncating the last "/xxxx" from the PATH_INFO, and so on until a matching class name is found. The surplus PATH_INFO is passed on in turn to the matching class. If no matching class is found, a server error is reported.
Warning: A servlet called using the ServletServlet will behave like any other servlet in that the init() method is executed the first time the servlet is called. (Versions of WebLogic Server prior to version 5.1 re-initialized a servlet called from the ServletServlet each time the servlet was called.)
Also, once the servlet class is loaded, it is not loaded again when subsequent servlet objects are instantiated. If you want WebLogic Server to use your latest servlet class files during runtime, you must use the servlet classpath, as described in the Using the Servlet Classpath
Disadvantages of Using the ServletServlet
In some special cases, you may need to use the ServletServlet as the mechanism for delivering servlets in a production release site. However, be aware that using the ServletServlet has the following disadvantage:
The ServletServlet does not administer WebLogic Server security access control over the servlets is serves. Users with permission to invoke the ServletServlet may use it to invoke any servlet on the host, including unregistered servlets. This counteracts any ACLs you have on other servlets in your system, and poses a security risk. You may also invoke a specific servlet to serve types of files that should otherwise be served by a more appropriate servlet.
For example, if you register the ServletServlet under the virtual name servlets, you can use that virtual name to call any servlet class file. A URL request to
http://host/servlets/weblogic/FileServlet/index.jsp
calls upon the weblogic.FileServlet servlet class to serve the source code of index.jsp as a plain HTML file, perhaps exposing code you would prefer to keep confidential.
For these reasons, WebLogic does not recommend the use of the ServletServlet in a production system unless there is a special circumstance that explicitly requires it.
Servlet classes placed in the servlet classpath are dynamically reloaded when they are modified. WebLogic Server can be configured to check for updates periodically, or whenever a class is invoked.
You can use the servlet classpath to redeploy your HTTP servlets at runtime, as they are updated, without the need to restart WebLogic Server. Classes that are referenced by JSP or JHTML pages are also reloaded if located in the servlet classpath.
JSP and JHTML pages are always recompiled if modified. However, the classes they use must be in the servlet classpath if you want them reloaded when they are modified.
To use the reload-on-modify feature, follow these steps:
/weblogic/myserver/servletclasses
Place your servlet classes under this directory using the -d option in your servlet compile command. If you run the setEnv script provided in the root directory of the WebLogic Server installation, it will set up the environment variable SERVLET_CLASSES to point to this directory. You can use the variable in your compile command, for example:
$ javac -d %SERVLET_CLASSES% myServlet.java
weblogic.httpd.servlet.classpath=\
/weblogic/myserver/servletclasses
You can add multiple directories to the servlet classpath, just as you would for the Java system classpath, separated by semi-colons ";". Note that in the weblogic.properties file, you use forward slashes "/" on all operating systems.
weblogic.httpd.servlet.reloadCheckSecs=x
where the server checks every x seconds for modified servlet classes. If x is set to zero, the servlet classes are checked every time they are invoked. If x is set to "-1", the servlet classes are never checked (effectively disabling the reload-on-modify feature).
Tips for Using the Servlet Classpath
Warning: If you store a reference to one of your classes in an HTTP session and that class is loaded from the servlet classpath and if your servlet is reloaded, you will recieve a ClassCastException when you retrieve the object from the HTTP session. See the notes on ClassCastException and HTTP Sessions.
WebLogic supports clustering servlet services across a WebLogic Cluster. Clustering provides failover and load balancing to increase the performance and reliability of your Web site. Provided that you use HTTP sessions as they were intended, there are no servlet implementation differences to consider.
For details on setting up a WebLogic Cluster, including using JDBC session persistence and in-memory state replication with a proxy server, see the Administrator Guide Setting up a WebLogic Cluster: Setting up HTTP servlets.
|
Copyright © 2000 BEA Systems, Inc. All rights reserved.
|