In a How to validate XML versus XSD in Java tutorial shows you how to validate an validate xml vs xsd file using the javax.xml.validation APIs. In this tutorial shows you how to use JAXB unmarshal schema validation during unmarshal operation. Here is a way to leverage the JAXB APIs.
Such as the previous tutorial, you should define Fruit XML schema
Fruit.xsd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="fruit"> <xs:complexType> <xs:sequence> <xs:element name="id" type="xs:int"></xs:element> <xs:element name="name" type="NameFruit"></xs:element> <xs:element name="produceby" type="ProduceBy" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> <xs:simpleType name="NameFruit"> <xs:restriction base="xs:string"> <xs:maxLength value="10" /> </xs:restriction> </xs:simpleType> <xs:simpleType name="ProduceBy"> <xs:restriction base="xs:string"> <xs:whiteSpace value="collapse" /> <xs:maxLength value="250" /> </xs:restriction> </xs:simpleType> </xs:schema> |
Here, you should use a java model that may be generated by JAXB in Eclipse such as the below figure (you could define manually this model by yourself)

then you get java file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
package com.javabycode.xml; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "id", "name", "produceby" }) @XmlRootElement(name = "fruit") public class Fruit { protected int id; @XmlElement(required = true) protected String name; protected String produceby; public int getId() { return id; } public void setId(int value) { this.id = value; } public String getName() { return name; } public void setName(String value) { this.name = value; } public String getProduceby() { return produceby; } public void setProduceby(String value) { this.produceby = value; } } |
Customize the ValidationEventHandler of JAXB
ValidationEventHandler catches all events that JAXB reports after finished validation. The event is an instance of ValidationEvent, and provides many details about the validation issue. You could get these details also by using SAXParseException. Here, the CustomValidationEventHandler will get information of all events and print the formatted messages.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.javabycode.xml; import javax.xml.bind.ValidationEvent; import javax.xml.bind.ValidationEventHandler; public class CustomValidationEventHandler implements ValidationEventHandler { public boolean handleEvent(ValidationEvent event) { System.err.println("\nEVENT " + "\nSEVERITY: " + event.getSeverity() + "\nMESSAGE: " + event.getMessage() + "\nLOCATOR" + "\n LINE NUMBER: " + event.getLocator().getLineNumber() + "\n COLUMN NUMBER: " + event.getLocator().getColumnNumber() + "\n OFFSET: " + event.getLocator().getOffset() + "\n OBJECT: " + event.getLocator().getObject() + "\n NODE: " + event.getLocator().getNode() + "\n URL: " + event.getLocator().getURL()); return true; } } |
JAXB unmarshal schema validation
The validation will be activated when the unmarshal operation starts. To catch the events you must set a instance of ValidationEventHandler for a unmarshal instance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.javabycode.xml; import java.io.File; import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; public class UnmarshalXMLValidation { public static void main(String[] args) throws Exception { SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = sf.newSchema(new File("src/main/resources/Fruit.xsd")); JAXBContext jc = JAXBContext.newInstance(Fruit.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); unmarshaller.setSchema(schema); unmarshaller.setEventHandler(new CustomValidationEventHandler()); Fruit fruit = (Fruit) unmarshaller.unmarshal(new File("src/main/resources/Fruit.xml")); } } |
Validation input Fruit.xml
The Fruit.xml is input for this validation demo
1 2 3 4 5 6 |
<?xml version="1.0" encoding="UTF-8"?> <fruit> <id>1</id> <name>Apple from Indonesia</name> <produceby>Chile</produceby> </fruit> |
OKay, now you run the main class UnmarshalXMLValidation and here is output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
EVENT SEVERITY: 2 MESSAGE: cvc-maxLength-valid: Value 'Apple from Indonesia' with length = '20' is not facet-valid with respect to maxLength '10' for type 'NameFruit'. LOCATOR LINE NUMBER: 4 COLUMN NUMBER: 36 OFFSET: -1 OBJECT: null NODE: null URL: file:/C:/Users/CanhPV/example/UnmarshalSchemaValidate/src/main/resources/Fruit.xml EVENT SEVERITY: 2 MESSAGE: cvc-type.3.1.3: The value 'Apple from Indonesia' of element 'name' is not valid. LOCATOR LINE NUMBER: 4 COLUMN NUMBER: 36 OFFSET: -1 OBJECT: null NODE: null URL: file:/C:/Users/CanhPV/example/UnmarshalSchemaValidate/src/main/resources/Fruit.xml |
That’s all on how to do JAXB unmarshal schema validation. You can download this program source code
UnmarshalSchemaValidate