问题
enter code here
I 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);
回答1:
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());
}
回答2:
It's possible that MOXy isn't processing the super interface properties because they aren't public. By default, JAXB's accessor type is set to PUBLIC_MEMBER. The properties on the sub interface are processed because they are explicitly specified in external bindings, but those on the super interface aren't because they aren't public. You could try specifying a different accessor type at the package or interface level (in external metadata), or making the interface methods public to see if this resolves the issue.
update
On further investigation, this is indeed a bug. EclipseLink doesn't automatically process parent interfaces as it should. A temporary workaround is to add 'super-type="IBaseCustomer"' to the java-type for ICustomer.
I opened this bug to track the issue: https://bugs.eclipse.org/bugs/show_bug.cgi?id=386959
来源:https://stackoverflow.com/questions/11853821/moxy-not-honoring-the-super-class-interface-properties