3

I have a xml file and I want to convert it into a java object using JAXB. I am getting an exception related to validation. It seems JAXB is validating it against the DTD which is declared in the xml file. Unfortunately the DTD is not at the location which is mentioned in the xml file. So I kept a local copy and used an EntityResolver to make JAXB use the local DTD. And the code worked like a charm.

Below is the code

JAXBContext context = JAXBContext.newInstance(Student.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();

            final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            final XMLReader reader = saxParserFactory.newSAXParser().getXMLReader();
            reader.setEntityResolver(new EntityResolver() {

                @Override
                public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {

                    return new InputSource(getClass().getResourceAsStream("/student.dtd"));
                }
            });
            final SAXSource saxSource = new SAXSource(reader, new InputSource(inputStream));

            student = (Student) unmarshaller.unmarshal(saxSource);

This code is inside my method parse(xmlFilePath). Every time I call parse method a new EntityResolver is created. Is this not redundant? Can I create one EntityResolver in the class's constructor and pass it to the setEntityResolver method?

public StudentParser() {
this.entityResolver = new EntityResolver() {

                @Override
                public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {

                    return new InputSource(getClass().getResourceAsStream("/student.dtd"));
                }
            }
}

Inside parse method

public Student parse(filePath) {
    ...
    ...
    reader.setEntityResolver(this.entityResolver);
    ...
}
Krishna Chaitanya
  • 2,533
  • 4
  • 40
  • 74

1 Answers1

1

First of all, check these answers:

In short, you can disable the DTD processing completely.

Next, as long as your entity resolver is thread-safe and reusable you definitely don't need to create new instances every time.

Community
  • 1
  • 1
lexicore
  • 42,748
  • 17
  • 132
  • 221
  • I don't want to disable DTD validation. What do you mean by "as long as your entity resolver is thread-safe and reusable you definitely don't need to create new instances every time" – Krishna Chaitanya Oct 18 '14 at 11:32
  • Multiple threads access my `parse(filePath)` method. So do I need to create new `EntityReolver`-s every time? But what is the difference? Each time I create a new `EntityResolver` it always point to the same DTD right? – Krishna Chaitanya Oct 18 '14 at 11:36
  • @KrishnaChaitanya Ok, then it is not a duplicate, sorry. No, thread-safe means (roughly) that if concurrent access to a resources does not spoil anything then you can use one instance for all threads. From what I see, I believe your entity resolver is thread safe. No need to create new instances every time. But be careful with the streams. – lexicore Oct 18 '14 at 12:00
  • I don't think xmlReader modifies the resource. I think the dtd file is only used in read mode and concurrency is not a problem. Thanks for support. – Krishna Chaitanya Oct 18 '14 at 12:30