An Overview of Web Applications
Resin 3.0

Features
Installation
Configuration
Web Applications
IOC/AOP
Resources
JSP
Quercus
Servlets and Filters
Databases
Admin (JMX)
CMP
EJB
Amber
EJB 3.0
Security
XML and XSLT
XTP
JMS
Performance
Protocols
Third-party
Troubleshooting/FAQ

Overview
Deploy
Tutorials
FAQ
Scrapbook
Web Applications
Web Applications
Deploy

A web application is a self-contained subtree of the web site. It uses Servlets, Filters, JSP, and the functionality provided by Resin and any other java code to provide a response to a client that makes an HTTP request.

  1. Web applications
    1. Try it!
    2. Example web application
  2. Components of a web application
    1. Servlet
    2. JSP
      1. JSP's are translated into Servlets
      2. The syntax of a JSP file
    3. Filter
    4. Custom java code
    5. Java code libraries
  3. The structure of web applications
    1. Directory structure
    2. web.xml
      1. A note about path seperators
    3. Automatic compilation
  4. Lifecycle: ServletContexts, Sessions, Requests, Responses
    1. ServletContext
      1. Scope of the ServletContext
    2. Request and Response
      1. Scope of the Request and Response
    3. Session
    4. Scope of the Session
      1. How Resin keeps track of the Session
      2. Cookies
      3. URL rewriting
  5. Obtaining the ServletContext, Session, Request, and Response objects
    1. Servlet
    2. JSP
      1. Obtaining the session in JSP
  6. Attributes
    1. The API for setting and getting attributes
    2. Choosing where to put attributes
  7. Using the Response object
    1. Encoding the URL
    2. Redirecting the users browser
      1. A note on redirecting wireless devices
    3. Setting the content type dynamically
    4. Telling the browser not to cache the page
    5. Telling the browser that the page is private
  8. Using the Request object
    1. Retrieving the values set in form fields
  9. Using the Session object
    1. Explicitly causing the session to end
    2. Doing something when the Session goes away
    3. Warning! One session does not mean one browser window!
  10. Error Handling
    1. JSP Translation Time Processing Errors
    2. Coompilation Time Processing Errors
    3. Client Request Time Processing Errors
  11. Architecture
    1. Simple JSP
    2. Seperating the logic into another JSP
    3. pageContext.forward
    4. Seperating the business logic into beans
    5. Model 2 (preferred)
  12. Security
    1. Principals
    2. Roles
    3. Declarative Security
    4. Programmatic Security
    5. When does Resin require a login?
    6. The login procedure
    7. Lifecycle of a Principal
    8. Authenticating the User
    9. Example usage of Security

Web applications

Each web application is part of the web server. It has a unique name or path that identifies it within the server.

Each web application has a corresponding url. The url begins with the part needed to identify the server, followed by the webapp path: http://server/webapp-name. Each server has one web-app that is the default, it is the one that is used when no webapp-name is provided.

Web applications are "deployed" within a web server, such as Resin. The simplest way to "deploy" a new web application is to the create a subdirectory in $RESIN_HOME/webapps/webapp-name. The special webapp name ROOT is used for the default web application. (There are other deployment options , but for the purposes of this discussion the one described here is used).

A web application has "web components", such as Servlets, Filters, JSP's, supporting Java source files, and supporting java libraries.

Try it!

You can make your own web application in a local install of Resin. Make a directory $RESIN_HOME/webapps/test. Use the url http://localhost:8080/test to access the web application.

To start with, you can make a file named $RESIN_HOME/test/index.jsp.

$RESIN_HOME/test/index.jsp
Hello, world!

index.jsp is a JSP file, and is also the name of the default page to show for a directory. So you can use the url http://localhost:8080/test/index.jsp in your browser, or since index.jsp is the default page to show, you can use http://localhost:8080/test.

Example web application

For example, www.hogwarts.com has two web applications, the default web application, and a web-application named "intranet".

Server: www.hogwarts.com
Server URL: http://www.hogwarts.com

webapp: default webapp
webapp URL: http://www.hogwarts.com/
filesystem directory: $RESIN_HOME/webapps/ROOT
default jsp page: $RESIN_HOME/webapps/ROOT/index.jsp

webapp: intranet
webapp URL: http://www.hogwarts.com/intranet
filesystem directory: $RESIN_HOME/webapps/intranet
default jsp page: $RESIN_HOME/webapps/intranet/index.jsp

Components of a web application

Servlet

From the Servlet Specification 2.2:

A servlet is a web component, managed by a container, that generates dynamic content. Servlets are small, platform independent Java classes compiled to an architecture neutral bytecode that can be loaded dynamically into and run by a web server. Servlets interact with web clients via a request response paradigm implemented by the servlet container. This request-response model is based on the behavior of the Hypertext Transfer Protocol (HTTP).

A Servlet is a Java class that has a method that gets called with information about a client request and is expected to produce some kind of result to be sent back to the client. It is just like any other class in Java, it happens to inherit from class javax.servlet.http.HttpServlet , so Resin can call certain methods on it when a request is made.

A Servlet class is made available by placing the .java source file in the approriate sub-directory and file of WEB-INF/classes:

