8

I have some classes with JAXB annotations, I have created some instances and I need to validate them against my XSD files. I should be able to get the details of what is wrong when the objects are invalid.

So far I haven't had luck, I know about this class ValidationEventHandler but apperantly I can use it with the Unmarshaller class, the problem is that I have to validate the objects not the raw XML.

I have this code:

MyClass myObject = new MyClass();
JAXBContext jaxbContext = JAXBContext.newInstance("x.y.z");
JAXBSource jaxbSource = new JAXBSource(jaxbContext, myObject);
SchemaFactory factory = SchemaFactory
                .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source schemaFile = new StreamSource(getClass().getClassLoader()
                .getResourceAsStream("mySchema.xsd"));
Schema schema = factory.newSchema(schemaFile);

Validator validator = schema.newValidator();

validator.validate(jaxbSource);

This code will work, it will validate the object and throw an exception with the message, something like this:

cvc-pattern-valid: Value '12345678901' is not facet-valid with respect to pattern '\d{10}' for type 'id'.]

The problem is that I need specific details, with a string like that I would have to parse all the messages.

Rodrigo
  • 483
  • 8
  • 14
  • One possible option exists here: http://stackoverflow.com/questions/11921190/how-to-get-the-element-of-and-invalid-xml-file-with-failed-xsd-validation – ug_ Jun 12 '14 at 04:40
  • Found another awnser that shows you how to get the actual invalid DOM element http://stackoverflow.com/questions/8077437/how-can-i-get-more-information-on-an-invalid-dom-element-through-the-validator#answer-8162185 – ug_ Jun 12 '14 at 09:39

2 Answers2

1

You can set an instance of ErrorHandler on the Validator to catch individual errors:

    Validator validator = schema.newValidator();
    validator.setErrorHandler(new MyErrorHandler());
    validator.validate(source);

MyErrorHandler

Below is a sample implementation of the ErrorHandler interface. If you don't rethrow the exception the validation will continue.

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class MyErrorHandler implements ErrorHandler {

    public void warning(SAXParseException exception) throws SAXException {
        System.out.println("\nWARNING");
        exception.printStackTrace();
    }

    public void error(SAXParseException exception) throws SAXException {
        System.out.println("\nERROR");
        exception.printStackTrace();
    }

    public void fatalError(SAXParseException exception) throws SAXException {
        System.out.println("\nFATAL ERROR");
        exception.printStackTrace();
    }

} 

For More Information

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • 3
    Hi @blaise The only problem that I have with this approach is that all I get is a string with all the details like "cvc-pattern-valid: Value '12345678901' is not facet-valid with respect to pattern '\d{10}' for type 'id'.]"... Since I need to know what specific element is wrong I have no other option but parse the string – Rodrigo Jun 19 '12 at 22:12
1

I. If you validate a complex object hierarchy, you can create the Marshaller yourself and set its listener:

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setListener(yourListener);
JAXBSource source = new JAXBSource(marshaller, object);

This listener will get notified with instances of your objects as it walks the hierarchy.

II. Add an ErrorHandler from the other answer. At least with Wildfly 15 the messages look like:

cvc-maxInclusive-valid: Value '360.953674' is not facet-valid with respect to maxInclusive '180.0' for type '#AnonType_longitudeGeographicalPosition'.'
cvc-type.3.1.3: The value '360.953674' of element 'longitude' is not valid.'

So you can parse out the element name, which is the guilty terminal field name.

III. Combine I and II with some introspection and you can reconstruct a full Java Beans style path to the erroneous field if necessary.

Vsevolod Golovanov
  • 4,068
  • 3
  • 31
  • 65