Programming a servlet is not really different from programming other applications. We do provide a sample servlet, which shows how to combine them programmatically. In this article two common issues that often come up with servlets are dealt with; using a session pool and classpath issues.
The information in this section only applies to
Summary of this article:
When possible, place all
tomcatDir/common/lib (and not in WEB-INF/lib of
individual servlets), replacing the Xerces jar with the one
included with
tomcatDir/common/endorsed directory, it is best
to place xercesImpl.jar and xml-apis.jar
and xalan.jar in the common/endorsed
directory instead of the common/lib directory. In fact,
because of a bug in Tomcat (see below) it is obligatory currently to
put xml-apis.jar there, to use the endorsed overriding scheme.
In concurrent situations, it gives a great performance boost to use sessions in read-only mode where possible. Use a session-pool to share sessions between requests in different threads, to limit the number of sessions created. A sample session pool is included with the sample servlet.
Don't use Tomcat 4.0.x, use later versions. Tomcat is a fast evolving program, different versions have different properties, especially in the area of classloading.
The information in this section applies mostly to the Tomcat servlet engine. It is about how to how to set up a classpath, specifically how Tomcat deals with this. It does not explain fully how the Tomcat classloader system works, please see the Tomcat documentation for this.
In Tomcat, like other servlet engines, the proper way to deal with the classpath is to create a
WEB-INF/lib directory for your servlet and copy all the jars to
this directory.
This is what is advised in the servlet specification. It is also where jars are placed if
an application gets unpacked from a .war file. However, there some serious
downsides to placing the
WEB-INF/lib:
The classloader that loads classes for jars located in the WEB-INF/lib
directory has certain special conditions. Specifically, the specification indicates
it may not load classes from certain packages. This can give problems in that it might
cause classes which are available in multiple jars to be loaded partially from one jar
and partially from another jar. In other words, if you place the
WEB-INF/lib of specific servlets, you should ensure not to place the
same or conflicting jars in common/lib.
If you have multiple servlets running within one Tomcat environment. There
will be one classloader per servlet running.
This will lead to multiple drivers being initialized when you connect, which means
that you can only do this if you have an external (dedicated) server running (in simpler terms,
when all the servlets connect to the datbase through an xhive://hostname:portnumer
URL). If you do decide to deploy xhive.jar in multiple directories, you must also
ensure that they all use different session-pools, no objects may be shared between servlets.
The requirement of not having a dedicated server can be important, because as described in the performance chapter of the manual, running without a dedicated (external) server will give a great performance boost to your applications.
If you want Tomcat to automatically reload servlets when they are changed (recompiled), you can turn on 'reloadable=true' on the servlet context in server.xml (consult the Tomcat documentation for this) (or you can also redeploy servlets). However, for each reloading/ redeploying action a new classloader is created, and this will thus has the same issues as described before.
tomcatDir/common/lib.
Jars in this directory are shared between all servlets. The classloader
which loads the classes from this directory does not unload classes, which means
the JNI library will not be loaded multiple times. Here follows a list of jar placement
tips:
When you want to run a servlet using the
lib subdirectory of
your
tomcatDir/common/lib.
If your Tomcat version also has a tomcatDir/common/endorsed directory,
it is best to place the following
common/lib if you are using JDK 1.4: xercesImpl.jar,
xalan.jar and xml-apis.jar. The reason for this is
that putting the jars there will mean they override the XML-classes that come with
JDK 1.4. For Xalan a lot of bug-fixes were applied since the version
that ships default with the JDK. For Xerces it means that the DOM Level 3 interfaces
are used. For almost every serious
Tomcat comes with its own version of Xerces (in xercesImpl.jar or
xerces.jar). You should remove those jars and replace them with ours. The reason
to use our jars instead of Tomcat is that we make more demanding use of those jars (Tomcat
only really uses them to load some configuration files, which will work with just about
any parser implementation).
One thing to make sure of is that the same jar is not duplicated in multiple directories
of Tomcat. Specifically, if you place the
When using Tomcat 4.1.x, download/ use the LE version when possible. The LE editions
of Tomcat only work with JDK 1.4 and ship with fewer jars, specifically xercesImpl.jar
is not included. This means one less jar to worry about, and JDK 1.4 is a requirement
for
Because the classloading issues described can sometimes lead to confusing exceptions and
error messages, we will list some common ones and their causes here. These errors
may be shown in your webbrowser accessing Tomcat, on the console of the running
Tomcat process, or in the file tomcatDir/logs/localhost_log.<date>.txt:
Load of library: oojava failed java.lang.UnsatisfiedLinkError
You are using
java.lang.VerifyError: xmlDecl signature: Illegal use of nonvirtual function call
Means that there is an older version of Xerces somewhere in
the classpath. Be sure to remove the existing xerces.jar from
tomcatDir/common/lib when you copy the
java.lang.ClassNotFoundError: some org.w3.dom class not found
Means that you have not placed our xml-apis.jar in the endorsed directory, and the DOM Level 3 interfaces cannot be loaded (because of a bug in Tomcat).
org.apache.xml.utils.WrappedRuntimeException: The output format must have a '{http://xml.apache.org/xslt}content-handler' property!
This error is usually caused by the Xalan included with JDK 1.4. Make sure xalan.jar
is placed in tomcatDir/common/endorsed (if you run into this error and there
is no such directory, we advise you to upgrade to a newer version of Tomcat).
It should be noted that although the creation of sessions in
In the sample servlet we create a stack of sessions,
from which sessions are taken and returned when needed.
Each time a session is used a connection is made on it
and a transaction is opened. In this way the session
pool can be used in a generic way. You can use this mechanism too
in your applications. As the goal of the
pool is to increase the responsiveness, we describe
three possible ways to increase the reaction speed and explain the merits
of each one. Only the first
tip on read-only sessions can lead to great improvements of
the performance of your system with
When you can determine at the start of a request that that request does not have to make changes in the database (e.g. you can make out from the request-URI that it is a request that will involve an XQuery and stylesheet transformation), you can use a readonly transaction. These have the advantage that A) the request itself does not have to wait for locks of other concurrent transactions and B) that other transactions do not have to wait for locks taken by this transaction. Because of this double effect, the performance gain of using read-only transactions when possible should not be underestimated. When using a pool of sessions, you can still set the readonlymode of the session before each transaction begin.
If you always connect to the same database as
the same user in your application, you can
choose to already connect on each session
when you create the pool (our session pool
has the method connectAs for
this purpose). The overhead of a connect is not
very large though, roughly comparable to the retrieval
of one tiny document through an index.
In previous releases we sometimes recommended to not commit
the transaction for every request, but for