The Source for Java Technology Collaboration

Home » java.net Forums » GlassFish » Metro and JAXB

Thread: Why is JAXB looking for a DTD when unmarshaling & how can I make it stop?

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 8 - Last Post: Feb 24, 2009 2:42 AM by: ammwuh
metamatic

Posts: 3
Why is JAXB looking for a DTD when unmarshaling & how can I make it stop?
Posted: Mar 24, 2008 4:00 PM
  Click to reply to this thread Reply

I've taken the XML schema in a .xsd file, and used to to generate a bunch of classes.

I've written my code to generate an unmarshaler, feed it an example file (actually a dump of some data fetched via HTTP), and then run through the unmarshaled object tree.

Now, my example input file has a DOCTYPE declaration which refers to a DTD by relative path. If I delete that DOCTYPE, everything works. With the DOCTYPE in place, I get an exception saying the DTD couldn't be found.

My first question is, why is JAXB going and looking for a DTD, if I already compiled all the schema information into Java classes?

The second question is, how can I make it stop?

If it helps, the error seems to be thrown inside xerces, specifically com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl... Perhaps there's a way to pass info into xerces to tell it to ignore the DOCTYPE, or tell it where it can find the DTD?

Thanks,


mathew

bhaktimehta

Posts: 142
Re: Why is JAXB looking for a DTD when unmarshaling & how can I make it sto
Posted: Mar 24, 2008 4:42 PM   in response to: metamatic
  Click to reply to this thread Reply

I am not sure if now there is a better way to do it now but I had read this some time ago
http://forum.java.sun.com/thread.jspa?threadID=284209&forumID=34
To prevent the XML to be checked against its DTD, this is what I did:

myDocumentBuilder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId)
throws SAXException, java.io.IOException
{
if (publicId.equals("--myDTDpublicID--"))
// this deactivates the open office DTD
return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));
else return null;
}
});

Basically have your EntityResolver return an emtpy xml document instead of a dtd and stop the validation

bhaktimehta

Posts: 142
Re: Why is JAXB looking for a DTD when unmarshaling & how can I make it sto
Posted: Mar 24, 2008 4:43 PM   in response to: bhaktimehta
  Click to reply to this thread Reply

Here was the thread to the previous post
http://forums.java.net/jive/thread.jspa;jsessionid=1D679B3BCDF0E4BB0FC8C12E12A14A09?messageID=257580&#257580

metamatic

Posts: 3
Re: Why is JAXB looking for a DTD when unmarshaling & how can I make it sto
Posted: Mar 25, 2008 12:29 PM   in response to: bhaktimehta
  Click to reply to this thread Reply

The problem is, that means I have to create my own SAX parser object, create an EntityResolver, configure SAX to use the EntityResolver, and then configure JAXB to use it, making the code twice as long. My whole reason for looking at JAXB is to not have to mess with SAX and to keep the code simple.

The documentation suggests that
unmarshaller.setSchema(null);
ought to turn off schema validation, which in turn should turn off attempts to load the DTD; but this seems not to be the case.

userquin

Posts: 1
Re: Why is JAXB looking for a DTD when unmarshaling & how can I make it sto
Posted: Mar 26, 2008 3:59 AM   in response to: metamatic
  Click to reply to this thread Reply

Hi:

When you must validate a DTD via JAXB using SAX source you must configure SAXParserFactory:

SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setValidating(true); // (1)
SAXParser saxParser = parserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
EntityResolver entityResolver = new EntityResolver()
{
public InputSource resolveEntity (String publicId, String systemId)
{
// some local resource via getClass().getResourceAsStream() for example
return ....; //
}
};
xmlReader.setEntityResolver(entityResolver); // (2)
SAXSource saxSource = new SAXSource(xmlReader, source);
Unmarshaller unmarshaller = JAXBContext.newInstance("somepackage").createUnmarshaller();
ValidationEventCollector eventCollector = new ValidationEventCollector();
unmarshaller.setEventHandler(eventCollector);
Objec umarshalledSata = unmarshaller.unmarshal(saxSource);
if (eventCollector.hasEvents())
{
for(ValidationEvent event: eventCollector.getEvents())
log.error(event.getMessage(), event.getLinkedException());
throw ....; // here throw an exception or what you want
}

If you want to disable DTD validation, turn off via:

parserFactory.setValidating(false);// from (1)

If this does not work remove line with mark (2).

Hope this help.

Bye.

metamatic

Posts: 3
Re: Why is JAXB looking for a DTD when unmarshaling & how can I make it sto
Posted: Mar 26, 2008 7:05 AM   in response to: userquin
  Click to reply to this thread Reply

Well, since I apparently have to mess with JAXP anyway, I've thrown away JAXB and started writing a straight DOM/XPath-using class to encapsulate everything. Maybe a future release of JAXB will be more flexible.

iznogood

Posts: 1
Re: Why is JAXB looking for a DTD when unmarshaling & how can I make it sto
Posted: Oct 31, 2008 3:24 AM   in response to: userquin
  Click to reply to this thread Reply

To simply disable DTD validation, you can set feature to the saxParserFactory:
parserFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //Disable DTD validation

But using either of the solutions, I have trouble binding attributes. It does bind elements but not attributes. If I use the unmarshal(InputStream) version, it works OK, but giving it a SAXSource causes the attribute parsing to fail.

I'm using JAXB RI 2.1.7 and bindings were generated from DTD.

Any ideas why it happens?

ammwuh

Posts: 1
Re: Why is JAXB looking for a DTD when unmarshaling & how can I make it sto
Posted: Feb 24, 2009 2:42 AM   in response to: iznogood
  Click to reply to this thread Reply

I too had trouble getting JAXB to unmarshal attributes when using SAXSource. I eventually got it to work by creating a namespace aware SAX parser:

spf.setNamespaceAware(true);

mdbuck

Posts: 2
Re: Why is JAXB looking for a DTD when unmarshaling & how can I make it sto
Posted: Mar 26, 2008 6:55 AM   in response to: metamatic
  Click to reply to this thread Reply

Even though you may have validation turned off the XML parser still must download the DTD in order to resolve entity references, default values for attributes and so on.

One solution may be to not include the DTD reference in the returned XML.

Another solution may be to add standalone="yes" in the XML prolog. I have never tried this, though.

See this for what the standalone attribute means: http://www.w3.org/TR/1998/REC-xml-19980210#sec-rmd

Michael




 XML java.net RSS