tags:

views:

5012

answers:

4

I have a problem with my web module classpath in Websphere v6.1.

In my WEB-INF/lib I have a largish number of jar files which include xercesImpl.jar and xmlparserv2.jar. I need both jars to be present, but they appear to confict with each other. Specifically, each jar contains a META-INF/services directory so, when we try to get an instance of a DocumentBuilderFactory via JAXP, which instance we get depends upon the order in which these two jars appear in the classpath.

I always want to use the xerces instance of the DocumentBuildFactory, so I want to push xercesImpl.jar to the front of the classpath. I've tried to do this by specifying a Class-Path section in the Manifest file for the war file, but the class path that I actually get in my WAS Module Compound CLass Loader in is very strange. I seem to get some standard stuff that WAS puts on, followed by the contents of WEB-INF lib in alphabetical order, followed by the classpath specified by the Manifest file.

If I don't put a manifest file into the war at all, I get the standard stuff followed by the contents of WEB-INF/lib but in an arbitrary order.

What am I missing? Is there a way in which I can set the class path up to be exactly what I want?

Dave

A: 

I assume by WebSphere, you mean the regular J2EE Application Server (and not something like Community Edition; WebSphere is a brand name applied to a number of IBM products).

I think your options are limited. Since the dependencies look quite explicit, I would prefer a programmatic approach rather than relying on the vagaries of the classpath (like creating factory instances explicitly rather than relying on the SPI).

If that isn't an option, you might want to look at making one of your dependencies an EAR project utility JAR and configure MODULE classloading with a PARENT_LAST classloading policy on the WAR. This can be configured via the browser admin console (or via the RAD tooling if you use it).

Another thing I'd look at is the WAS Shared Libraries feature (under Environment in the browser admin console). These can be associated with servers or applications. The downside is that this requires more configuration.

McDowell
+3  A: 

In IBM Websphere Application Server 6.1, web modules have their own class loaders that are usually used in the PARENT_FIRST mode. This means that the web module class loaders attempt to delegate class loading to the parent class loaders, before loading any new classes.

If you wish to have the Xerces classes loaded before the XML parser v2 (I'm assuming Oracle XML v2 parser) classes, then the Xerces classes will have to be loaded by a parent class loader - in this case, preferably the application class loader. This can be done by placing the Xerces jar in the root of the EAR file (if you have one) or prepare the EAR file with xerces.jar and your WAR file in the root. The xmlparserv2 jar should then be placed in WEB-INF\lib.

You could also attempt creating an Xerces shared library for usage by your application.

You can find more information about this in the IBM WebSphere Application Server V6.1: System Management and Configuration. Details are available in Chapter 12.

Vineet Reynolds
I just want to make sure I understand : I've restructed my ear file to :myapp.warMETA-INF/MANIFEST.MFxercesImpl.jarapplication.xmlwas.policyWhen I load this, xercesImpl.jar isn't on my CLASSPATH at all. Have I misunderstood you?
formatting got lost ... all the listed files are in the root of the ear file
A: 

You could also try setting system property to prefer an implementation. e.g. to prefer xmlparserv2 dom parser, set javax.xml.parsers.DocumentBuilderFactory=oracle.xml.jaxp.JXDocumentBuilderFactory

Shreeni
A: 

How JAXP Chooses Parsers

You may be wondering which parser this program actually uses. JAXP, after all, is reasonably parser-independent. The answer depends on which parsers are installed in your class path and how certain system properties are set. The default is to use the class named by the javax.xml.parsers.DocumentBuilderFactory system property. For example, if you want to make sure that Xerces is used to parse documents, then you would run JAXPChecker like this:

D:\books\XMLJAVA>java -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl JAXPChecker file:///D:/books/xmljava/dom.xml file:///D:/books/xmljava/dom.xml is well-formed.

If the javax.xml.parsers.DocumentBuilderFactory property is not set, then JAXP looks in the lib/jaxp.properties properties file in the JRE directory to determine a default value for the javax.xml.parsers.DocumentBuilderFactory system property. If you want to consistently use a certain DOM parser, for instance gnu.xml.dom.JAXPFactory, place the following line in that file:

javax.xml.parsers.DocumentBuilderFactory=gnu.xml.dom.JAXPFactory

If this fails to locate a parser, next JAXP looks for a META-INF/services/javax.xml.parsers.DocumentBuilderFactory file in all JAR files available to the runtime to find the name of the concrete DocumentBuilderFactory subclass.

Finally, if that fails, then DocumentBuilderFactory.newInstance() returns a default class, generally the parser from the vendor who also provided the JAXP classes. For example, the JDK JAXP classes pick org.apache.crimson.jaxp.DocumentBuilderFactoryImpl by default but the Ælfred JAXP classes pick gnu.xml.dom.JAXPFactory instead.

Ivan