WEB-INF/classes/example/HelloWorldServlet.java
package example;

import java.io.*;

import javax.servlet.http.*;
import javax.servlet.*;

/**
 * Hello world servlet.  Most servlets will extend
 * javax.servlet.http.HttpServlet as this one does.
 */
public class HelloServlet extends HttpServlet {
  /**
   * Initialize the servlet.  Servlets should override this method
   * if they need any initialization like opening pooled
   * database connections.
   */
  public void init() throws ServletException
  {
  }

  /**
   * Implements the HTTP GET method.  The GET method is the standard
   * browser method.
   *
   * @param request the request object, containing data from the browser
   * @param repsonse the response object to send data to the browser
   */
  public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
    throws ServletException, IOException
  {
    // Returns a writer to write to the client
    PrintWriter out = response.getWriter();

    // Write a string to the browser.
    out.println("Hello, world!");
    out.close();
  }
}

Entries in ithe WEB-INF/web.xml file tell Resin the URL that should invoke the Servlet:

WEB-INF/web.xml
<web-app xmlns="http://caucho.com/ns/resin">
  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>example.HelloServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <url-pattern>/hello</url-pattern>
    <servlet-name>hello</servlet-name>
  </servlet-mapping>
</web-app>

In a web-app named "foo" on a server named "localhost" listening on port "80", the servlet is now invoked with the URL http://localhost:8080/foo/hello.

More information on the usage of Servlets is available in the Servlet section of the Resin documenation.

JSP

Java Server Pages are text files that contain text to be output (usually HTML or somesuch) and special directives, actions, scripting elements, and expressionsthat are used to generate results dynamically.

From the JSP 2.0 specification:

JavaServer Pages technology supports scripting elements as well as actions. Actions encapsulate useful functionality in a convenient form that can be manipulated by tools. Expressions are used to access data. Scripts can be used to glue together this functionality in a per-page manner.

With JSP the developer specifies the content mostly as the kind of thing they want to send back to the client or browser, for example HTML. Optionally interspersed with the HTML are special xml tags (directives and actions), EL expressions, or specially marked scripting code (Java code). The special xml tags, EL expressions and Java code are used to generate dynamic ouput.

JSP's are translated into Servlets

It is helpful to understand what it is that Resin does with a JSP page. Basically, it takes the JSP page and turns it into the Java code for a Servlet, a process of translation.

From the JSP specification:

JSP pages are textual components. They go through two phases: a translation phase, and a request phase. Translation is done once per page. The request phase is done once per request.

The translation phase occurs when Resin takes a look at the JSP page, reads it in, and creates a Servlet. This only needs to be done once. Now when a request from a client comes in, Resin will call the appropriate method in the Servlet that it created from the.

During translation, Resin takes all of the code that has been specially marked in the JSP as java code and inserts it directly into the code for a Servlet. It takes all of the template text and makes the equivalent of print statements to generate that ouput.

Because JSP files are translated into Servlets, JSP is an extension to Java Servlets. Everything that applies to Java Servlets also applies to JSP. Much information that is relevent to JSP programming is found in documentation about Java Servlets. So you want to have the Servlet Specification around as a handy reference, as well as the JSP Specification. Any reference to the capabilities and resources available to a Servlet are also available to a JSP page.

This process is invisible to the JSP developer, all the developer needs to do is make the JSP page and Resin will look at it and turn it into a Servlet.

The syntax of a JSP file

JSP has it's own section in the Resin documentation, the following is an introductory guide.

template data - The text to be output

Unless specially marked, the text in the JSP file will be sent exactly as it is in the text file as part of the response. This is called template data in the JSP specification.

JSP EL and JSTL

JSP EL is the JSP Expression Language. It is used to evaluate expressions that do not have side-effects (side-effects are changes to Objects). The use of EL is recognizable by it's syntax: ${ expr }.

JSTL is the JavaServer Pages Standard Tag Libray, a set of tags that are used to create dynamic output from JSP. These tags look like regular XML tags, and are interpreted by Resin at translation time to generate java code that performs the desired action.

EL and JSTL are used throughout this discussion, the Resin JSP documentation , the JSP Specification , and the JSTL Specification provide more information.

x.jsp - Example JSP file using EL and JSTL
<%@page session="false" contentType="text/html" %>
<%@taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<head>
<title>A simple thing</title>
</head>
<body>

<!-- this comment gets all the way to the browser -->
<%-- this comment gets discarded when the JSP is translated into a Servlet --%>
<%
// some java code that makes the variable `x' available to EL
pageContext.setAttribute("x",new Integer(5));
%>

The value of x is ${ x }
The value of x + 2 is ${ x + 2 }
Is x
less than 6?
<c:if test="${ x < 6 }">
<%@include file="y.jsp" %>
</c:if>
</body>

y.jsp - Example java code in JSP file to be included
Yes, it is true that x is less than 6, 
with a value of ${ x }

x.jsp output - The result of a call to x.jsp
<head>
<title>A simple thing</title>
</head>
<body>
<!-- this comment gets all the way to the browser -->


The value of x is 5.
The value of x + 2 is 7.
Is x
less than 6?

