If an optional attribute is set, then I want another attribute to be suddenly required. Also, this means the ladder optional attribute can only be set if the previous attribute is set.
ie,
name is Required
status is optional, but if set then country needs to be specified as well.
country is only set if status is given.
<field name="myField" status="citizen" country="England"/>
A valid xml tag can also be where status and country are null (and therefore not unmarshalled):
<field name="myField" />
It will probably be easier if I put the optional fields in their own xml tag? Maybe something like this:
<field name="myField">
<option status="citizen" country="England"/>
</field>
Although would the first way be possible?
You could use a beforeMarshal event and do the following:
Field
If you don't like having the beforeMarshal method on your domain class you could implement a Marshaller.Listener and set in on the Marshaller (see: http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.Listener.html).
package forum13918891;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Field {
@XmlAttribute
String name;
@XmlAttribute
String status;
@XmlAttribute
String country;
private void beforeMarshal(Marshaller marshaller) {
if(country != null && status == null) {
throw new RuntimeException("country was set but status was not");
}
}
}
Demo
Below is some demo code to prove everything works.
package forum13918891;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Field.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Field field = new Field();
field.name = "myField";
marshaller.marshal(field, System.out);
field.status = "citizen";
field.country = "England";
marshaller.marshal(field, System.out);
field.status = null;
marshaller.marshal(field, System.out);
}
}
Output
Below is the output from running the demo code.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<field name="myField"/>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<field name="myField" status="citizen" country="England"/>
Exception in thread "main" java.lang.IllegalStateException: java.lang.reflect.InvocationTargetException
at com.sun.xml.bind.v2.runtime.XMLSerializer.fireMarshalEvent(XMLSerializer.java:758)
at com.sun.xml.bind.v2.runtime.XMLSerializer.fireBeforeMarshalEvents(XMLSerializer.java:743)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:491)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:315)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:244)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:75)
at forum13918891.Demo.main(Demo.java:21)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.xml.bind.v2.runtime.XMLSerializer.fireMarshalEvent(XMLSerializer.java:755)
... 6 more
Caused by: java.lang.RuntimeException: country was set but status was not
at forum13918891.Field.beforeMarshal(Field.java:21)
... 11 more
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With