Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Avoiding ClassCastExceptions due to Xerces Libraries within Web Modules on WebSphere Application Server

Barry Searle (searle@ca.ibm.com), WebSphere Studio Development, IBM Toronto Lab
Photo of Barry Searle

Barry Searle is the Migration Team Leader for WebSphere Studio Application Developer. He is a Professional Engineer who has worked at the IBM Canada Lab for over ten years on various application development tools. Prior to that he had many years of industry experience developing command and control systems and leading communications development projects. You can reach Barry at searle@ca.ibm.com .

Ellen McKay (ecmckay@ca.ibm.com), IBM Toronto Lab, WebSphere Information Developer

Ellen McKay is an Information Developer for IBM Canada Ltd. She writes online help and publications for WebSphere Studio Application Developer. You can reach Ellen at ecmckay@ca.ibm.com

Summary:  WebSphere Application Server has run-time libraries of classes, including Xerces libraries, and sometimes ClassCastExceptions occur because utility EAR classes that use Xerces unexpectedly load Xerces classes from WAR modules. This article shows you how to avoid the problem.

Date:  22 Oct 2003
Level:  Introductory

Activity:  9501 views
Comments:  

Introduction

IBM ® WebSphere® Application Server has a run-time library of classes, including Xerces. Those classes are loaded by applications when their application classloaders delegate upward and use the WASext Application Server classloader to load them. WebSphere Application Server V5 has a hierarchy of classloaders and delegation modes (preference orders) that can be set for J2EE modules. You can use the classloader hierarchy and the PARENT_LAST delegation mode to build Web Archive files (WARs) or Enterprise Application files (EARs) that include their own specific version of common libraries, particularly the Xerces XML parsing classes. Normally, everything works as expected, but sometimes ClassCastExceptions occur because utility EAR classes that use Xerces unexpectedly load Xerces classes from WAR modules (which they should not be able to "see" or load), instead of from the EAR Xerces (if Xerces is included in the EAR) or from the default WASext run-time Xerces.

A typical scenario: a developer creates a utility class that uses Xerces and puts that utility class into a library JAR in one or more EARs. Another typical scenario involves a utility class that will be widely used throughout an enterprise and is therefore put into the ws.ext.dir for use by any application. The expectation is that an EAR utility class will use an EAR Xerces (if one is included in the EAR), or else will default up to the WASext run-time Xerces (since EARs can only see the EAR libraries or the default run-time libraries)

Various Web application WARs are then built, which sometimes include a specific Xerces within their WAR, and they set the PARENT_LAST delegation (so that their specific Xerces is used). However, when such a WAR uses your EAR (or WASext) utility class, that utility class creates a Xerces DOMParser (loading the WebSphere Xerces) and the DOMParser calls ObjectFactory.createObject, which switches to the contextclassloader to actually create the DOMparser object. This causes a ClassCastException error, since the resulting WAR DOMparseris not the same as the expected WASext DOMparser. Suddenly your utility class has switched to use the WAR Xerces instead of the WASext Xerces, even though that utility class was loaded by the EAR (or WASext) classloader and should not be able to see or load WAR classes.

What causes this problem, and how do you eliminate it? The answer is that some special coding is required in the utility class, the same as is done for all WebSphere run-time classes that use Xerces.


WebSphere Application Server V5 classloaders

There is, by design, a hierarchy of classloaders in WebSphere Application Server V5. The main ones we are interested in are:

WebSphere Extension Classloader 
^ 
^ 
EAR Classloader 
^ 
^ 
WAR Classloader 

There are two related concepts associated with classloaders:

Visibility
defines which classes are "reachable" -- that is, which classes can be loaded. Normally, visibility extends "up" but not "down". Therefore, any class loaded by a WAR classloader can also load classes using the EAR or WASext classloader, but any class loaded by the EAR (or WASext) classloader cannot subsequently load classes using the WAR classloader.
Delegation
defines the "preference" order of classloaders. In other words, it defines where to look first (and subsequently if necessary) to try to load classes. Within WebSphere Application Server V5, each J2EE module classloader has a setting (PARENT_FIRST or PARENT_LAST) that you can use to set the delegation mode for the EAR and WAR (but not for anything higher).

Building Web application WARs to use a specific Xerces version

When a Web application WAR is built to include and use a specific Xerces version, a specific server configuration is required. Follow these steps to set up that configuration:

  1. In WebSphere Application Server, open your WebSphere server configuration.
  2. Click the Configuration tab. In the Application classloader policy drop-down list, select MULTIPLE:

  3. Click the Applications tab and select your application (your EAR file). In the Classloader mode drop-down list, select PARENT_FIRST (or if you prefer, PARENT_LAST).
  4. Within that same Applications tab, move to the WAR classloader policy drop-down list and select MODULE, as shown below:
  5. Still within the same Applications tab, select your WAR file, and in the Classloader mode drop-down list, select PARENT_LAST, as shown below:
  6. Save your changes and close your server configuration.

