Jump to: navigation, search

Difference between revisions of "EclipseLink/UserGuide/MOXy/Runtime/Convert Objects to XML/Events"

m (New page: =Validating against an XML Schema= Consider the following object model: <source lang="java"> package blog.jaxb.validation; import java.util.ArrayList; import java.util.List; import j...)
 
m
Line 1: Line 1:
 +
{{EclipseLink_UserGuide
 +
|info=y
 +
|eclipselink=y
 +
|eclipselinktype=MOXy
 +
|toc=n
 +
}}
 +
 
=Validating against an XML Schema=
 
=Validating against an XML Schema=
  

Revision as of 13:54, 5 April 2011

EclipseLink MOXy

link="http://wiki.eclipse.org/EclipseLink"
EclipseLink
Website
Download
Community
Mailing ListForumsIRC
Bugzilla
Open
Help Wanted
Bug Day
Contribute
Browse Source


Validating against an XML Schema

Consider the following object model:

package blog.jaxb.validation;
 
import java.util.ArrayList;
import java.util.List;
 
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement
public class Customer {
 
    private String name;
 
    private List<PhoneNumber> phoneNumbers =
        new ArrayList<PhoneNumber>();
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @XmlElement(name="phone-number")
    public List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }
 
    public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }
 
}
 
package blog.jaxb.validation;
 
public class PhoneNumber {
 
}


Notice that the model classes do not contain any validation specific information.

The sample code uses the following XML schema:

 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
    <xs:element name="customer">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="stringMaxSize5"/>
                <xs:element ref="phone-number" maxOccurs="2"/>
             </xs:sequence>
        </xs:complexType>
    </xs:element>
 
    <xs:element name="phone-number">
        <xs:complexType>
            <xs:sequence/>
        </xs:complexType>
    </xs:element>
 
    <xs:simpleType name="stringMaxSize5">
        <xs:restriction base="xs:string">
            <xs:maxLength value="5"/>
        </xs:restriction>
    </xs:simpleType>
 
</xs:schema>

Notice the following constraints:

  • The customer's name cannot be longer than 5 characters.
  • The customer cannot have more than 2 phone numbers.

ValidationEventHandler

JAXB reports validation events through the ValidationEventHandler. The event is represented as an instance of ValidationEvent, and provides many details about the issue. The data is similar to what is available from a SAXParseException.

Returning false from the handleEvent method will cause the JAXB operation to stop.

Returning true will allow the method to continue, if possible.

 
package blog.jaxb.validation;
 
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
 
public class MyValidationEventHandler implements ValidationEventHandler {
 
    public boolean handleEvent(ValidationEvent event) {
        System.out.println("\nEVENT");
        System.out.println("SEVERITY:  " + event.getSeverity());
        System.out.println("MESSAGE:  " + event.getMessage());
        System.out.println("LINKED EXCEPTION:  " + event.getLinkedException());
        System.out.println("LOCATOR");
        System.out.println("    LINE NUMBER:  " + event.getLocator().getLineNumber());
        System.out.println("    COLUMN NUMBER:  " + event.getLocator().getColumnNumber());
        System.out.println("    OFFSET:  " + event.getLocator().getOffset());
        System.out.println("    OBJECT:  " + event.getLocator().getObject());
        System.out.println("    NODE:  " + event.getLocator().getNode());
        System.out.println("    URL:  " + event.getLocator().getURL());
        return true;
    }
 
}

Marshalling

To enable validation, an instance of Schema must be set on the Marshaller. To handle the events an implementation of ValidationEventHandler must also be set.

 
package blog.jaxb.validation;
 
import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
 
public class MarshalDemo {
 
    public static void main(String[] args) throws Exception {
        Customer customer = new Customer();
        customer.setName("Jane Doe");
        customer.getPhoneNumbers().add(new PhoneNumber());
        customer.getPhoneNumbers().add(new PhoneNumber());
        customer.getPhoneNumbers().add(new PhoneNumber());
 
        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = sf.newSchema(new File("customer.xsd"));
 
        JAXBContext jc = JAXBContext.newInstance(Customer.class);
 
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setSchema(schema);
        marshaller.setEventHandler(new MyValidationEventHandler());
        marshaller.marshal(customer, System.out);
    }
 
}

Output

The validation performed during the marshal raised 3 events. The first 2 events are related to the text value of the "name" element being too long. The 3rd event is related to the extra "phone-number" element.

	
EVENT
SEVERITY:  1
MESSAGE:  cvc-maxLength-valid: Value 'Jane Doe' with length = '8' is not facet-valid with respect to maxLength '5' for type 'stringWithMaxSize5'.
LINKED EXCEPTION:  org.eclipse.persistence.oxm.record.ValidatingMarshalRecord$MarshalSAXParseException: cvc-maxLength-valid: Value 'Jane Doe' with length = '8' is not facet-valid with respect to maxLength '5' for type 'stringWithMaxSize5'.
LOCATOR
    LINE NUMBER:  -1
    COLUMN NUMBER:  -1
    OFFSET:  -1
    OBJECT:  blog.jaxb.validation.Customer@10045eb
    NODE:  null
    URL:  null
 
EVENT
SEVERITY:  1
MESSAGE:  cvc-type.3.1.3: The value 'Jane Doe' of element 'name' is not valid.
LINKED EXCEPTION:  org.eclipse.persistence.oxm.record.ValidatingMarshalRecord$MarshalSAXParseException: cvc-type.3.1.3: The value 'Jane Doe' of element 'name' is not valid.
LOCATOR
    LINE NUMBER:  -1
    COLUMN NUMBER:  -1
    OFFSET:  -1
    OBJECT:  blog.jaxb.validation.Customer@10045eb
    NODE:  null
    URL:  null
 
EVENT
SEVERITY:  1
MESSAGE:  cvc-complex-type.2.4.d: Invalid content was found starting with element 'customer'. No child element '{phone-number}' is expected at this point.
LINKED EXCEPTION:  org.eclipse.persistence.oxm.record.ValidatingMarshalRecord$MarshalSAXParseException: cvc-complex-type.2.4.d: Invalid content was found starting with element 'customer'. No child element '{phone-number}' is expected at this point.
LOCATOR
    LINE NUMBER:  -1
    COLUMN NUMBER:  -1
    OFFSET:  -1
    OBJECT:  blog.jaxb.validation.Customer@10045eb
    NODE:  null
    URL:  null


 
<customer>
   <name>Jane Doe</name>
   <phone-number/>
   <phone-number/>
   <phone-number/>
</customer>
</xml>