Within Java, we often have abstract classes and commonly use them in collections and arrays. When a class is abstract, we cannot generate XML for any derived elements because they are not known until runtime. An example of this is the following code structure:
public abstract class VendorQuote implements Serializable ... public class HardwareVendorQuote extends VendorQuote ... public class ServiceVendorQuote extends VendorQuote ... public class Quote implements Serializable { private AbstractList<VendorQuote> vendors; ...
Note, that the vendors
attribute in the Quote
class is the collection of an abstract class. If we need our XML to differentiate between these concrete classes or create a Quote
class (which will need concrete classes in the collection), then we need to generate XML Schema elements for the concrete derived classes HardwareVendorQuote
and SoftwareVendorQuote
. In this recipe we show how to achieve this.
We need to know the class name of the bean and the name of the property that is the abstract class.
<xml-see-also>
and <xml-elements>
elements to the mapping file.In the OXM mapping file, we declare that a property has multiple possible concrete classes, and hence multiple possible elements in the WSDL mapping, by marking it with an <xml-elements>
, as shown in the following code snippet:
<?xml version="1.0" encoding="UTF-8" ?> <xml-bindings ...> <java-types> <java-type name="soa.cookbook.Quote"> <!-- Indicate that we are referencing these classes and so generate mappings for them --> <xml-see-also> soa.cookbook.HardwareVendorQuote soa.cookbook.ServiceVendorQuote </xml-see-also> <java-attributes> <xml-elements java-attribute="vendors"> <!-- Can provide concrete classes for abstract classes via explicit type attribute in xml-element --> <xml-element type="soa.cookbook.HardwareVendorQuote" name="hwVendorQuote"/> <xml-element type="soa.cookbook.ServiceVendorQuote" name="svcVendorQuote"/> <xml-element-wrapper name="vendors"/> </xml-elements> </java-attributes> </java-type> </java-types> </xml-bindings>
The <xml-elements> java-attribute
property is the name of the Java property that we want to associate with potential concrete classes; the <xml-element>
elements under the <xml_elements>
element identify the potential concrete classes for this abstract class. The <xml-see-also>
is a list of concrete classes that we need to provide XML types for in the generated schema. The <xml-element> name
property is the name of our concrete element and the type
property in the concrete Java class.
If the interface has already been mapped, then it is necessary to regenerate the WSDL interface for the changes we have made to take effect. Do this by deleting the existing wire and then rewiring.
<xml-elements>
provides a list of all the possible concrete elements that may be found in the given abstract Java class. Each <xml-element>
element is used to identify an XML element that should be generated and how it maps onto a concrete class extending the abstract Java class. The <xml-see-also>
element is really a hint to the schema generator that it will need to create the XML elements corresponding to the listed Java classes.
The EXMMapping
project in the code samples has a sample OXM file (mappings.xml
) demonstrating this.
When creating the mapping file, we need to be aware of all the possible concrete implementations that we may encounter. If we add new concrete classes to our Java implementation, we need to revisit the mapping file to add the new concrete classes.