Keith and Arnaud,
Thank you very much for your help on this. Fortunately, since you guys built
Castor to accept a custom classloader (a good design choice), the workaround for
this problem is actually very simple. All that has to be done is as follows.
If you have installed Castor as a java extension and want to use xsi:type
attributes, then instead of calling the unmarshal method created by the
SourceGenerator like this...
Root root = Root.unmarshalRoot(reader);
You just have to build the Unmarshaller yourself and give it a more suitable
classloader, like this:
Unmarshaller unm = new Unmarshaller(Root.class,
Root.class.getClassLoader());
Root root = (Root) unm.unmarshal(reader);
You can pass in a classloader from any class NOT installed as an extension or
ClassLoader.getSystemClassLoader(). Note that this workaround does not require
Java 1.2.
This is not a tough workaround, although it should probably be documented
somewhere. FYI, if you ever wanted to fix this permanently for all users, you'd
need to make a change in the SourceGenerator or Unmarshaller.java so that Castor
tries to use the classloader of the class being unmarshalled when no custom
classloader is present instead of resorting to the extclassloader, which is what
you get when you call Class.forName() from an installed extension. Note that
this should have zero impact on existing users of Castor because of how the Java
classloaders work. Again, the details are all in this whitepaper...
http://www.javageeks.com/Papers/ClassForName/ClassForName.pdf
... but basically, if you use the classloader of the class being unmarshalled,
it will FIRST give the extclassloader an opportunity to find the class. Only if
it fails does the classloader of the class being unmarshalled get a chance to
find the class. Basically, this is equivalent to calling Class.forName and if
this fails, trying to load the class with the classloader of the class being
unmarshalled (but it takes less code!) This change doesn't require Java 1.2,
and should not negatively impact any Java 1.1 users. I haven't spent much time
in the Castor code so I'm not sure exactly where you guys would like to make
such a change, and again it's not a tough workaround, so I'll leave it with you
guys at that.
Keith- thank you *very* much for the modification you checked into the CVS
regarding the use of schema names in xsi:type instead of the "java:" tagged
names. I just checked it out and everything is working perfectly now.
Jeff
/**
* [EMAIL PROTECTED] (818) 354-5472
* http://robotics.jpl.nasa.gov/people/jnorris/
*/
> -----Original Message-----
> From: Keith Visco [mailto:[EMAIL PROTECTED]]
> Sent: Wednesday, January 16, 2002 5:59 PM
> To: [EMAIL PROTECTED]
> Subject: Re: [castor-dev] BUG: Castor fails to find class for
> xsi:type="java:MyClass" - Example included.
>
>
>
>
> Jeff Norris wrote:
> >
> > I have determined the source of the error I encountered with the xsi:type=""
> > attribute. The problem is that I have installed castor as a java
> extension (the
> > jar file is symlinked in the jdk/jre/lib/ext/ directory), and I
> would bet money
> > that you (Keith) have it on your classpath. Java extensions use the
> > ExtClassLoader by default, which unfortunately does not have access to the
> > application classpath. This is not a security issue-- it is in my
> opinion an
> > unfortunate by-product of some design decisions made by Sun.
> >
> > http://www.javageeks.com/Papers/ClassForName/ClassForName.pdf
> >
> > What this means for Castor users is that Castor, if installed as a java
> > extension, will NOT be able to locate any user-defined classes that are not
> > themselves installed as extensions through the simple, one argument
> > Class.forName() call. Fortunately, there are some workarounds, described in
> > detail in the document referenced above. Each workaround has some minor
> > consequences that will have to be considered by the Castor development team.
> > Most notably, one of the workarounds uses features that are only in
> Java 1.2 and
> > above. Does Castor even support the 1.1 JVM at all? If not, then
> I think that
> > the workarounds have no serious consequences and should become part
> of Castor.
>
> Yes, as Arnaud mentioned in his e-mail, Castor XML does support JDK 1.1
> (Castor JDO does not have this requirement).
>
> The main reason is that we have some "influential" users that require
> JDK 1.1 support. When I say influential users, I mean users that enable
> me to continue working on Castor. :-)
>
> >
> > Keith- I plan to try making the modifications described in the
> document above on
> > my local copy of Castor and will let you know how it goes. I'd be very
> > interested to hear your thoughts on this, though, particularly
> whether *you* are
> > comfortable with the consequences of the workaround.
>
> I'll need to read the document, but I need to grab some food first...
>
> Also please let me know if my fix for "xsi:type" with regards to Schema
> name vs. Java class name works for you.
>
> Thanks,
>
> --Keith
>
> > > -----Original Message-----
> > > From: Keith Visco [mailto:[EMAIL PROTECTED]]
> > > Sent: Monday, January 14, 2002 7:33 PM
> > > To: [EMAIL PROTECTED]
> > > Subject: Re: [castor-dev] BUG: Castor fails to find class for
> > > xsi:type="java:MyClass" - Example included.
> > >
> > >
> > >
> > > Hi Jeff,
> > >
> > > I just ran your test case, and it appears fine for me. The output I get
> > > is:
> > >
> > > BugTest
> > > Beginning test #1
> > > Test 1 suceeded.
> > > Beginning test #2
> > > Test 2 suceeded.
> > >
> > >
> > > I am using the CVS version. I don't think any changes have gone into the
> > > CVS that would affect this issue, but you might want to try it.
> > >
> > > If not, it sounds to me like it could be a CLASSPATH issue. Are you
> > > running inside of a Servlet or App server engine?
> > >
> > > I will still look into the second issue: xsi:type="java:ChildType"
> > > instead of xsi:type="childType"
> > >
> > > Thanks,
> > >
> > > --Keith
> > >
> > >
> > > Jeff Norris wrote:
> > > >
> > > > First, I continue to be amazed by Castor. It is truly a first-rate
> > > product and
> > > > has saved my development staff countless hours. I have taken
> the time to
> > > > carefully write a detailed bug report and include a test
> program because I
> > > > appreciate Castor so much and want to see it continue to
> improve. On to the
> > > > bug...
> > > >
> > > > Castor 0.9.3.9 is not able to locate the class for a derived type
> > > that has been
> > > > specified in an XML file with
> xsi:type="java:fully.qualified.ClassName" and
> > > > throws a ClassNotFoundException. This occurs even when the file being
> > > > unmarshalled was originally written by Castor. Note that I *AM*
> > > including the
> > > > "java:" prefix and am specifing the fully qualified class name of
> > > the desired
> > > > derived type.
> > > >
> > > > I have constructed a simple schema, xml file, and test program
> which will
> > > > illustrate the problem. Note that I am using the "type" method in
> > > the source
> > > > generator - if you use the "element" method then you will have
> to slightly
> > > > modify BugTest.java.
> > > >
> > > > ***** THE SCHEMA (bugtest.xsd):
> > > >
> > > > <?xml version="1.0" encoding="UTF-8"?>
> > > > <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
> > > > <xs:element name="root">
> > > > <xs:complexType>
> > > > <xs:sequence>
> > > > <xs:element name="foo"
> type="parentType"/>
> > > > </xs:sequence>
> > > > </xs:complexType>
> > > > </xs:element>
> > > > <xs:complexType name="parentType">
> > > > <xs:sequence>
> > > > <xs:element name="a" type="xs:int"/>
> > > > </xs:sequence>
> > > > </xs:complexType>
> > > > <xs:complexType name="childType">
> > > > <xs:complexContent>
> > > > <xs:extension base="parentType">
> > > > <xs:sequence>
> > > > <xs:element name="b"
> type="xs:int"/>
> > > > </xs:sequence>
> > > > </xs:extension>
> > > > </xs:complexContent>
> > > > </xs:complexType>
> > > > </xs:schema>
> > > >
> > > > ***** THE XML FILE (bugtest.xml):
> > > >
> > > > <?xml version="1.0" encoding="UTF-8"?>
> > > > <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> > > > xsi:noNamespaceSchemaLocation="bugtest.xsd">
> > > > <foo xsi:type="java:ChildType">
> > > > <a>0</a>
> > > > <b>1</b>
> > > > </foo>
> > > > </root>
> > > >
> > > > ***** THE TEST PROGRAM (BugTest.java):
> > > >
> > > > import java.io.*;
> > > >
> > > > public class BugTest
> > > > {
> > > > public static void main (String[] args)
> > > > {
> > > > try {
> > > > // TEST 1 - attempt to unmarshal a hand-written xml file that
> > > > // contains a derived element.
> > > > System.out.println("Beginning test #1");
> > > > FileReader reader = new FileReader("bugtest.xml");
> > > > Root root = Root.unmarshalRoot(reader);
> > > > System.out.println("Test 1 suceeded.");
> > > > } catch (Exception e) {
> > > > System.out.println("Test 1 failed.");
> > > > e.printStackTrace();
> > > > } // end of try-catch
> > > >
> > > > try {
> > > > // TEST 2 - attempt to marshal and unmarshal an xml file with
> > > > // a derived element
> > > > System.out.println("Beginning test #2");
> > > > Root root = new Root();
> > > > root.setFoo(new ChildType());
> > > > ((ChildType)root.getFoo()).setA(1);
> > > > ((ChildType)root.getFoo()).setB(2);
> > > > FileWriter writer = new FileWriter("bugtest2.xml");
> > > > root.marshal(writer);
> > > > FileReader reader = new FileReader("bugtest2.xml");
> > > > root = Root.unmarshalRoot(reader);
> > > > System.out.println("Test 2 suceeded.");
> > > > } catch (Exception e) {
> > > > System.out.println("Test 2 failed.");
> > > > e.printStackTrace();
> > > > } // end of try-catch
> > > >
> > > > } // end of main ()
> > > > }
> > > >
> > > > ***** OUTPUT FROM THE TEST PROGRAM:
> > > >
> > > > > java BugTest
> > > > Beginning test #1
> > > > Test 1 failed.
> > > > org.xml.sax.SAXException: unable to instantiate ChildType;
> > > > java.lang.ClassNotFoundException: ChildType
> > > > at
> > > >
> > >
> org.exolab.castor.xml.UnmarshalHandler.startElement(UnmarshalHandler.java:957)
> > > > at
> > > org.apache.xerces.parsers.SAXParser.startElement(SAXParser.java:1335)
> > > > at
> > > >
> > > org.apache.xerces.validators.common.XMLValidator.callStartElement(XMLV
> > > alidator.j
> > > > ava:823)
> > > > at
> > > >
> > > org.apache.xerces.framework.XMLDocumentScanner.scanElement(XMLDocument
> > > Scanner.ja
> > > > va:1852)
> > > > at
> > > >
> > > org.apache.xerces.framework.XMLDocumentScanner$ContentDispatcher.dispa
> > > tch(XMLDoc
> > > > umentScanner.java:1233)
> > > > at
> > > >
> > > org.apache.xerces.framework.XMLDocumentScanner.parseSome(XMLDocumentSc
> > > anner.java
> > > > :380)
> > > > at
> org.apache.xerces.framework.XMLParser.parse(XMLParser.java:900)
> > > > at
> > > org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:338)
> > > > at
> > > org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:270)
> > > > at
> > > org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:391)
> > > > at Root.unmarshalRoot(Root.java:173)
> > > > at BugTest.main(BugTest.java:10)
> > > > Beginning test #2
> > > > Test 2 failed.
> > > > org.xml.sax.SAXException: unable to instantiate ChildType;
> > > > java.lang.ClassNotFoundException: ChildType
> > > > at
> > > >
> > >
> org.exolab.castor.xml.UnmarshalHandler.startElement(UnmarshalHandler.java:957)
> > > > at
> > > org.apache.xerces.parsers.SAXParser.startElement(SAXParser.java:1335)
> > > > ... etc, same as above
> > > >
> > > > ***** XML FILE WRITTEN DURING TEST #2:
> > > >
> > > > For reference, here is bugtest2.xml, which is the xml file
> written by Castor
> > > > during test #2:
> > > >
> > > > <?xml version="1.0"?>
> > > > <root><foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> > > > xsi:type="java:ChildType"><a>1</a><b>2</b></foo></root>
> > > >
> > > > Note that the xsi:type tag is exactly the same as it was in the
> hand-written
> > > > bugtest.xml above.
> > > >
> > > > As a side note, It would be fantastic if Castor were able to
> handle derived
> > > > types without the "java:" prefix in the xsi:type attribute.
> Castor-written
> > > > documents with derived types can't be loaded into any commercial
> > > xml editor (IE,
> > > > XMLSpy) since they don't recongnize the "java:" prefix.
> > > >
> > > > Jeff
> > > >
> > > > /**
> > > > * [EMAIL PROTECTED]
> > > > * http://robotics.jpl.nasa.gov/people/jnorris/
> > > > */
> > > >
> > > > -----------------------------------------------------------
> > > > If you wish to unsubscribe from this mailing, send mail to
> > > > [EMAIL PROTECTED] with a subject of:
> > > > unsubscribe castor-dev
> > >
> > > -----------------------------------------------------------
> > > If you wish to unsubscribe from this mailing, send mail to
> > > [EMAIL PROTECTED] with a subject of:
> > > unsubscribe castor-dev
> > >
> >
> > -----------------------------------------------------------
> > If you wish to unsubscribe from this mailing, send mail to
> > [EMAIL PROTECTED] with a subject of:
> > unsubscribe castor-dev
>
> -----------------------------------------------------------
> If you wish to unsubscribe from this mailing, send mail to
> [EMAIL PROTECTED] with a subject of:
> unsubscribe castor-dev
>
-----------------------------------------------------------
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
unsubscribe castor-dev