Yes, it is true that x is less than 6,
with a value of 5.
</body>

Prior to the introduction of JSTL and EL, JSP pages used the direct insertion of Java code to accomplish the same thing. The use of JSTL and EL is much cleaner and more maintable.

Including other files

Often it is desirable to include the contents of another file into a JSP file. For example, sometimes there is code that you find yourself using over and over again. The mechanism for this is the include directive:

<%@ include file="relativeURLspec"%>

Using the include directive it is exactly the same as if the included text was in the original file. The text is included at translation time - when the JSP is turned into a servlet.

Specifying content type

A JSP page can use the contentType attribute of the page directive to indicate the content type of the response it is sending. For example, text/html and text/wml are valid content types.

Since this value is part of a directive, a given page will always provide the same content type. It is also possible to dynamically indicate the content type using the response object, which is discussed later.

Comments

A JSP comment is of the form:

JSP comments
<%-- anything but a closing --%> ... --%>

The body of the JSP content is ignored completely. JSP Comments are discarded at translation time, they do not become part of the Servlet that is used to generate the response. Comments are useful for documentation but also to comment out some portions of a JSP page. JSP comments do not nest.

In order to generate comments that appear in the response to the requesting client, the HTML and XML comment syntax is used, as follows:

HTML comments
<!-- comments ... -->

Java code in the JSP file

Java code in the JSP is marked by the special characters <% and %>. To insert the value of a variable or an expression in the output it is marked with ><%= expr &>.

Be careful not to depend on the ability of JSP to include Java code too much. JSP is best used to present a view of data that has already been prepared in Servlets or other code, as discussed in Architecture.

Now that JSTL and JSP EL exist, they are preferred over the insertion of Java code directly.

x.jsp - Example java code in JSP file
<%@page session="false" contentType="text/html" import="java.util.*, example.*%>

<head>
<title>A simple thing</title>
</head>
<body>
<!-- this comment gets all the way to the browser -->
<%-- this comment gets discarded when the JSP is translated into a Servlet --%>
<% int x = 5; // java-style comments valid here %>
The value of x is <%= x %>.
The value of x + 2 is <%= x + 2 %>.
Is x
less than 6?
<% if (x < 6) { %>
<%@include file="y.jsp" %>
<% } %>
</body>

y.jsp - Example java code in JSP file to be included
Yes, it is true that x is less than 6, 
with a value of <%= x %>.

x.jsp output - The result of a call to x.jsp
<head>
<title>A simple thing</title>
</head>
<body>
<!-- this comment gets all the way to the browser -->


The value of x is 5.
The value of x + 2 is 7.
Is x
less than 6?

Yes, it is true that x is less than 6,
with a value of 5.
</body>

Importing Java packages

Usually when making a JSP the developer draws on classes from various packages. Unless these packages are imported, the use of such a class must include the fully qualified class name:

<%
java.util.Date d = new java.util.Date();
%>

Packages can be imported with the import attribute of the page directive. Multiple packages are seperated with a comma:

<%@ page import="java.util.*, example.*" %>
<%
Date d = new Date();
%>

Custom tag libraries

Custom tag libraries are a mechanism that allows developers to make functionality available to a JSP author through the use of XML tags.

As an example, a mail tag can be implemented and then used in the JSP in the following manner:

HogwartsRegistrationMail.jsp - an example usage of a taglib
<mail:mailMessage 
  from="registration@hogwarts.com" 
  to="<%= userEmail %>" 
  subject="Hogwarts Registration">

Thank-you for registering with the Hogwarts news service.  We will be sending
you an email with twice-weekly with updates and the latest news from Hogwarts.

</mail:mailMessage>

Tag libraries can be very useful, however they are somewhat complicated to implement. They are probably best left to developers of libraries -- the taglibs can provide some simple access to the functionality of the library.

More information on implementing custom tag libraries is in the JSP section of the Resin documentation.

Filter

From the Servlet Specification 2.4:

A filter is a reusable piece of code that can transform the content of HTTP requests, responses, and header information. Filters do not generally create a response or respond to a request as servlets do, rather they modify or adapt the requests for a resource, and modify or adapt responses from a resource.

A Filter is a Java class that is used to intercept the request and the response ("request" and "response" are discussed later). A filter can intercept the request before it get's to other web components, such as a JSP or Servlet, and change what the request looks like. A filter can intercept the response that is generated by web components, such as a JSP or Servlet, and change (transform) the reponse before it is sent to the client.

More information on the usage of Filters is available in the Servlets and Filters section of the Resin documenation.

Custom java code

