44

We are using JAXB to generate Java classes and have encountered a few cases where generated plural method names are not correct. For example, where we expect getPhysicians we are getting getPhysicien. How would we customize how JAXB pluralizes specific methods?

The schema:

<xs:complexType name="physician">
    <xs:sequence>
       ...
    </xs:sequence>
</xs:complexType>

<xs:complexType name="physicianList">
    <xs:sequence>
        <xs:element name="Physician"
                    type="physician"
                    minOccurs="0"
                    maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

The generated Java code:

...
public class PhysicianList {
...

    @XmlElement(name = "Physician")
    protected List<Physician> physicien;
    ...

    public List<Physician> getPhysicien() {
        if (physicien == null) {
            physicien = new ArrayList<Physician>();
        }
        return this.physicien;
    }

Update

This has been answered by Blaise. However, I prefer not mixing concerns such as JAXB customizations in an XML schema. So for those of you with the same preference, here is a JAXB binding file that achieves the same thing as what Blaise suggested, keeping JAXB customization out of the schema:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               version="2.0">

    <jaxb:bindings schemaLocation="myschema.xsd">
        <jaxb:bindings node="//xs:complexType[@name='physicianList']//xs:element[@name='Physician']">
            <jaxb:property name="physicians"/>
        </jaxb:bindings>
    </jaxb:bindings>

</jaxb:bindings>
SingleShot
  • 18,821
  • 13
  • 71
  • 101
  • 1
    It doesn't even spell physician correctly, but rather as physici*e*n. Strange. – Hovercraft Full Of Eels Dec 21 '10 at 17:59
  • XJC actually bases it on the element name for lists, so you could have just called your element name physicians. BUT (and it is a big but...) if you do this, there is is still a quirk in that when you re-marshal the object using JAXB each element will have the plural name 'physicians'. Very odd. So that said, I have used your approach and it works all round. – Simon May 10 '12 at 12:54

2 Answers2

31

By default the following is generated for your schema fragment:

    import java.util.ArrayList;
    import java.util.List;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlType;

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "physicianList", propOrder = {
        "physician"
    })
    public class PhysicianList {

        @XmlElement(name = "Physician")
        protected List<Physician> physician;

        public List<Physician> getPhysician() {
            if (physician == null) {
                physician = new ArrayList<Physician>();
            }
            return this.physician;
        }

    }

If you annotate your XML schema:

    <xs:schema
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        jaxb:version="2.1">

        <xs:complexType name="physician">
            <xs:sequence>
            </xs:sequence>
        </xs:complexType>

        <xs:complexType name="physicianList">
            <xs:sequence>
                <xs:element name="Physician"
                            type="physician"
                            minOccurs="0"
                            maxOccurs="unbounded">
                      <xs:annotation>
                          <xs:appinfo>
                              <jaxb:property name="physicians"/>
                          </xs:appinfo>
                      </xs:annotation>
                 </xs:element>
            </xs:sequence>
        </xs:complexType>

    </xs:schema>

Then you can generate the desired class:

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "physicianList", propOrder = {
    "physicians"
})
public class PhysicianList {

    @XmlElement(name = "Physician")
    protected List<Physician> physicians;

    public List<Physician> getPhysicians() {
        if (physicians == null) {
            physicians = new ArrayList<Physician>();
        }
        return this.physicians;
    }

}
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • 2
    That worked great. Thanks! FYI, I dislike mixing concerns such as JAXB customizations in an XML schema, so I've added to the end of my question an example of using a binding file to do the same as you suggest. Thanks again! – SingleShot Dec 21 '10 at 22:15
  • I tried the solution suggested by you, and the classes generated still dont have the return types I would love to have. I have asked another question for that [here](http://stackoverflow.com/questions/4502229/how-do-you-customize-how-jaxb-generates-plural-method-names). I would really appreciate your help if you take your time to answer this question as well. – Ashish Kumar Shah Jun 12 '16 at 03:38
23

Maybe it's a little late to answer, but there's another way to generate plural names simply, without mixing XML Schema and JAXB Bindings.

By using JAXB XJC binding compiler with the "-extension" mode. A customization bindings file need to be added, like this one :

<?xml version="1.0"?>
<jxb:bindings version="1.0"
              xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
              jxb:extensionBindingPrefixes="xjc">

  <jxb:globalBindings>              
    <xjc:simple/>
  </jxb:globalBindings>

</jxb:bindings>

References :

Guillaume Husta
  • 4,049
  • 33
  • 40
  • This should be the accepted answer. Also, here's a nice reference on how to pass this bindings file to the xjc on the command line: https://www.ibm.com/docs/en/ste/10.1?topic=adapter-java-class-requirements – Adam Wise May 24 '23 at 13:45