[JAXP-17] Improve the error diagnostics with classloader related problems Created: 12/Mar/07  Updated: 12/Mar/07

Status: Open
Project: jaxp
Component/s: www
Affects Version/s: current
Fix Version/s: milestone 1

Type: Improvement Priority: Major
Reporter: kohsuke Assignee: jaxp-issues
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Operating System: All
Platform: All
URL: http://forums.java.net/jive/thread.jspa?messageID=207570


Issuezilla Id: 17

 Description   

See the cited URL for the actual users that hit the problem. The error happens
in the following cast:

public static XMLOutputFactory newInstance()
throws FactoryConfigurationError

{ return (XMLOutputFactory) FactoryFinder.find("javax.xml.stream.XMLOutputFactory", "com.bea.xml.stream.XMLOutputFactoryBase"); }

... because there are apparently two copies of JSR-173 APIs, so the
XMLOutputFactory that Zephyr implements and the XMLOutputFactory used here are
two different classes, hence the cast fails.

This kind of problems are fairly common in multi-classloader environment, and
most of the users would get really confused with this.

In JAXB API, we have precautions for this kind of failures and provide error
diagnostics. The code is cited below so that you can adapt a similar technique
in the JAXP API.

// this creates JAXBContext, but don't cast it just yet.
Object context = m.invoke(null, classes, properties);
if(!(context instanceof JAXBContext))

{ // the cast would fail, so generate an exception with a nice message handleClassCastException(context.getClass(), JAXBContext.class); }

return (JAXBContext)context;

private static void handleClassCastException(Class originalType, Class
targetType) throws JAXBException

{ final URL targetTypeURL = which(targetType); throw new JAXBException(Messages.format(Messages.ILLEGAL_CAST, // we don't care where the impl class is, we want to know where JAXBContext lives in the impl // class' ClassLoader originalType.getClass().getClassLoader().getResource("javax/xml/bind/JAXBContext.class").toString(), targetTypeURL.toString())); }

static URL which(Class clazz)

{ return which(clazz, clazz.getClassLoader()); }

static URL which(Class clazz, ClassLoader loader) {

String classnameAsResource = clazz.getName().replace('.', '/') + ".class";

if(loader == null)

{ loader = ClassLoader.getSystemClassLoader(); }

return loader.getResource(classnameAsResource);
}


Generated at Sat Aug 01 02:06:16 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.