We have been using jaxb for a long time to unmarshal XML into POJOs that we can use within our system. However, only recently I found an issue with how jaxb is parsing the xml provided data and I would like to override that behavior by implementing a custom XmlAdapter and forcing jaxb to use it.
Let's say we have a complex field definition like the below in our xsd:
<xs:complexType name="ratingType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="scheme" use="required" type="xs:NMTOKEN"/>
<xs:attribute name="subRatings" use="optional">
<xs:simpleType>
<xs:list itemType='xs:string'/>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
Without making any changes, jaxb creates the following java class attribute:
@XmlAttribute(name = "subRatings")
protected List<String>subRatings;
This has been generally ok, however, due to new client requirements the data we get on this field will change.
Current use case:
<rating scheme="urn:ncs" subRatings="Violence">MA15+</rating>
This turns into subRatings=["Violence"], which is great.
New use case:
<rating scheme="urn:ncs" subRatings="Coarse Language">MA15+</rating>
This, however, turns into subRatings=["Coarse", "Language"], which is not right and causes issues downstream as that is not a recognized subRating. I expect it to be subRatings=["Coarse Language"] instead.
I have tried a few things, but so far the one that gets me closest to what I want is using jaxb bindings like the below:
<jxb:bindings schemaLocation="media.xsd" node="//xs:complexType[@name='ratingType']">
<jxb:bindings node=".//xs:attribute[@name='subRatings']">
<jxb:property>
<jxb:baseType>
<xjc:javaType name="java.util.List<String>" adapter="org.jvnet.jaxb2_commons.xml.bind.annotation.adapters.CommaDelimitedStringAdapter"/>
</jxb:baseType>
</jxb:property>
</jxb:bindings>
</jxb:bindings>
The generated class has the following attribute definition:
@XmlAttribute(name = "subRatings")
@XmlJavaTypeAdapter(CommaDelimitedStringAdapter.class)
protected List<String>subRatings;
All good so far. However, for some reason, jaxb adds this import to the class: import java.util.List<String>;
which causes it to not compile.
Other thing that I tried was removing the specific type in the javaType name definition, like java.util.List
but that causes jaxb to create the field with a raw type like protected List subRatings;
and that's not only ugly but it causes issues downstream as now anyone using this class needs to cast the subrating object making the code smelly. Any ideas how to overcome this? Keep in mind that I cannot modify the generated classes as they are built at compile time.