We had the same description requirements for Dave. The solution that worked was based on Java reflection.
The idea is to set propOrder for attributes at runtime. In our case, there is an APP_DATA element containing 3 attributes: app, key, value. The generated AppData class includes “content” in propOrder and none of the other attributes:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AppData", propOrder = { "content" }) public class AppData { @XmlValue protected String content; @XmlAttribute(name = "Value", required = true) protected String value; @XmlAttribute(name = "Name", required = true) protected String name; @XmlAttribute(name = "App", required = true) protected String app; ... }
So, to determine the order at runtime, Java reflection was used:
final String[] propOrder = { "app", "name", "value" }; ReflectionUtil.changeAnnotationValue( AppData.class.getAnnotation(XmlType.class), "propOrder", propOrder); final JAXBContext jaxbContext = JAXBContext .newInstance(ADI.class); final Marshaller adimarshaller = jaxbContext.createMarshaller(); adimarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); adimarshaller.marshal(new JAXBElement<ADI>(new QName("ADI"), ADI.class, adi), new StreamResult(fileOutputStream));
The change AnnotationValue () was borrowed from this post: Change the class definition annotation string parameter at run time
Here's a method for your convenience (credit applies to @assylias and @Balder):
@SuppressWarnings("unchecked") public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue){ Object handler = Proxy.getInvocationHandler(annotation); Field f; try { f = handler.getClass().getDeclaredField("memberValues"); } catch (NoSuchFieldException | SecurityException e) { throw new IllegalStateException(e); } f.setAccessible(true); Map<String, Object> memberValues; try { memberValues = (Map<String, Object>) f.get(handler); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } Object oldValue = memberValues.get(key); if (oldValue == null || oldValue.getClass() != newValue.getClass()) { throw new IllegalArgumentException(); } memberValues.put(key,newValue); return oldValue; }
Hope this helps someone!