WSDL-to-Java: OUT parameters (holders) vs. return types

WSDL and its mapping to Java never fail to puzzle me. The other day I was confused about OUT parameters (holders) vs. return types. CXF‘s wsdl2java produced those ugly and terrible to work methods with OUT parameters in one case and natural methods with return types in other cases. Here’s why.

First the obvious…”If there is more than one output parameter, the second and subsequent output parameters map to method arguments (moreover, the values of these arguments must be passed using Holder types)”.

Holder example

Consider the following WSDL excerpt, methodResponse is a complex type used as a WSDL response message:

<xs:element name="methodResponse">
 <xs:complexType>
   <xs:sequence>
     <xs:element name="nsType" minOccurs="1" maxOccurs="1">
       <xs:complexType>
         <xs:sequence>
           <xs:element ref="someType" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
       </xs:complexType>
     </xs:element>
     <xs:element name="msType" minOccurs="1" maxOccurs="1">
       <xs:complexType>
         <xs:sequence>
           <xs:element ref="someType" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
       </xs:complexType>
     </xs:element>

Both CXF and the JAX-WS Reference Implementation (RI) produce a Java method where both nsType and msType are method OUT parameters as holders. There’s no apparent reason why this should be necessary. It’d be way more natural to have a the method return a MethodResponse object that wraps the two member variables nsType and msType.

Natural example

Turning the two members into references changes the game completely for CXF:

<xs:element name="methodResponse">
 <xs:complexType>
   <xs:sequence>
     <xs:element ref="nsType" minOccurs="1" maxOccurs="1"/>
     <xs:element ref="msType" minOccurs="1" maxOccurs="1"/>
   </xs:sequence>
 </xs:complexType>
</xs:element>
<xs:complexType name="nsType">
 <xs:sequence>
   <xs:element ref="someType" minOccurs="0" maxOccurs="unbounded"/>
 </xs:sequence>
</xs:complexType>
<xs:complexType name="msType">
 <xs:sequence>
   <xs:element ref="someType" minOccurs="0" maxOccurs="unbounded"/>
 </xs:sequence>
</xs:complexType>

CXF (by default, there is the -allowElementRefs flag to wsdl2java) doesn’t consider them as unwrappable and thus will put the operation in BARE mode when it encounters them. Therefore, the operation returns a MethodResponse object that wraps the two member variables nsType and msType. The RI does consider them unwrappable and will generate the holders.

If you don’t like the holders, the “official” way around it is to create a jaxws binding file that forces BARE mode on everything. With CXF, the easier method is to just pass -bareMethods to wsdl2java.

Leave a Reply