ONJava.com -- The Independent Source for Enterprise Java  
oreilly.comSafari Books Online.Conferences.

Using App Server-Specific Functionality on Multiple App Servers

by Tom Stamm
Content provided by BEA Systems

When designing an application to run on a J2EE compliant application server, it is usually a good idea to stay within the boundaries of the J2EE specifications that are supported by that app server. However, sometimes it is necessary to go beyond the specs, and use functionality that is app server-specific. The drawback is that this makes it difficult to port your application to a different app server. This article will discuss an example of when you might need to go beyond the J2EE servlet specification, and how to do so in a way that will work across multiple app servers.

The Problem

WebLogic Page Flows provide a framework built on struts/JSP that uses annotations in java code to define the flow of a webapp. Some of this functionality, particularly in the area of security, depends on internal WebLogic classes. In order to make the Portable Page Flow development kit, we needed to create a mechanism for providing as much of this functionality as possible on Tomcat, and to enable the framework to fail gracefully when something was simply not supported. It is also important to do this transparently, so that the page flow runtime would not need to know what servlet container it is running in. To see this in action, download the Portable Page Flow kit and run the example page flows under Tomcat.

The specific example I will show here is doing a programmatic login in a page flow, given a username and password. There is no way to do this in a way that is strictly compliant to the J2EE servlet specification, however, the ability to login a user must exist somewhere in a servlet container, it is just a matter of learning where, and figuring out how to expose it. In a situation like page flows, we needed to do this in a way that could easily scale to other app servers without major code changes.

The Solution – An Adapter Layer

To accomplish this portability, we created an adapter layer. This consists of an interface that defines the functionality used by page flows that is not exposed in the servlet specification:

public interface ServerAdapter
    public void login( String username, String password, 
HttpServletRequest request )
        throws LoginException;

For this example, the interface defines a “login” method, that takes a username, password, and HttpServletRequest; and will authenticate the given username/password combination, and make that user the “current” user; or throw a javax.security.auth.login.LoginException if the username/password combination is not valid. This interface can now be implemented for each specific server that needs to be supported by the web application.

When the webapp wants to call this method, it still needs to know which implementation to use. This can be solved using a factory pattern, by creating a utility class that knows how to look at the environment and instantiate and return the correct implementation. The goal of Portable Page Flows is to provide as much functionality as possible on Tomcat, and to enable page flows to run in a limited manner on other servlet containers. To accomplish this, we created a default implementation of ServerAdapter that basically does a no-op on all methods; a tomcat implementation that implements most of the methods; and a weblogic implementation that implements everything. (For details on what is supported, see the Portable Page Flow documentation) A factory method in a utility class creates the correct server adapter by looking first at a system property to see if one was specified explicitly, and then at various environment variables that would identify a WebLogic or Tomcat server.

Getting Past J2EE

The next problem is accessing the internal workings of other servers. In Tomcat’s case, there is a very strict classloader hierarchy that makes it impossible for a class in a webapp to access a class in the server core that is not exposed through the servlet API. (For a thorough description of how this works, see http://jakarta.apache.org/tomcat/tomcat-5.0-doc/class-loader-howto.html) There is a system classloader that is a parent to a common classloader, and the common classloader is a parent to both the Catalina and webapp classloaders. The internal security functionality lives in Catalina, so it is not accessible to a webapp that is loaded by the webapp classloader.

To get around this, we created an interface, PageFlowHelper, that mirrors the ServerAdapter interface, and lives in the common area. An implementation of this interface that knows how to use the Catalina internal classes lives in the server area, PageFlowHelperImpl, which is loaded by the Catalina classloader. So now we have an interface that the webapp can get to, and an implementation of this interface; but we still have the problem of getting the implementation to the webapp.

A non-J2EE feature of Tomcat is the notion of "valves". This basically allows you to setup a "pipeline" of classes that are invoked in order when a request is received. Each valve can do whatever it wants to the request, and can pass execution to the next valve, or halt execution if it needs to. The Portable Page Flow kit provides a valve implementation that, on each request, places an instance of PageFlowHelperImpl and places it in a well-known location in the request:

// Initialize pageflow helper – the request and response that we have 
//    inside the valve are actually internal
// Catalina classes that wrap the “real” HttpServletRequest and 
//    HttpServletResponse

HttpServletRequest hreq = (HttpServletRequest) request.getRequest();

PageflowHelper helper = new PageflowHelperImpl();

// The helper keeps a handle to the internal request/response pair 
//    and the valve itself

((PageflowHelperImpl)helper).initRequest( (HttpRequest)request,
                                          (HttpResponse)response, this );

hreq.setAttribute(PageflowHelper.PAGEFLOW_HELPER_KEY, helper );

The Tomcat implementation of the ServerAdapter can now retrieve this from the request (as a PageFlowHelper) and delegate to it. Now, inside a Page Flow, calling PageFlowUtils.getServerAdapter().login( username, password, request ) in a Tomcat server will retrieve the TomcatServerAdapter, which will retrieve the PageFlowHelper from the request, and invoke the login method on it; which allows the Page Flow to access internal Tomcat functionality across classloader boundaries, without needing direct access to classes outside of the servlet specification.


The J2EE servlet specification provides a lot of functionality, but it also leaves out a lot of things that are useful in "real-world" applications. Where possible, it is usually safer to stick to the spec, especially for applications that need to run on more than one container. However, in cases where you need to use functionality that is not in the spec, there is usually a way to create a scalable solution that is reasonably transparent to the rest of your application. Most servlet containers have a lot of functionality that is hidden from the webapp environment, but is used by the system itself, and is generally accessible with some creative classloading.

Tom Stamm is a software developer on the Page Flow team at BEA Systems.

Return to ONJava.com.