In Service Oriented Architecture (SOA) or MicroServices Architecture, data is exchanged between different components over the network.
Keeping in mind the INTEROPERABILITY, Data Contracts are created and shared.
Contracts either in the form of WSDL or XSDs etc are mutually agreed between the components to exchange the Structured data among them.
As part of these contracts, you may have a need to send a collection of similar data and for this purpose you may have defined different complexTypes in your xsd.
This article talks about problem associated with defining List Complex Types, how can we overcome this problem using XEW Plugin and the benefits.
Consider you want to exchange a list of AirSegments under an Itinerary like:
AC
12
AC
13
AC
189
To accomplish this, you will define Something like below:
<xs:complexType name="OriginDestinationBookedType">
<xs:element name="AirSegmentBookedList" type="SegmentBookedListType"/>
<xs:complexType name="SegmentBookedListType">
<xs:element maxOccurs="unbounded" name="AirSegmentBooked" type="SegmentBookedType"/>
<xs:complexType name="SegmentBookedType">
<xs:element name="CarrierCode" type="CarrierCodeType"/>
<xs:element name="FlightNumber" type="FlightNumberType"/>
This looks good. Looks Good until we generate the Proxy classes out of these Contracts. Give it a try to generate the classes out of these XSDs using Plugins: JAXB-MAVEN, CXF etc.
You will notice that 3 proxy classes get generated.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "OriginDestinationBookedType", propOrder = {
"segmentBookedList"
})
public class OriginDestinationBookedType {
@XmlElement(name = "SegmentBookedList", required = true)
protected SegmentBookedListType segmentBookedList;
public SegmentBookedListType getSegmentBookedList() {
return segmentBookedList;
}
public void setSegmentBookedList(SegmentBookedListType value) {
this.segmentBookedList = value;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SegmentBookedListType", propOrder = {
"segmentBookeds"
})
public class SegmentBookedListType {
@XmlElement(name = "SegmentBooked", required = true)
protected List segmentBookeds;
public List getSegmentBookeds() {
if (segmentBookeds == null) {
segmentBookeds = new ArrayList();
}
return this.segmentBookeds;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SegmentBookedType", propOrder = {
"carrierCode",
"flightNumber"
})
public class SegmentBookedType {
@XmlElement(name = "CarrierCode", required = true)
protected String carrierCode;
@XmlElement(name = "FlightNumber", required = true)
protected String flightNumber;
}
With the above classes, if you want to get an access to a Segment within an OD, you will have to write:
OriginDestinationBookedType od; // Initialized properly and you have a non-null reference
od.getSegmentBookedList().getSegmentBookeds().get(segIndex);
Bold part above is redundant and not needed for sure. Instead, we want to have:
od.getSegmentBookeds().get(segIndex);
How can we directly get a list of segments under an OD?
Solution
Integrate XEW Plugin into your repository and get it executed during Code generation phase.
Simply,
org.jvnet.jaxb2.maven2 maven-jaxb2-plugin 0.13.1 org.jvnet.jaxb2_commons jaxb2-basics 0.6.3 air-ticket-schema generate true -Xannotate -Xxew -Xxew:control ${basedir}/src/main/resources/xsds/xewInclusionExclusion.txt org.jvnet.jaxb2_commons jaxb2-basics-annotate 1.0.2 com.github.jaxb-xew-plugin jaxb-xew-plugin 1.9 com.sun.xml.bind jaxb-xjc 2.2.11 -Djavax.xml.accessExternalSchema=all ${basedir}/src/main/resources/xsds yourXSDsHere.xsd ${basedir}/target/generated-sources ${basedir}/src/main/resources/xsds bindings.xjb false false true
With the above configuration, only 2 classes will be generated.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "OriginDestinationBookedType", propOrder = {
"segmentBookedList"
})
public class OriginDestinationBookedType {
@XmlElement(name = "SegmentBookedList", required = true)
protected List segmentBookedList;
public List getSegmentBookedList() {
return segmentBookedList;
}
public void setSegmentBookedList(List value) {
this.segmentBookedList = value;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SegmentBookedType", propOrder = {
"carrierCode",
"flightNumber"
})
public class SegmentBookedType {
@XmlElement(name = "CarrierCode", required = true)
protected String carrierCode;
@XmlElement(name = "FlightNumber", required = true)
protected String flightNumber;
}
And you are all set. No cursing on XSDs 🙂
ADVANTAGES
- No more List wrapper classes.No more additional clumsy code
- No redundant Null checks
- More readability
- Less Machine Instructions to execute
- Less Memory Footprint of Virtual Functions Table
- More maintainability