A developer can, and usually does, use the general facilities of Java to create custom Java classes that are used by the Servlets, JSP, Filters, and other components of the web applications. Java source files are placed in the WEB-INF/classes/ directory (for example, WEB-INF/classes/com/hogwarts/Util.java, and are automatically compiled by Resin.

Java code libraries

A web application can take advantage of java code libraries. These libraries are usually packaged in a .jar file, and placed in the WEB-INF/lib directory (for example, WEB-INF/lib/batik.jar). The libraries in the jar file are then available to the Servlet, JSP, Filter, and other components of the web application.

Jar libraries usually contain code that is not specific to the web application, for example a library that provides a database driver, or a library that is used to generate images.

The structure of web applications

The componets of a web application are placed in appropriate files and configured using the WEB-INF/web.xml file.

Directory structure

Web application directory structure
FileDescription
/index.jspA jsp file that is usually the default file that is accesed
/WEB-INF/web.xmlThe file that configures the Web Application
/WEB-INF/classesA directory containing classes specific to this application
/WEB-INF/classes/com/hogwarts/foo/Util.java 
/WEB-INF/classes/com/hogwarts/foo/Util.class 
/WEB-INF/libA directory containing jar files
/WEB-INF/lib/mysql-connector-java-3.0.9-stable-bin.jarAn example usage of the lib directory, the MySQL driver

For the most part, the directory structure of a web application reflects the structure that the end-user will see from their browser.

In addition, a special directory named WEB-INF is recognized by Resin.

This directory contains a WEB-INF/classes sub-directory which is where you put any Java classes that are specifically for your application.

There is also a WEB-INF/lib directory which can contain .jar files for libraries that are needed by the application. These .jar files are usually third-party libraries or libraries that are reused amongst many different web applications.

Finally, the file WEB-INF/web.xml is used to configure your web application.

web.xml

A Web Application is configured with a deployment descriptor that collects information about the JSP pages, Servlets, security zones, and other resources used in the Web Application.

A full description of it can be found in the JSP specification.

A note about path seperators

In the web.xml file (and in Java programming in general), always use "/" as the path seperator. Do not use the MS-DOS/Windows "\" path seperator.

Automatic compilation

A convenience that is provided by Resin is the automatic compilation of Java files that are changed.

You can take advantage of this by placing your java source files in the WEB-INF/classes/... directory of your web application.

For example, if you have a file Util.java, in package com.hogwarts.foo, place the file in WEB-INF/classes/com/hogwarts/foo/Util.java. Now any changes to Util.java will result in the automatic recompilation of the java file into a class file.

Lifecycle: ServletContexts, Sessions, Requests, Responses

ServletContexts, Sessions, Requests, and Responses have corresponding java objects that Resin creates. Each of these objects has a unique scope: they are created at a certain time and destroyed at a certain time.

The JavaServer Pages specification inherits from the Servlet specification the concepts of ServletContexts, Sessions, Requests and Responses.

These objects are created by Resin, they are always available to a Servlet, Filter, or JSP page.

ServletContext

A ServletContext provides a view of the application that the Servlet, Filter, or JSP is running in. The ServletContext models the Web Application. A ServletContext is an object that is common to all Servlets in an application.

A ServletContext is represented by a class javax.servlet.ServletContext object.

Scope of the ServletContext

Resin creates a ServletContext as soon as the Web Application is started, and it remains until the Web Application is closed. There is one ServletContext made for each web application, and any usage of the ServletContext will always use the same one.

Request and Response

Every time a user follows a URL that points to a Servlet or JSP within the Web Application, Resin creates a Request object to represent the current request. Resin also creates a Response object which the developer can use to set certain things that apply to the response to the users browser.

A request is represented by a class javax.servlet.http.HttpServletRequest object. A response is represented by a class javax.servlet.http.HttpServletResponse object.

Scope of the Request and Response

A new Request and Response are created each time the user follows a link into the Web Application. These objects last until the response is sent back to the client.

Session

A Session is established for each user of the web application. The first time a user accesses anything within the web application, Resin recognizes this unknown user and creates a new Session to represent them. This Session object will remain the same for that user for the duration of their use of the web application.

A session is represented by a class javax.servlet.http.HttpSession object.

Scope of the Session

The Session is created the first time a user access a component in the web application that requests the session. Resin sees the incoming request from a user and checks to see if it has a Session for that user. If it does not, it creates one. This session object will remain the same for that user.

The end of the session object is a bit complicated. Since Resin cannot tell the difference between when the user has stopped using the application and when the user is just taking a long time to do something, Resin must guess. Resin uses a time-out value to determine when it should assume that the user has gone away, it defaults to 30 minutes. What this means is that if a user has not accessed any resource in the Web application for 30 minutes the Resin will destroy the session object for that user.

A developer can also explicitly destroy the Session object, and that is discussed later.

How Resin keeps track of the Session

Resin establishes a session by giving the user's browser a unique id that is returned back to Resin with each new request. This is accomplished in one of two ways: using cookies or URL rewriting.

Cookies

Resin attempts to track the session of a user by sending the user's browser a cookie. This cookie contains a long string that Resin creates that becomes the id of the session.

URL rewriting

Sometimes Resin cannot establish a cookie, either because the user has disabled cookies in their browser or because the browser does not support them (as is the case with some HDML and WML browsers). If the cookie cannot be established then something called URL rewriting is used.

with URL rewriting, Resin rewrites every URL that it submits to the user so that it contains a portion ';jsessionid=id;'. Then for each incoming request the first thing it does is look for this parameter, and if it is available it knows a session has been established and it removes the jsessionid and uses it to find the users session object.

URL rewriting requires some assistance from the developer, which is discussed later.

Obtaining the ServletContext, Session, Request, and Response objects

Servlet

The Servlet implementation class usually obtains the ServletContext in the init() method. The request and response object are passed in the doXXXX() method. The request object is used to obtain the Session.

JSP

When translation of a JSP to a Servlet occurs, there are some variables that are automatically defined. These variables can be used within any Java code that is inserted in the page.

Implicit Variables in JSP
VariableClassDescription
responseclass javax.servlet.HttpServletResponse Assists in sending a response to the client. Includes the ability to set the HTTP response headers.
requestclass javax.servlet.HttpServletRequest Provides client request information including parameter name and values from forms and the HTTP headers that the client sends.
sessionclass javax.servlet.HttpSession Provides a way to identify a user across more than one request and allows the developer to store information about that user (but see below).
applicationclass javax.servlet.ServletContext Every Web Application gets a ServletContext when it is started. It contains information and attributes that apply to the whole application.
configclass javax.servlet.ServletConfig The ServletConfig for this JSP page
pageContextclass javax.servlet.jsp.PageContext A variable specific to JSP (not available to servlets). It contains a number of convenience functions for use in a JSP page.
outclass javax.servlet.jsp.JspWriter An Object that is used to write into the output stream

Obtaining the session in JSP

With JSP, the page directive is used to indicate that the JSP needs the session object. When the page is executed, and has indicated that the session is needed, a session will be created for the user if it has not already and the session variable will be made available.

<%@page session="true">

The default for session is true, which is convenient for pages that need the session, but creates an undue burden on the server if the page does not need the session. Therefore it is best to mark all JSP pages with session="false" unless they really do need the session.

<%@page session="false">

Attributes

Each of the objects application, session, and request can have attributes. These attributes consist of a name and a value.

Using attributes the developer can store a value for later retrieval.

The name is a String that uniquely identifies the attribute, and the value is a Java object.

The API for setting and getting attributes

The following methods are available for the application, session, and request objects.

API for attributes
MethodDescription
getAttribute(String name) Return the Object that is associated with the passed name. Usually you will need to cast the Object to whatever class you know it to be. If there is no attribute with the given name, null is returned.
setAttribute(String name, Object value) Associates the given name with the value. If an attribute name already exists, it is replaced.
removeAttribute(String name) Removes the attribute with the given name if it exists.

Choosing where to put attributes

As a developer you have a choice of which object to store attributes in. The object that you choose should be appropriate to the scope within which you will need to get that value out again.

Whenever possible put the attribute in the request object. If that cannot work, put it in the session object. And very rarely, put values in the application object.

The reason for this order is simple, all of the attributes in a session cannot be garbage collected until they are explicitly removed or the session expires. All of the objects in the application stay until they are explicitly removed or the web application is stopped or restarted.

Using the Response object

Encoding the URL

Probably the most important and most frequent usage of the response object is to rewrite the URL. Recall from earlier that in order to maintain the identity of a Session with the user Resin may have to add a special parameter to every URL. The developer must co-operate with this, using the response.encodeURL method.

Because of this, it is a good idea to form a String for every URL you will use in a page and store it in a variable:

EncodingUrls.jsp - Encoding the URL's and storing them in a String variable
<%
    String boatUrl = response.encodeURL("water/boat.jsp");
    String goatUrl = response.encodeURL("animals/goat.jsp");
%>

<%-- the presentation --%>

Hello, would you like some green eggs and ham?
Would you, could you, on a 
<a href='<%= boatUrl %>'>boat</a>?
Would you, could you, with a
<a href='<%= goatUrl %>'>goat</a>?

This has the added benefit of placing all of your URL's in one place, allowing you to change them more easily.

Redirecting the users browser

Sometimes it is desirable to send a redirect to the client. This is a response to the client that tells it to go to some other URL. This is often used by developers so that the URL in the browser makes sense to the user. It is however, a slow procedure because it requires a response to go all the way back to the browser, and then the browser will make a new request.

The redirect is accomplished by using the response.sendRedirect() method. Again, the URL must be encoded, and a special kind of encoding is needed for a redirect:

Redirect.jsp - an example of redirecting the client
<% 
   String redirectUrl = 
     response.encodeRedirectURL("elsewhere.jsp");

   response.sendRedirect(redirectUrl);
%>

A note on redirecting wireless devices

Redirects often do not work with wireless devices like cell phones and WML clients, and the emulators of these devices. As well, the latency of a wireless connection compounds the speed problem of using redirects. Redirects should probably be avoided with wireless devices.

Setting the content type dynamically

As mentioned eariler, the <%@ page contentType="..." %> directive can be used to tell the browser the type of content that it is getting.

The page directive method does not allow you to do this dynamically. You can instead use: response.setContentType("...") to set the content type.

Telling the browser not to cache the page

Often it is necessary to inform the browser that a page should not be cached - the browser should ask for a new copy of the page every time. The best way to do this is by setting appropriate HTTP headers in the response to the browser.

Unfortunately, all the browsers work differently. The following seems to be a consensus on the headers to set:

nocache.jsp - Stop the browser from caching the page
<%
/** stop browser from caching */
response.setHeader("Cache-Control","no-cache,post-check=0,pre-check=0,no-cache");
response.setHeader("Pragma","no-cache");
response.setHeader("Expires","Thu,01Dec199416:00:00GMT");
%>

Telling the browser that the page is private

A little known fact is that it is necessary to inform the browser with certain pages that they are private pages, meaning they should never be seen by anyone except the current user.

This applies to any pages that the user has needed a password to get to.

private.jsp - Telling the browser the page is private
<%
/**
 * Add an HTTP header to the response that 
 * indicates to the browser and any
 * intervening cache's that this is a private 
 * page, and should never be seen
 * by a different user.
 */
response.addHeader("Cache-Control","private");
%>

Using the Request object

Retrieving the values set in form fields

The main use of the request object is to get the values that a user has supplied in a form submit. For example, with this HTML on page a.jsp:

a.jsp - a form that submits a value
<% 
    String bUrl = response.encodeUrl("b.jsp");
%>

<%-- presentation --%>

<form method="post" action="<%= bUrl %>">
What is your favourite kind of eggs?
<input type="text" name="favegss" size="25">
<br>
<input type="submit" value="Submit">
<input type="reset" value="Reset">
</form>

The value that was supplied in ``eggs'' can be retrieved with:

b.jsp - retrieving a value from a form submit

<% 
    String aUrl = response.encodeUrl("a.jsp");
%>

<% 
    String faveggs = request.getParameter("eggs"); 
    if ((faveggs != null) && (faveggs.trim().length() == 0))
        faveggs = null;
%>

<%-- presentation --%>

<% if (faveggs == null) { %>
No eggs supplied!
<a href="<%= aUrl %>">Try again</a>
<% } else if (faveggs.equals("green"))  { %>
Of course we have <%= faveggs %> eggs! 
It's one of our favourites too.
<% } else { %>
We do not have <%= faveggs %> eggs.
<% } %>

Using the Session object

The Session object is used primarily to store two types of information. The first is information about the user, and the second is data that is built up and used over multiple pages. A classic example of information you would store in a session is user profile information, or a shopping cart that is filled up over many pages.

It is important to try to limit the amount of information that is stored in the session object.

Explicitly causing the session to end

The session object will go away if the user is inactive for a certain time (usually 1/2 hour). You can also explicitly destroy the session, which you may want to do for example if the user chooses to logout.

This is accomplished with: session.invalidate();

Doing something when the Session goes away

It is possible to add a hook so that something can be done when Resin decides that a Session has expired, or the Session is explicitly destroyed.

To accomplish this, you write a class that implements the class javax.servlet.http.HttpSessionBindingListener interface. Then you register this class with the session simply by putting it as one of the attributes. The Session will notify all of it's attributes that implement class javax.servlet.http.HttpSessionBindingListener .

SessionBind.jsp - An example of getting notification when a Session is destroyed
<%@page import="example.SessionListener" %>

<%
    // example.SessionListener implements HttpSessionBindingListener 
    SessionListener d = new SessionListener();
    session.setAttribute("sessiongoesbyebye", d);
%>

Warning! One session does not mean one browser window!

It is important to realize that the user can have multiple windows open that use the same session. If the user uses the "Open in new Window" functionality of a browser, they will have two windows open and the Web Application will see them both as belonging to the same session. This has some ramifications on how the Session can be used for shopping-cart like applications.

For example, let's assume that an application uses the Session attribute "cart" to store shopping cart information about different types of juice a user has chosen to purchase.

The user may start one juice buying transaction and get to the confirmation page, having 3 grape and 2 apple in their cart. Now, what happens if at this point they use another browser window to initiate another purchase? If the Web Application is using the Session to store shopping cart information then the second window may destroy the contents of the shopping cart, so that if the user finishes the first window they end up buying nothing!

A possible solution for this is to keep a version counter in your cart. Every time the cart is changed, the version counter is updated. Then, when your application shows the "confirm purchase" page (the next action will cause the purchase to occur), it sends the version counter to the "confirm purchase page". The "confirm purchase" page submits that version counter as a parameter. The application can check the submitted version counter, and the current version counter in the shopping cart - if they are different then the cart has been modified in some other way, and a message is returned that the purchase did not occur because the cart had been modified elsewhere.

Error Handling

JSP Translation Time Processing Errors

Some errors may occur at JSP translation time. This could be, for example, from an error in the syntax of some Java code in your JSP. You will usually see this error in your browser the first time you try to access the page. Resin can also put the error in log files.

From the JSP specification:

The translation of a JSP page source into a corresponding JSP page implementation class using the Java technology by a JSP container can occur at any time between initial deployment of the JSP page into the runtime environment of a JSP container, and the receipt and processing of a client request for the target JSP page. If translation occurs prior to the JSP container receiving a client request for the target (untranslated) JSP page then error processing and notification is implementation dependent. Fatal translation failures shall result in subsequent client requests for the translation target to also be failed with the appropriate error; for HTTP protocols, error status code 500 (Server Error).

Coompilation Time Processing Errors

Some errors may occur at the time a Servlet or other source file is being compiled by Resin. This could be, for example, from an error in the syntax of the Java code. You will usually see this error in your browser the first time you try to access the page. Resin might also put the error in log files.

Client Request Time Processing Errors

Java handles runtime errors with exceptions. If an exception is not caught in your JSP or Servlet, Resin will use a special error page to send results back to the browser. Resin uses a default error page unless you explicitly provide an error page yourself.

From the JSP specification:

During the processing of client requests, arbitrary runtime errors can occur in either the body of the JSP page implementation class or in some other code (Java or other implementation programming language) called from the body of the JSP page implementation class. Such errors are realized in the page implementation using the Java programming language exception mechanism to signal their occurrence to caller(s) of the offending behavior 1 . These exceptions may be caught and handled (as appropriate) in the body of the JSP page implementation class.

However, any uncaught exceptions thrown from the body of the JSP page implementation class result in the forwarding of the client request and uncaught exception to the errorPage URL specified by the offending JSP page (or the implementation default behavior, if none is specified).

The offending java.lang.Throwable describing the error that occurred is stored in the javax.ServletRequest instance for the client request using the putAttribute() method, using the name javax.servlet.jsp.jspException. Names starting with the prefixes java and javax are reserved by the different specifications of the Java platform; the javax.servlet prefix is used by the Servlet and JSP specifications. If the errorPage attribute of a page directive names a URL that refers to another JSP, and that JSP indicates that it is an error page (by setting the page directive's isErrorPage attribute to true) then the exception implicit scripting language variable of that page is initialized to the offending Throwable reference.

Architecture

There are many ways to use the capabilities that are offered by JSP -- different models apply to different applications.

Simple JSP

The simplest model is to use JSP as an add-on to existing web pages. At the top of each page is the Java code that is necessary for the display of the page, and at the bottom is the markup that is to be output, with appropriate insertion of any dynamically generated variables.

Note the seperation of the different logical parts. It is a very good idea to keep the presentation section as Java-less as possible. Setup all of the values in the logic part, and then use only simple <%= var %> and if statements in the presentation part.

SimpleJSP.jsp - the logic and display code in one page
<%-- urls --%>

<%
  // store your target urls in String variables
%>

<%-- incoming parameters --%>
<%
  // store form values from the request object in variables
%>

<%-- logic --%>
<%
  // we all make decisions with logic, right?
%>

<%-- presentation --%>

<markup>
  <forthebrowser>
  </forthebrowser>
</markup>

This seems like a sensible approach. However, imagine that later it is decided that a different set of HTML is needed for the output if there is no news available. As well, support of WML output is required. Now we need to put the display code for 4 different types of output into one page. Maybe we need to go to different places as well, for example an administrator might get a different display page, or we need to check the users profile to see what is apporiate to display. This is too much complication to put all in one place.

This type of implementation, because of it's limitiations and it's inability to change without exponentially increasing the complexity, should be avoided.

Seperating the logic into another JSP

To address some of the disadvantages of the Simple JSP method, it is possible to seperate the `logic' and the `presentation' into two different JSP files.

In this model, instead of a link pointing directly to the page that does the display, it points to a page that handles the incoming request. This 'logic' page contains the Java code that is responsible for preparing the values that will be used for displaying. It stores these prepared values as attributes of the request object, and then forwards to the appropriate display page. The display page then pulls the information it needs out of the request object and displays it.

SeperateJsp.jsp - The logic JSP that prepares the data for display

<% 
/** -- incoming parameters -- */
     String strJuiceType = request.getParameter("juiceType");
     String strQuantity = request.getParameter("juiceQuantity");

/** -- logic -- */
Double cost;
String strCost;

here we might do a check to make sure mandatory fields
have values.

Here we might do a database lookup to determine the price, and
set the cost value to the price * quanitity

Now we might format the cost double into 
a two-decimal number and store it in strCost

/** -- set outgoing parameters
    -- forward to display page -- */

/** note that here we put juiceType in as a request
    attribute, even though the display page could get
    it from the request parameters. This helps us keep
    the interface between the logic and the presentation
    cleaner */

request.setAttribute("cost", strCost);
request.setAttribute("juiceType", strJuiceType);
request.setAttribute("quantity", strQuantity);

if (isWML)
    pageContext.forward("SeperateJspPresentationWML.jsp");
else
    pageContext.forward("SeperateJspPresentationHTML.jsp");
%>

SeperateJspPresentationHTML.jsp - The JSP that presents the prepared information in HTML format
<%-- urls --%>

<%-- prepared objects --%>

<%
String cost = (String) request.getAttribute("cost");
String juiceType = (String) request.getAttribute("juiceType");
String quantity = (String) request.getAttribute("quantity");
%>

<%-- presentation --%>

Hey, if you want <%= quantity %> bottles of 
<%= juiceType => juice, it is going to cost
you $<%= cost %>

Here we have introduced a new thing: pageContext.forward.

pageContext.forward

The pageContext.forward(String url) forwards the processing to a different JSP page. That is, it passes control over to another page. This page is then executed, inheriting the current request and response objects. It is important that this is the last thing that a JSP page does.

Seperating the business logic into beans

Even the seperation of all logic into a different JSP can get a bit muddled. You can seperate the `logic' into two types of logic, business logic and presentation logic.

Presentation logic is logic that is part of the presentation. Examples are form validation and formatting of numbers into strings.

Business logic is programming that involves your data. If you can separate something in your mind from the presentation, it doesn't depend on the presentation in any way, that's business logic. Examples are database lookups and shopping cart manipulation.

Your application will be cleaner and easier to manage if you put your business logic in Java classes (beans) which hide the complexities. You then use these classes in the logic.jsp.

Model 2 (preferred)

The final approach discussed here is called the `Model 2' approach. This approach requires a level of sophistication that is usually not warranted unless you use a library that supports it, however it is the cleanest way to implement an application.

In this approach there is a special Servlet called a controller servlet. The controller maps an incoming request to a Java class that takes care of all of the 'business logic'. This Java class returns a result that indicates to the controller where it should go next. The controller then dispatches to the appropriate place.

The flow of a request moves through these `business logic' pieces, finally ending up at a `view'. The logic pieces are responsible for examing the submitted information (such as parameters from forms), managing logical flow, and preparing objects for the view. The objects for the view are stored as attributes of the request (or sometimes, the session).

The view is responsible for preparing a response for the user using the prepared objects now available as request or session objects. This is where JSP is often used, it works very well as the view component of a Model 2 architecture.

The developer tells the controller what the flow for each request is by specifying it an external (usually XML) file.

This approach is by far the cleanest approach to using Servlets and JSP. Most applications of any significant complexity use a Model 2 architecture.

Security

JSP inherits the Servlet security mechanism. Using the two fundamental concepts of Principals and Roles, JSP provides declarative and programmatic security.

In addition, there is builtin support for various HTTP methods of login that establish a Principal and it's Roles based on a user login and password.

Principals

A Principal is established in association with a Session. There is a one to one correspondence between the two. Usually the Principal is a user, a real live honest to goodness person sitting at a computer somewhere and accessing the Web Application.

The Application may require that the User go through a login process, a successful login will establish a Principal, which will have a certain set of Roles.

Roles

Servlet 2.2 Specification states: A role is an abstract logical grouping of users that is defined by the Application Developer or Assembler. When the application is deployed, these roles are mapped by a Deployer to security identities, such as principals or groups, in the runtime environment.

Roles are similar to groups in Unix security. As an example, you might have a "member" role for users who have a membership, and an "admin" role for administrators.

Principals can have more than one role -- a user might be both a "member" and an "admin".

Declarative Security

Servlet 2.2 Specification states:

Declarative security refers to the means of expressing an application's security structure, including roles, access control, and authentication requirements in a form external to the application. The deployment descriptor is the primary vehicle for declarative security in web applications.

Basically what this means in real terms is that you can specify certain paths in web.xml that require certain roles. For example, you can say that to access any page in the "/accountsetup/" subdirectory, the user must have a role of "admin".

Programmatic Security

Servlet 2.2 Specification states:

Programmatic security is used by security aware applications when declarative security alone is not sufficient to express the security model of the application.

Programmatic security lets you decide in some Java code what to do, based on the role that a user has. For example, you might make a certain button appear in the button bar only for an "admin" user.

Programmatic Security API
MethodDescription
request.getRemoteUser() return the name of an authenticated user.
request.isUserInRole(String role) return true if the current user is in a given security role.
request.getUserPrincipal() return the class java.security.Principal associated with the current user.

When does Resin require a login?

The resources in an Application are by default open to the public, and do not require a login. As soon as the User attempts to access a resource that has been declared to require a role in the web.xml, Resin will insert in the process a login of some kind before continuing on to the resource that was originally requested.

For example, if the "/members/*" area has been declared to require a "member" role, as soon as the user tries to access anything in "/members/" Resin will check to see if the user has logged in yet. If the user has logged in, then the roles for the user are checked to see if "member" is a role that user can take. If the user has not logged in, Resin inserts a login procedure and then checks the roles.

The login procedure

The Servlet Specification details numerous methods for getting user identification and password information from the user.

The example below shows usage of "Form Based Authentication", which allows you to specify a login page to be sent to the user when needed, and an error page that will be displayed if the user login fails.

The login page should submit a form to the url j_security_check with the parameters j_username and j_password set to appropriate values.

Resin recognizes the special url j_security_check and authenticates the username and password.

Lifecycle of a Principal

The Servlet authentication associates a principal with a session. The principal will only last as long as the Session; as soon as the Session is gone then the user will no longer be logged in.

As a result, invalidation of the Session will also cause a logout:

session.invalidate();

You can also cause a logout without invalidating the whole Session. Other objects in the session will remain available but the principal will be null:

session.logout();

Authenticating the User

Once the user information is collected, the password must be verified and the roles determined. Unfortunately, the Servlet specification does not indicate a standard way for this to occur.

What that means is that every Container is likely to do this differently, and you will have to refer to Container specific documentation and examples.

Example usage of Security

The Resin documentation on Security includes a comprehensive discussion, and the Basic Security Tutorial is a good starting point as well.


Web Applications
Web Applications
Deploy
Copyright © 1998-2006 Caucho Technology, Inc. All rights reserved.
Resin® is a registered trademark, and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc.