Search code examples
jaxbjaxb2moxy

Moxy not honoring the super class/interface properties


enter code hereI have the properties for a Customer spread across two interfaces as shown below. I have the external xml binding defined using the sub interface ICustomer. When I marshall the pojo to xml, it seems like the Moxy is ignoring the super interface's property firstName. Is this a bug or do I need to explicitly specify each of these two interfaces in the xml meta-data?

Base interface

public interface IBaseCustomer
{
    String getFirstName();

    void setFirstName(final String firstName);
}

sub interface

public interface ICustomer extends IBaseCustomer
{
    String getLastName();

    void setLastName(final String lastName);

    Address getAddress();

    void setAddress(final Address address);

    List<PhoneNumber> getPhoneNumbers();

    void setPhoneNumbers(final List<PhoneNumber> phoneNumbers);

    void setPrefix(final String prefix);

    String getPrefix();
}

meta-data xml

<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="blog.bindingfile">
   <xml-schema namespace="http://www.example.com/customer" element-form-default="QUALIFIED" />
   <java-types>
      <java-type name="ICustomer">
         <xml-root-element name="customer"/>
         <xml-type prop-order="firstName lastName address phoneNumbers" />
         <java-attributes>
            <xml-element java-attribute="firstName" name="first-name" />
            <xml-element java-attribute="lastName" name="last-name" />
            <xml-element java-attribute="phoneNumbers" name="phone-number" />
         </java-attributes>
      </java-type>
      <java-type name="PhoneNumber">
         <java-attributes>
            <xml-attribute java-attribute="type" />
            <xml-value java-attribute="number" />
         </java-attributes>
      </java-type>
   </java-types>
</xml-bindings>

output

<customer xmlns="http://www.example.com/customer">
   <prefix>pre</prefix>
</customer>

Demo code

Map<String, Object> properties = new HashMap<String, Object>(1);
InputStream resourceAsStream = Demo.class.getResourceAsStream("xml-bindings.xml");
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, resourceAsStream);
JAXBContext jc = JAXBContext.newInstance("blog.bindingfile",  ICustomer.class.getClassLoader(), properties);

ICustomer customer = new Customer();
customer.setPrefix("pre");
customer.setFirstName("firstName");

Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(customer, System.out);

Solution

  • Fixed by EclipseLink MOXy V 2.4.1.

    I found that super interface support added into JavaClassImpl.getSuperClass method as following:

    public JavaClass getSuperclass() {
        if(this.superClassOverride != null) {
            return this.superClassOverride;
        }
        if(jClass.isInterface()) {
            Class[] superInterfaces = jClass.getInterfaces();
            if(superInterfaces != null) {
                if(superInterfaces.length == 1) {
                    return javaModelImpl.getClass(superInterfaces[0]);
                } else {
                    Class parent = null;
                    for(Class next:superInterfaces) {
                        if(!(next.getName().startsWith("java.") || next.getName().startsWith("javax."))) {
                            if(parent == null) {
                                parent = next;
                            } else {
                                throw JAXBException.invalidInterface(jClass.getName());
                            }
                        }
                    }
                    return javaModelImpl.getClass(parent);
                }
            }
        }
        return javaModelImpl.getClass(jClass.getSuperclass());
    }