When the Web application is running, the thread of execution comes from the servlet in the WAR. Any WAR classes that use Xerces will locate and load Xerces classes using the WAR classloader. Any WAR classes using WASext run-time classes will locate and load those classes using the WASext classloader (since the WAR does not contain those classes and its classloader delegates up to the EAR and then WASext classloader until they are found and loaded). Those WASext classes in turn can then only locate and load other classes using that same WASext classloader. This kind of isolation is intended (and desirable).

So far, everything is behaving as expected. However, a problem occurs if your WAR uses a utility class in your EAR file (or in ws.ext.dir).


The cause of the Xerces ClassCastException problem

The root cause of the problem is that J2EE requires that contextclassloader must always be the classloader of the currently executing J2EE artifact. Specifically, J2EE containers must provide a per thread contextclassloader for the use of system or library classes when dynamically loading and executing such classes.

Therefore the system library Xerces code calls Thread.currentThread().getContextClassloader() to switch and use the contextclassloader during its execution. In particular, when your utility class creates a DOMParser object, that class is initially found and loaded using the EAR classloader, which delegates to the WASext classloader (assuming there are no Xerces classes in the EAR libraries) to locate and load the WASext run-time Xerces DOMParser class (all as expected). That DOMParser constructor then calls ObjectFactory.createObject, but that method then switches to the J2EE artifact contextclassloader (the current WAR classloader), to construct (using getResourceAsStream) the actual DOMParser object. Unfortunately , the resulting DOMParser object is therefore a class from the WAR Xerces rather than from the original WASext (or EAR) Xerces, which causes a ClassCastException when it is returned from the DOMParser constructor.

In other words, when a utility class in a PARENT_LAST hierarchy constructs a WASext DOMParser, that DOMParser switches to the active J2EE contextclassloader, and it will fail trying to return an actual DOMParser object from the active contextclassloader (lower-level) WAR Xerces.


The solution

To work around this, your utility class code must:

  1. Get the currently executing thread contextclassloader and save it, as shown below:
    ClassLoader savedClassloader = Thread.currentThread().getContextClassloader();
  2. Set the contextclassloader to its own classloader, as shown below:
    Thread.currentThread().setContextClassloader( this.getClass().getClassLoader() );
  3. Invoke the Xerces parsing operations it needs to use
  4. Restore the contextclassloader, as shown below:
    Thread.currentThread().setContextClassloader( savedClassLoader );

By performing the above steps, your utility class can safely be in the classloader hierarchy above PARENT_LAST J2EE modules that include their own version of Xerces.

Whenever a WebSphere run-time class uses Xerces, WebSphere has to similarly modify all such classes to save the contextclassloader, explicitly use the WASext classloader to load Xerces and perform the parsing operations, and then restore the contextclassloader.


Similar problems

Here are some problems similar to the one described above:

  1. Commons-logging has the same run-time problem as Xerces, so any utility class that uses it can have PARENT_LAST ClassCastExceptions from WARs (containing a different version of commons-logging).
  2. A few WebSphere V5.0.0 run-time classes that use Xerces previously caused similar errors, but all known WebSphere V5 run-time problems have now been fixed in recent APARs or PTFs (using the solution described above). As of October 2003, the most recent PTFs and APARs related to this are V5 PTF-2, plus APAR-PQ77263, which is also part of WebSphere Application Server 5.0.2 Cumulative Fix 1.

Conclusion

Developers often want to create Web application WARs that contain and use a specific version of Xerces. WebSphere Application Server provides visibility (the classloader hierarchy) and delegation (the classloader order preference) settings to support this. However, you must avoid creating any EAR or ws.ext.dir utility classes that use Xerces, unless you implement a specific contextclassloader workaround within them to ensure that PARENT_LAST WAR modules will not have a ClassCastException whenever they use those utility classes

Top of page


About the authors

Photo of Barry Searle

Barry Searle is the Migration Team Leader for WebSphere Studio Application Developer. He is a Professional Engineer who has worked at the IBM Canada Lab for over ten years on various application development tools. Prior to that he had many years of industry experience developing command and control systems and leading communications development projects. You can reach Barry at searle@ca.ibm.com .

Ellen McKay is an Information Developer for IBM Canada Ltd. She writes online help and publications for WebSphere Studio Application Developer. You can reach Ellen at ecmckay@ca.ibm.com

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=14231
ArticleTitle=Avoiding ClassCastExceptions due to Xerces Libraries within Web Modules on WebSphere Application Server
publish-date=10222003
author1-email=searle@ca.ibm.com
author1-email-cc=
author2-email=ecmckay@ca.ibm.com
author2-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers