CXF Wsdl2java, with a `cannot be unwrapped` error...
By Mathieu CARBONNEAUX
I was trying to generate a java stub from a wsdl (using the wsdl2java tool) in unwrapped mode with CXF (unwrapping is the default mode of the wsdl2java tool)… and I encountered the following error when generating java from the wsdl :
[java] May 22, 2018 4:59:31 PM org.apache.cxf.wsdl11.WSDLServiceBuilder checkForWrapped
[java] INFO: Operation {http://refservices/MonServiceNS}MonService cannot be unwrapped, input message must reference global element declaration with same localname as operation
I searched for a long time to understand where this was coming from…
The message in question can be found here in the CXF source code: https://github.com/apache/cxf/blob/master/rt/wsdl/src/main/java/org/apache/cxf/wsdl11/Messages.properties
WRAPPED_RULE_2 = Operation {0} cannot be unwrapped, input message must reference global element declaration with same localname as operation
It is used here in the CXF source code: https://github.com/apache/cxf/blob/master/rt/wsdl/src/main/java/org/apache/cxf/wsdl11/WSDLServiceBuilder.java
// RULE No.2:
// The input message part refers to a global element declaration whose
// local name is equal to the operation name.
MessagePartInfo inputPart = inputMessage.getMessagePartByIndex(0);
if (!inputPart.isElement()) {
passedRule = false;
} else {
QName inputElementName = inputPart.getElementQName();
inputEl = schemas.getElementByQName(inputElementName);
if (inputEl == null) {
passedRule = false;
} else if (!opInfo.getName().getLocalPart().equals(inputElementName.getLocalPart())) {
passedRule = relaxed;
}
}
if (!passedRule) {
org.apache.cxf.common.i18n.Message message
= new org.apache.cxf.common.i18n.Message("WRAPPED_RULE_2", LOG, opInfo.getName());
LOG.log(logLevel, message.toString());
return;
}
In fact, after some research I realized that it was linked to the Jax-WS standard, because in the v2.2 specification it says the following (same rules controlled in the CXF source code): http://download.oracle.com/otn-pub/jcp/jaxws-2.2-mrel3-evalu-oth-JSpec/jaxws-2_2-mrel3-spec.pdf
**2.3.1.2 Wrapper Style**
A WSDL operation qualifies for wrapper style mapping only if the following criteria are met:
(i) The operation’s input and output messages (if present) each contain only a single part
(ii) The input message part refers to a global element declaration whose localname is equal to the operation name
(iii) The output message (if present) part refers to a global element declaration
(iv) The elements referred to by the input and output message (if present) parts (henceforth referred to as wrapper elements) are both complex types defined using the xsd:sequence compositor
(v) The wrapper elements only contain child elements, they MUST not contain other structures such as wildcards (element or attribute), xsd:choice, substitution groups (element references are not permitted) or attributes; furthermore, they MUST not be nillable.
So the code generator wsdl2java blocks on the ii
rule…
At first glance, the ii
rule isn’t easy to understand on its own … it’s only by reading the CXF source code that I understood its meaning…
In fact, localname
refers to the name
attribute of the element
which defines the type of the input
message of the operation
…
With an example, it’s much clearer…
The MonService
operation refers to an input
message MonServiceMsg
, this message
is composed of a part
(rule i
which indicates that only one part
is needed in the input
to use the unwrapped mode) refers to a typesns:MonService
type, and it’s this type that must have the same name as the operation, in this case MonService
.
So the name
of the <xsd:element name="MonService">
element must be the same as the name
of the operation
<operation name="MonService">
operation.
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://MonService.com"
xmlns:typesns="http://MonService.com/types/"
targetNamespace="http://MonService.com">
<types>
<xsd:schema targetNamespace="http://arcadye.sfr.com/types/"
xmlns="http://arcadye.sfr.com/types/"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:element name="MonService">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="args1" type="xsd:string"/>
<xsd:element name="args2" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
…
<message name="MonServiceMsg">
<part element="typesns:MonService" name="MonService"/>
</message>
…
<portType name="MonService">
<operation name="MonService">
<input message="tns:MonServiceMsg"/>
<output message="tns:MonServiceResponseMsg"/>
</operation>
</portType>
…