Jax empty element unmarshalling

The problem is this:

I get a response to soap with an empty element inside (for example ... <someDate /> ... ) and as a result an exception is thrown when JAXB wants to parse this element instead, set the corresponding field with null value.

How to configure JAXB to handle empty elements as null? Can we only do this with JAXB (without using some third-party workarounds)

+4
source share
1 answer

Main problem

Empty String not a valid value for type xsd:date . To be valid in an XML schema, an optional element must be represented as a missing node.,


Why the main problem affects you

All JAXB implementations recognize that an empty String not a valid value for xsd:date . They do this by reporting this to the ValidationEventHandler instance. You yourself see this by following these steps:

  Unmarshaller unmarshaller = jc.createUnmarshaller(); unmarshaller.setEventHandler(new ValidationEventHandler() { @Override public boolean handleEvent(ValidationEvent event) { System.out.println(event); return true; } }); 

The JAX-WS implementation that you use uses EclipseLink MOXy as the JAXB provider. And in the version that you use MOXy, it throws an exception by default if instead of FATAL_ERROR ValidationEvent meets the severity ERROR , as a reference implementation. Since then, this has been fixed in the following error:


Work around

If you use the JAXB API directly, you can simply override the default ValidationEventHandler . In a JAX-WS environment, a XmlAdapter can be used to provide custom conversion logic. We will use the XmlAdapter to override how conversion to / from Date handled.

XmlAdapter (DateAdapter)

 import java.text.SimpleDateFormat; import java.util.Date; import javax.xml.bind.annotation.adapters.XmlAdapter; public class DateAdapter extends XmlAdapter<String, Date>{ private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); @Override public Date unmarshal(String v) throws Exception { if(v.length() == 0) { return null; } return dateFormat.parse(v); } @Override public String marshal(Date v) throws Exception { if(null == v) { return null; } return dateFormat.format(v); } } 

Java Model (Root)

The XmlAdapter link XmlAdapter used using the @XmlJavaTypeAdapter annotation. If you want this XmlAdapter applied to all instances of Date , you can register it at the package level (see http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html ).

 import java.util.Date; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlSchemaType(name = "date") @XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class) private Date abc; @XmlSchemaType(name="date") @XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class) private Date qwe; } 

Demo code

Below is a separate example that you can run to see that everything works.

jaxb.properties

In the standalone example of using MOXy as your JAXB provider, you need to include a file named jaxb.propeties in the same package as your domain model, with the following entry (see http://blog.bdoughan.com/2011/05/ specifying-eclipselink-moxy-as-your.html ).

 javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

Input.xml

 <?xml version="1.0" encoding="UTF-8"?> <root> <abc></abc> <qwe>2013-09-05</qwe> </root> 

Demo

 import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum18617998/input.xml"); Root root = (Root) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } } 

Exit

Note that in the marshalled XML, the Date field, which was null, was allocated as the missing element (see http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html ) .

 <?xml version="1.0" encoding="UTF-8"?> <root> <qwe>2013-09-05</qwe> </root> 
+8
source

All Articles