Using App Server-Specific Functionality on Multiple App Serversby 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.
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:
For this example, the interface defines a “login” method, that takes a username,
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
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
To get around this, we created an interface,
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
The Tomcat implementation of the
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.