2

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&lt;String&gt;" 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.

CjRobin
  • 161
  • 1
  • 1
  • 14
  • _"jaxb adds this import to the class: `import java.util.List;`"_ - Generating invalid Java code would indicate a bug, no? You might want to check the bug database to see if this issue is listed? – Jim Garrison May 20 '23 at 00:30
  • What is the delimiter of the list supposed to be? – FLUXparticle May 21 '23 at 02:31
  • @FLUXparticle comma (",") delimited. – CjRobin May 22 '23 at 13:58
  • Then I would say it is not possible to describe such a format in XML schema. At least not in a way that the list is handled automatically. In XML Schema a list is always divided by spaces. – FLUXparticle May 22 '23 at 16:53

0 Answers0