“Wrapper”/”non-wrapper” Web services styles are mandated by JAX-RPC and JAX-WS
specifications
and are explained in details in documentation or in other sources, for
example in
this article. However, from my experience, there is still a lot of
confusion among developers about differences between these two styles and also
how a particular style affects design and implementation of a Web service.
First of all, we need to understand that “wrapper”/”non-wrapper” style is a
characteristic of a Web services implementation framework (such as JAX-WS), as
opposed to a style defined in WSDL. In fact “wrapper”/”non-wrapper”
can only be used in conjunction with the document/literal style defined in WSDL.
“wrapper”/”non-wrapper” setting defines how Web service request/reply messages
are interpreted by a Web service provider/consumer. Quite simply, “wrapper”
style tells the Web service provider that the root element of the message (also
called “wrapper element”) represents the name of the operation and it is not
part of the payload. This also means that children of the root element must map
directly to parameters of the operation’s signature. The “non-wrapper” style (also
sometimes called “bare”), does not make this assumption; in this case the entire
message will be passed to the service operation. The reply message is handled in
a similar way.
“Wrapper” style can be used for the following method:
public String produceFullName(
// note we have to provide names in annotations
// to comply with the schema.
// otherwise generic "in0", "in1" names are used.
@WebParam(name = "firstName")String firstName,
@WebParam(name = "lastName") String lastName );
The request SOAP messages for this method will look like this:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<produceFullName xmlns="http://personservice">
<firstName>John</firstName>
<lastName>Doe</lastName>
</produceFullName>
</soap:Body>
</soap:Envelope>
However, suppose we implemented the same function differently:
public String produceFullName(
@WebParam(name = "person",
targetNamespace="http://person")
Person person );
This method can be used with “non-wrapper” style resulting in the following
request message:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<ns2:personExt xmlns:ns2="http://person">
<firstName>John</firstName>
<lastName>Doe</lastName>
</ns2:personExt>
</soap:Body>
</soap:Envelope>
In JAX-WS, “SOAPBinding” annotation can be used to specify the style, e.g.,
@SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.BARE)
.
Note that “wrapper” is the default. In JAX-RPC the “wrapper” style is
specified in the Web service mapping xml file by adding “wrapped-element”
element to the service endpoint mapping.
If you generate your Java artifacts from WSDL file, the “wsdl2java” tool
will automatically assume “wrapper” if operation name matches the wrapper
element name and if some other requirements are met (some “wsdl2java”
implementations also allow to control “wrapper”/”non-wrapper” using a command-line option).
So once again, “wrapper”/”non-wrapper” is a data binding style used in the
context of a particular Web service provider/consumer. It is not part of the
contract of a Web service, since it is not mentioned anywhere in the WSDL file.
In other words, if you are a Web service provider, your consumers don’t have to
know or care whether your implementation style is “wrapper” or “non-wrapper”.
They may very well choose the “non-wrapper” style for their client’s
implementation and this client should interoperate with your “wrapper” service
without a hitch (at least in theory).
In fact, the “wrapper” style is supported widely but not universally.
From what I understand, the support for the “wrapper”
style first appeared in .NET and later on Java-based Web services frameworks
began supporting it as well (in Axis and others). I think it is also supported
by Perl SOAP library. However, this style may not be supported by other languages,
for example, I believe that PHP 5 SOAP engine does not have a notion of the “wrapper”
style.
“Wrapper” style is really an RPC-style binding over “document/literal” WSDL
style. The basic premise of the “wrapper” style is that our service is a remote
method that takes some parameters (as opposed to pure message-based paradigm of
a “non-wrapper” Web service, where method name is not explicitly provided in the message).
So how “wrapper” with “document/literal is better
than “rpc/literal” WSDL style? Here are some of its advantages:
- “Wrapper” service can only have one message part in WSDL, which guarantees that
the message (consisting of the method element that contains parameters) will be
represented by one XML document with a single schema.
- RPC style message definitions in WSDL have to use schema types, whereas with the
document style we can refer directly to element names. This makes XML message
representation more “precise”, it is also easier to validate.
- RPC/literal, while WS-I compliant, fell out of favor and being
frowned upon, not
in small part due to poor Microsoft support.
“Wrapper” style has one interesting drawback, which may not be immediately
obvious. Most Web services engines (at least the ones that I had a chance to
work with) use positional parameter binding with “wrapper” style. This means
that if a service signature changed (e.g., a new parameter was added), clients
will have to change as well. In other words, with “wrapper” style, all
parameters have to be present in the XML message (although they can be defined
as null using “xsd:nil” attribute). This is despite the fact that the element
corresponding to the parameter can be defined as optional in the schema. “non-wrapper”
style does not have this problem; adding a new optional element does not
affect clients, since binding is always name-based. This creates somewhat
tighter coupling between “wrapper” style consumers and providers. This may also
violate the contract of the Web service defined by its schema. To get around
the last problem, you may want to define all child elements of the wrapper root
element as required (minOccurs=1); optional elements must be made nillable. For
some reason JAX-WS spec does not explicitly state this.
JAX-WS, however, does impose some additional restrictions on the “wrapper” style,
the most important one being that the wrapper element’s content type must
be “sequence”. This makes sense, since we’re trying to model a method’s
signature, which is always represented as an ordered list of arguments (at least
in Java/C#).
As far as the “non-wrapper” style goes, probably the most obscure thing about it
deals with how a SOAP engine decides which operation to invoke based on the
message type (assuming a Web service has multiple operations), since operation
name is not explicitly provided by the message (unless “SOAPAction” header is
used, however, this header is HTTP-only and also optional in JAX-WS). With “non-wrapper”,
each operation must accept a message that corresponds to a unique XML element
name. Note that it is not enough to define different WSDL messages using “wsdl:message”
element, each message must be represented by a different element in the schema.
Web service engines use unique element names to determine Java method names (that
correspond to WSDL operations). This means that with “non-wrapper” you can’t
have different operation names processing the same message, e.g., process(Customer)
and processDifferently(Customer) can only be implemented by creating
different customer types.
So we have an interesting dilemma – “wrapper” does not support overloaded methods (in
fact, I don’t think WS-I allows them either), whereas “non-wrapper” does not support
methods with the same signature (at least under certain conditions).
So how should we decide when to use the “wrapper” style? My approach is always
the following:
-
Design good “tight” schemas for your request and reply messages. Do not rely on Java-to-WSDL/Schema
generation. Hopefully, you have good requirements as the basis for your design.
-
You can now see if the request schema matches the Web service operation’s
signature. If that is the case, “wrapper” might be your choice. Consider pros
and cons of each style described above. Basically, “wrapper” provides more “natural”
RPC implementation, whereas “non-wrapper” gives more control and somewhat
looser coupling (from a client’s standpoint). If you decide to go with the “wrapper”,
do not assume that all of your clients will be using the “wrapper” (unless you
know for sure that this will be the case). So make sure that your WSDL can be
easily consumed by both “wrapper” and “non-wrapper” clients. For example, an
element with empty sequence maps to “void” return type if the “wrapper” style is
used; however, “wsdl2java” (or a similar tool used by other languages) will
generate an empty class as the return type for “non-wrapper”. This last option
may not be very intuitive or desirable for your clients.
-
When publishing your service, provide examples of its client implementation. You
may not be able to address all the different languages and platforms; however
covering the most widely used ones (most often, Java in C# in an enterprise environment) is a
good idea. This will help your clients consume your Web service and also clarify
the “wrapper” versus “non-wrapper” question.