You are on page 1of 70

JAX-RPC vs JAX-WS

Java API for XML-Based RPC (JAX-RPC) is a


Legacy Web Services Java API, it uses SOAP
and HTTP to do RPCs over the network and
enables building of Web services and Web
applications based on the SOAP 1.1
specification, Java SE 1.4 or lower, or when
rpc/encoded style must be used.

You can use the JAX-RPC programming


model to develop SOAP-based web service
clients and endpoints. JAX-RPC enables
clients to invoke web services developed
across heterogeneous platforms. Likewise,
JAX-RPC web service endpoints can be
invoked by heterogeneous clients. JAX-RPC
requires SOAP and WSDL standards for this
cross-platform interoperability.

JAX-RPC lets people develop a web service


endpoint using either a Servlet or Enterprise
JavaBeans (EJB) component model. The
endpoint is then deployed on either the Web
or EJB container, based on the
corresponding component model. Endpoints
are described using a Web Services
Description Language (WSDL) document.
(This WSDL document can be published in a
public or private registry, though this is not
required). A client then uses this WSDL
document and invokes the web service
endpoint.

JAX-RPC in J2ee 1.4 supports 4 types of


stubs and invocations: static stub, dynamic
proxy, Dynamic Invocation Interface (DII)
and Application client.

Static Stub Client


Web service client makes a call through a
stub, a local object that acts as a proxy for
the remote service. Because the stub is
created by wscompile at development time
(as opposed to runtime), it is usually called
a static stub.

Example: Invoking a Stub Client


Stub stub = (Stub) (new
MyHelloService_Impl().getHelloIFPort());
stub._setProperty
(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPE
RTY,endpoint_address_string);
HelloIF hello = (HelloIF)stub;
System.out.println(hello.sayHello("Duke!")
);
Dynamic Proxy Client
In contrast, the client call a remote
procedure through a dynamic proxy, a class
that is created during runtime. Although the
source code for the static stub client relies
on an implementation-specific class, the
code for the dynamic proxy client does not
have this limitation.

Example: Dynamic Proxy


javax.xml.rpc.Service service =
ServiceFactory.newInstance().createService
(...);
com.example.StockQuoteProvider sqp =
(com.example.StockQuoteProvider)service.ge
tPort(portName, StockQuoteProvider.class);
float price =
sqp.getLastTradePrice("ACME");

Dynamic Invocation Interface Client


With the dynamic invocation interface (DII),
a client can call a remote procedure even if
the signature of the remote procedure or the
name of the service is unknown until
runtime. In contrast to a static stub or
dynamic proxy client, a DII client does not
require runtime classes generated by
wscompile.
Example: Dynamic Invocation Interface
javax.xml.rpc.Service service =
ServiceFactory.newInstance().createService
(...);
javax.xml.rpc.Call call =
service.createCall(portName,
"getLastTradePrice");
// This example assumes that addParameter
and setReturnType methods are not required
to be called
Object[] inParams = new Object[] {"ACME"};
Float quotePrice =
(Float)call.invoke(inParams);

Application Client
Unlike the stand-alone clients, for an
application client, because it's a J2EE
component, an application client can locate
a local web service by invoking the JNDI
lookup method.

Example: Application Client


Context ic = new InitialContext();
MyHelloService myHelloService =
(MyHelloService)
ic.lookup("java:comp/env/service/MyJAXRPCH
ello");
appclient.HelloIF helloPort =
myHelloService.getHelloIFPort();
((Stub)helloPort)._setProperty(Stub.ENDPOI
NT_ADDRESS_PROPERTY,args[0]);
System.out.println(helloPort.sayHello("Jak
e!"));

Service Endpoint Model


JAX-RPC supports a client model for the
service consumer, and a service endpoint
model for the service producer.

Application-Level Interaction Modes


JAX-RPC specifies three client application
interaction models:
* Synchronous request-response two-way
RPC
* Asynchronous (non-blocking) request-
response two-way RPC
* One-way RPC

JAX-WS

JAX-WS 2.0 is the successor of JAX-RPC 1.1


- the Java API for XML-based Web services.
If possible, JAX-WS should be used instead
as it is based on the most recent industry
standards.

What remains the same?


Before we itemize the differences between
JAX-RPC 1.1 and JAX-WS 2.0, we should
first discuss what is the same.

* JAX-WS still supports SOAP 1.1 over HTTP


1.1, so interoperability will not be affected.
The same messages can still flow across the
wire.

* JAX-WS still supports WSDL 1.1, so what


you've learned about that specification is
still useful. A WSDL 2.0 specification is
nearing completion, but it was still in the
works at the time that JAX-WS 2.0 was
finalized.

What is different?

* SOAP 1.2
JAX-RPC and JAX-WS support SOAP 1.1.
JAX-WS also supports SOAP 1.2.

* XML/HTTP
The WSDL 1.1 specification defined an HTTP
binding, which is a means by which you can
send XML messages over HTTP without
SOAP. JAX-RPC ignored the HTTP binding.
JAX-WS adds support for it.

* WS-I's Basic Profiles


JAX-RPC supports WS-I's Basic Profile (BP)
version 1.0. JAX-WS supports BP 1.1. (WS-I
is the Web services interoperability
organization.)

* New Java features


o JAX-RPC maps to Java 1.4. JAX-WS maps
to Java 5.0. JAX-WS relies on many of the
features new in Java 5.0.
o Java EE 5, the successor to J2EE 1.4, adds
support for JAX-WS, but it also retains
support for JAX-RPC, which could be
confusing to today's Web services novices.

* The data mapping model


o JAX-RPC has its own data mapping model,
which covers about 90 percent of all schema
types. Those that it does not cover are
mapped to javax.xml.soap.SOAPElement.
o JAX-WS's data mapping model is JAXB.
JAXB promises mappings for all XML
schemas.

* The interface mapping model


JAX-WS's basic interface mapping model is
not extensively different from JAX-RPC's;
however:
o JAX-WS's model makes use of new Java
5.0 features.
o JAX-WS's model introduces asynchronous
functionality.

* The dynamic programming model


o JAX-WS's dynamic client model is quite
different from JAX-RPC's. Many of the
changes acknowledge industry needs:
+ It introduces message-oriented
functionality.
+ It introduces dynamic asynchronous
functionality.
o JAX-WS also adds a dynamic server
model, which JAX-RPC does not have.

* MTOM (Message Transmission


Optimization Mechanism)
JAX-WS, via JAXB, adds support for MTOM,
the new attachment specification. Microsoft
never bought into the SOAP with
Attachments specification; but it appears
that everyone supports MTOM, so
attachment interoperability should become a
reality.
* The handler model
o The handler model has changed quite a bit
from JAX-RPC to JAX-WS.
o JAX-RPC handlers rely on SAAJ 1.2. JAX-
WS handlers rely on the new SAAJ 1.3
specification.

JAX-RPC versus JAX-WS

Introduction
Web services have been around a while now.
First there was SOAP. But SOAP only described
what the messages looked like. Then there was
WSDL. But WSDL didn't tell you how to write
web services in Java™. Then along came JAX-
RPC 1.0. After a few months of use, the Java
Community Process (JCP) folks who wrote that
specification realized that it needed a few
tweaks, so out came JAX-RPC 1.1. After a year
or so of using that specification, the JCP folks
wanted to build a better version: JAX-RPC 2.0.
A primary goal was to align with industry
direction, but the industry was not merely
doing RPC web services, they were also doing
message-oriented web services. So "RPC" was
removed from the name and replaced with
"WS" (which stands for web Services, of
course). Thus the successor to JAX-RPC 1.1 is
JAX-WS 2.0 - the Java API for XML-based web
services.
What remains the same?
Before we itemize the differences between
JAX-RPC 1.1 and JAX-WS 2.0, we should first
discuss what is the same.
• JAX-WS still supports SOAP 1.1 over HTTP
1.1, so interoperability will not be affected.
The same messages can still flow across
the wire.
• JAX-WS still supports WSDL 1.1, so what
you've learned about that specification is
still useful. A WSDL 2.0 specification is
nearing completion, but it was still in the
works at the time that JAX-WS 2.0 was
finalized.
What is different?
• SOAP 1.2
JAX-RPC and JAX-WS support SOAP 1.1.
JAX-WS also supports SOAP 1.2.
• XML/HTTP
The WSDL 1.1 specification defined an
HTTP binding, which is a means by which
you can send XML messages over HTTP
without SOAP. JAX-RPC ignored the HTTP
binding. JAX-WS adds support for it.
• WS-I's Basic Profiles
JAX-RPC supports WS-I's Basic Profile (BP)
version 1.0. JAX-WS supports BP 1.1. (WS-
I is the web services interoperability
organization.)
• New Java features
o JAX-RPC maps to Java 1.4. JAX-WS

maps to Java 5.0. JAX-WS relies on


many of the features new in Java 5.0.
o Java EE 5, the successor to J2EE 1.4,

adds support for JAX-WS, but it also


retains support for JAX-RPC, which
could be confusing to today's web
services novices.
• The data mapping model
o JAX-RPC has its own data mapping

model, which covers about 90 percent


of all schema types. Those that it does
not cover are mapped to
javax.xml.soap.SOAPElement.
o JAX-WS's data mapping model is JAXB.
JAXB promises mappings for all XML
schemas.
• The interface mapping model
JAX-WS's basic interface mapping model is
not extensively different from JAX-RPC's;
however:
o JAX-WS's model makes use of new
Java 5.0 features.
o JAX-WS's model introduces

asynchronous functionality.
• The dynamic programming model
o JAX-WS's dynamic client model is quite

different from JAX-RPC's. Many of the


changes acknowledge industry needs:
 It introduces message-oriented

functionality.
 It introduces dynamic

asynchronous functionality.
o JAX-WS also adds a dynamic server

model, which JAX-RPC does not have.


• MTOM (Message Transmission Optimization
Mechanism)
JAX-WS, via JAXB, adds support for MTOM,
the new attachment specification. Microsoft
never bought into the SOAP with
Attachments specification; but it appears
that everyone supports MTOM, so
attachment interoperability should become
a reality.
• The handler model
o The handler model has changed quite a

bit from JAX-RPC to JAX-WS.


o JAX-RPC handlers rely on SAAJ 1.2.

JAX-WS handlers rely on the new SAAJ


1.3 specification.
In the remainder of this tip, we will discuss
SOAP 1.2, XML/HTTP, the WS-I Basic Profiles,
and Java 5. Each of the remaining five bullets
above will be a separate tip in this series.

SOAP encoding
SOAP encoding has fallen out of favor in the
web services community. It is not supported
by the WS-I basic profile. So JAX-WS, as the
latest incarnation of Java web services, has
disallowed SOAP encoding. JAX-RPC supports
SOAP encoding, so if you really must use SOAP
encoded messages, stick with JAX-RPC.
SOAP 1.2
There is really not a lot of difference, from a
programming model point of view, between
SOAP 1.1 and SOAP 1.2. As a Java
programmer, the only place you will encounter
these differences is when using the handlers,
which we will cover in a future tip. SAAJ 1.3
has been updated to support SOAP 1.2.
XML/HTTP
Like the changes for SOAP 1.2, there is really
not a lot of difference, from a programming
model point of view, between SOAP/HTTP and
XML/HTTP messages. As a Java programmer,
the only place you will encounter these
differences is when using the handlers, which
we will cover in a future tip. The HTTP binding
has its own handler chain and its own set of
message context properties.
WS-I's basic profiles
JAX-RPC 1.1 supports WS-I's Basic Profile (BP)
1.0. Since that time, the WS-I folks have
developed BP 1.1 (and the associated AP 1.0
and SSBP 1.0). These new profiles clarify some
minor points, and more clearly define
attachments. JAX-WS 2.0 supports these
newer profiles. For the most part, the
differences between them do not affect the
Java programming model. The exception is
attachments. WS-I not only cleared up some
questions about attachments, but they also
defined their own XML attachment type:
wsi:swaRef.
Many people are confused by all these profiles.
You will need a little history to clear up the
confusion.
WS-I's first basic profile (BP 1.0) did a good
job of clarifying the various specs. But it wasn't
perfect. And support for SOAP with
Attachments (Sw/A) in particular was still
rather fuzzy. In their second iteration, the WS-
I folks pulled attachments out of the basic
profile - BP 1.1 - and fixed some of the things
they missed the first time around. At that point
they also added two mutually exclusive
supplements to the basic profile: AP 1.0 and
SSBP 1.0. AP 1.0 is the Attachment Profile
which describes how to use Sw/A. SSBP 1.0 is
the Simple SOAP Binding Profile, which
describes a web services engine that does not
support Sw/A (such as Microsoft's .NET). The
remaining profiles that WS-I has and is
working on build on top of those basic profiles.
Java 5
There are a number of changes to the Java
language. JAX-WS relies on: annotations,
generics, and executors. We will detail exactly
how JAX-WS relies on this new functionality in
follow-on tips. For information on these new
features of Java, see the Java 5 link in
Resources.
Summary
JAX-WS 2.0 is the successor to JAX-RPC 1.1.
There are some things that haven't changed,
but most of the programming model is
different to a greater or lesser degree. The
topics introduced in this tip will be expanded
upon in a series of tips which we will publish
over the coming months that will compare, in
detail, JAX-WS and JAX-RPC. At a high level
though, here are a few reasons why you would
or would not want to move to JAX-WS from
JAX-RPC.
Reasons you may want to stay with JAX-RPC
1.1:
• If you want to stay with something that's
been around a while, JAX-RPC will continue
to be supported for some time to come.
• If you don't want to step up to Java 5.
• If you want to send SOAP encoded
messages or create RPC/encoded style
WSDL.
Reasons to step up to JAX-WS 2.0:
• If you want to use the new message-
oriented APIs.
• If you want to use MTOM to send
attachment data.
• If you want better support for XML schema
through JAXB.
• If you want to use an asynchronous
programming model in your web service
clients.
• If you need to have clients or services that
can handle SOAP 1.2 messages.
• If you want to eliminate the need for SOAP
in your web services and just use the
XML/HTTP binding.
• If you like playing with leading edge
technology.
Mapping XML schema to Java

JAX-RPC and JAXB


Why didn't JAX-RPC use JAXB in the first place? The
answer is timing. The first version of JAX-RPC was
completed before JAXB, so rather than wait, the
writers of JAX-RPC developed their own mapping
feature.

Mapping XML names to Java names in JAX-RPC and


JAX-WS/JAXB are essentially the same, while
mapping simple types has some slight differences.
Table 1 shows these differences, which may appear
significant; however, except for date/time types,
they're the least-used XML simple types.

Table 1. Mapping differences between JAX-RPC


1.1 and JAXB 2.0 for XML simple types
Type JAX-RPC 1.1 JAXB 2.0
xsd:anySimpleTypejava.lang.String java.lang.Object
xsd:duration java.lang.String javax.xml.datatype.Duration
javax.xml.datatype.XMLGre
xsd:dateTime java.util.Calendar
(new type)
xsd:time java.util.Calendarjavax.xml.datatype.XMLGre
xsd:date java.util.Calendarjavax.xml.datatype.XMLGre
xsd:gYearMonth java.lang.String javax.xml.datatype.XMLGre
xsd:gYear java.lang.String javax.xml.datatype.XMLGre
xsd:gMonthDay java.lang.String javax.xml.datatype.XMLGre
xsd:gMonth java.lang.String javax.xml.datatype.XMLGre
xsd:gDay java.lang.String javax.xml.datatype.XMLGre
xsd:anyURI java.net.URI java.lang.String
xsd:NMTOKENS java.lang.String[]java.util.List<java.lang.Strin
xsd:IDREF java.lang.String java.lang.Object
xsd:IDREFS java.lang.String[]java.util.List<java.lang.Obje
xsd:ENTITY not supported java.lang.String
xsd:ENTITIES not supported java.util.List<java.lang.Strin

The pure Java aspects of the simple type mappings


are nearly the same between JAX-RPC and JAXB, but
the JAXB mappings also use the new Java annotation
feature. See Listings 1 through 3 for some examples
of simple type mappings.

Listing 1. XML complexType elements and


attributes
<xsd:sequence>
<xsd:element name="intField" type="xsd:int"/>
<xsd:element name="intMinField" type="xsd:int"
minOccurs="0"/>
<xsd:element name="intNilField" type="xsd:int"
nillable="true"/>
<xsd:element name="stringField"
type="xsd:string"/>
<xsd:element name="stringMinField"
type="xsd:string" minOccurs="0"/>
<xsd:element name="stringNilField"
type="xsd:string" nillable="true"/>
</xsd:sequence>
<xsd:attribute name="intAttr" type="xsd:int"/>
<xsd:attribute name="intAttrReq" type="xsd:int"
use="required"/>

Listing 2. Mapping to Java Bean properties via


JAX-RPC 1.1
private int intField;
private Integer intMinField;
private Integer intNilField;
private String stringField;
private String stringMinField;
private String stringNilField;
private Integer intAtt;
private int intAttReq;

Listing 3. Mapping to Java Bean properties via


JAXB 2.0
protected int intField;
protected Integer intMinField;

@XmlElement(required = true, type =


Integer.class, nillable = true)
protected Integer intNilField;

@XmlElement(required = true)
protected String stringField;

protected String stringMinField;

@XmlElement(required = true, nillable = true)


protected String stringNilField;

@XmlAttribute
protected Integer intAtt;

@XmlAttribute(required = true)
protected int intAttReq;

In a JAX-RPC 1.1-generated Java Bean, you cannot


tell the difference between:

• An element field and an attribute field


• A field mapped from minOccurs="0"
type="xsd:int" and a field mapped from
nillable="true" type="xsd:int"
• A field mapped from type="xsd:string" and
type="xsd:string" minOccurs="0"

But now you can, thanks to JAXB's use of new Java


annotations. The @XmlElement and @XmlAttribute
annotations have several parameters. The ones
pertinent to this article include:

• Required: Must the element exist? For example,


is minOccurs something other than one?
• Nillable: Does the field contain the
nillable="true" attribute?
Mapping arrays

Mapping arrays from XML to Java differs between


JAX-RPC and JAXB because JAXB uses the new
generic Java feature, as Listings 4 through 6 show.

Listing 4. XML array


<xsd:element name="intArrayField" type="xsd:int"
minOccurs="0" maxOccurs="unbounded"/>

Listing 5. Mapping to Java Bean properties via


JAX-RPC 1.1
private int[] intArrayField;
public int[] getIntArrayField() {...}
public void setIntArrayField(int[]
intArrayField) {...}
public int getIntArrayField(int i) {...}
public void setIntArrayField(int i, int value)
{...}

Listing 6. Mapping to Java Bean properties via


JAXB 2.0
@XmlElement(type = Integer.class)
protected List<Integer> intArrayField;
public List<Integer> getIntArrayField() {...}

Notice the differences in the accessor methods. The


JAX-RPC mapping follows the strict definition of Java
Bean array accessors. The JAXB mapping does not
map to an array, so it slightly differs.
getIntArrayField returns a reference, not just a
snapshot, to the live list. Therefore, any modification
you make to the returned list will be present inside
the property. This is why no set method exists for
'array' properties.

Mapping complex types

Mapping a complexType is nearly the same between


JAX-RPC and JAXB, except the fields are private in
JAX-RPC and protected in JAXB, and the JAXB
mapping adds annotations describing the field order.
See Listings 7 through 9 for an example and
comparisons between the two mappings.

Listing 7. XML schema complexType


<xsd:element name="Phone" type="tns:Phone"/>
<xsd:complexType name="Phone">
<xsd:sequence>
<xsd:element name="areaCode"
type="xsd:string"/>
<xsd:element name="exchange"
type="xsd:string"/>
<xsd:element name="number"
type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>

Listing 8. JAX-RPC 1.1 mapping of complexType


public class Phone {
private String areaCode;
private String exchange;
private String number;

...
}

Listing 9. JAXB 2.0 mapping of complexType


@XmlType(name = "Phone", propOrder = {
"areaCode",
"exchange",
"number"
})
public class Phone {

@XmlElement(required = true)
protected String areaCode;
@XmlElement(required = true)
protected String exchange;
@XmlElement(required = true)
protected String number;

...
}

Note that the schema in Listing 7 used xsd:sequence.


If it had used xsd:all instead, the propOrder
annotation would have been empty: @XmlType(name =
"Phone", propOrder = {}).

The new ObjectFactory class

JAXB generates a file that JAX-RPC does not:


ObjectFactory. Each directory containing Java Beans
will have one ObjectFactory. For each type defined in
the schema's corresponding namespace, the
ObjectFactory class will have a create method for
that type. For each element, the ObjectFactory class
will have a create element method, which returns a
javax.xml.bind.JAXBElement<Type>. For example, for
the Phone schema in Listing 7, Listing 10 shows the
generated ObjectFactory class with a method that
returns an instance of Phone and a method that
returns an instance of JAXBElement<Phone>. You can
still directly instantiate the Java Beans in the
directory, but it would be best to use the factory.

Listing 10. JAXB 2.0 ObjectFactory for Phone


import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.namespace.QName;

public class ObjectFactory {

private final static QName _Phone_QNAME = new


QName
("urn:types.MyServiceSample.ibm.com", "Phone");

public ObjectFactory() {...}

public Phone createPhone() {...}

@XmlElementDecl(namespace =
"urn:types.MyServiceSample.ibm.com", name =
"Phone")
public JAXBElement<Phone> createPhone(Phone
value) {...}
}

Java to XML schema mappings


With a judicious sprinkling of these new JAXB-
defined annotations, Java can map in a well-directed
manner to XML, essentially in the reverse of the
XML-to-Java mappings that we have presented. But
what about unannotated Java?

Mapping Java names to XML names in JAX-RPC and


JAXB are essentially the same. That is, Java primitive
types map to the same XML schema whether the
mapping follows JAX-RPC or JAXB. JAX-RPC defines a
small set of standard Java classes that map to XML.
For all but one of those, JAXB maps precisely the
same, but JAXB adds a few more to its list of
mapped classes, as Table 2 shows.

Table 2. Mapping differences between JAX-RPC


1.1 and JAXB 2.0 for standard Java classes
JAX-RPC
Type JAXB 2.0
1.1
java.lang.String xsd:string xsd:string
java.math.BigInteger xsd:integer xsd:integer
java.math.BigDecimal xsd:decimal xsd:decimal
xsd:dateTim
java.util.Calendar xsd:dateTime
e
xsd:dateTim
java.util.Date xsd:dateTime
e
javax.xml.namespace.QNamexsd:QName xsd:QName
java.net.URI xsd:anyURI xsd:string
javax.xml.datatype.
n/a xsd:anySimpleType
XMLGregorianCalendar
javax.xml.datatype.Duration n/a xsd:duration
java.lang.Object n/a1 xsd:anyType
java.awt.Image n/a2 xsd:base64Binary
javax.activation.DataHandler n/a2 xsd:base64Binary
javax.xml.transform.Source n/a2 xsd:base64Binary
java.util.UUID n/a xsd:string

Table 2 Notes:
1. Some vendors mapped java.lang.Object to
xsd:anyType.
2. In JAX-RPC, this is mapped to a mime binding
type - the XML type is undefined.

Conclusion

We've compared the mappings of JAX-RPC 1.1 and


JAXB 2.0. They are similar with some notable
exceptions:

• XML to Java:
o A few of the simple types are mapped
differently
o JAXB adds the ObjectFactory class
o JAXB makes use of the new Java language
annotation feature and generic feature
• Java to XML:
o The primitive type mappings are identical
o The standard Java mappings are nearly
identical

We can say much more about the JAXB 2.0


specification, particularly its use of Java annotations,
but that topic is out of this article's scope. For more
information about JAXB 2.0, see Resources.

Introduction
Overall, the structures of a Java API for XML-based
RPC (JAX-RPC) 1.1 service endpoint interface (SEI)
and a Java API for XML Web Services (JAX-WS) 2.0
SEI are very similar. This article addresses the
differences. Even with differences in structure,
however, the goal of providing an interface that
reflects the contract of the Web service is the same.

Comparing SEI mapping

Listing 1 shows the WSDL for a simple HelloWorld


Web service.

Listing 1. HelloWorld WSDL


<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="urn:helloWorld/sample/ibm/com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/
"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="HelloWorld"
targetNamespace="urn:helloWorld/sample/ibm/c
om">
<wsdl:types>
<xsd:schema
targetNamespace="urn:helloWorld/sample/ibm/com"
xmlns:tns="urn:helloWorld/sample/ibm/com"
xmlns:xsd="http://www.w3.org/2001/XMLSchem
a">
<xsd:element name="hello">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name"
nillable="true" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="helloResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="response"
nillable="true" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="helloRequestMsg">
<wsdl:part element="tns:hello"
name="helloParameters" />
</wsdl:message>
<wsdl:message name="helloResponseMsg">
<wsdl:part element="tns:helloResponse"
name="helloResult" />
</wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="hello">
<wsdl:input message="tns:helloRequestMsg"
name="helloRequest" />
<wsdl:output message="tns:helloResponseMsg"
name="helloResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorldBinding"
type="tns:HelloWorld">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" /
>
<wsdl:operation name="hello">
<soap:operation
soapAction="urn:helloWorld/sample/ibm/com/hello" /
>
<wsdl:input name="helloRequest">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="helloResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorldService">
<wsdl:port name="port"
binding="tns:HelloWorldBinding">
<soap:address location="http://tempuri.org/"
/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

Listing 2 shows the JAX-RPC mapping of the Java SEI


from this WSDL without the method signatures (you
will see more about those later).

Listing 2. JAX-RPC HelloWorld SEI


package com.ibm.samples;
public interface HelloWorld extends
java.rmi.Remote {
...
}

Listing 3 shows the JAX-WS SEI for the same WSDL.

Listing 3. JAX-WS HelloWorld SEI


package com.ibm.samples.helloworld;

import javax.jws.WebService;

@WebService(name = "HelloWorld",
targetNamespace =
"urn:samples.ibm.com/HelloWorld")
public interface HelloWorld {
...
}

There are three differences here:

• Package: The target namespace is


"urn:helloWorld/sample/ibm/com". Both
mappings take the domain name-like string and
reverse the order of the elements. JAX-RPC's
mapping stops at the first slash. JAX-WS's
mapping continues with the string, adding the
information after the first slash. Both
specifications allow for custom namespace-to-
package mappings.
• Annotations: JAX-WS requires that all SEIs
include the @WebService annotation. As
mentioned in Part 1 of this series, JAX-WS
includes support for the annotations defined in
JSR-181 Web Services Metadata.
• java.rmi.Remote: The JAX-RPC SEI extends the
java.rmi.Remote interface. JAX-WS no longer
requires this.

Before moving into the details of operation


mappings, there is one last thing about the SEI
itself. Although JAX-WS provides support for Web
services that have an SEI, this is not mandatory for
all services. With JAX-WS, a JavaBean can be
deployed on its own as a Web service
implementation, as opposed to JAX-RPC where the
bean must include an SEI. JAX-WS services deployed
without an SEI are considered to have an implicit
SEI.

Comparing operation mapping

Now that you have seen the interfaces, look at the


comparison of how the operations are mapped.
There are different ways of designing a WSDL
document to represent Web services that have
similar semantics. The article Which style of WSDL
should I use? provides an overview of the different
styles of WSDL documents available and how to
determine which is best for you.

Now, look at how JAX-RPC and JAX-WS map to each


of the WSDL styles.

Exploring the document/literal wrapped pattern

The WSDL in Listing 1 is formatted using the


document/literal wrapped pattern. Listings 4 and 5
are mappings for the same wrapped operation in
JAX-RPC and JAX-WS. Notice that JAX-WS adds the
@RequestWrapper and @ResponseWrapper annotations to
the method. These provide additional metadata
about both the elements that will serve as the
operation wrapper along with any Java beans that
might have been generated for those wrapper
elements. These annotations are optional.

Listing 4. JAX-RPC complete HelloWorld SEI


package com.ibm.samples;

public interface HelloWorld extends


java.rmi.Remote {
public java.lang.String
hello(java.lang.String name) throws
java.rmi.RemoteException;
}

Listing 5. JAX-WS complete HelloWorld SEI


package com.ibm.samples.helloworld;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

@WebService(name = "HelloWorld",
targetNamespace =
"urn:samples.ibm.com/HelloWorld")
public interface HelloWorld {

@WebMethod(action =
"urn:samples.ibm.com/HelloWorld/hello")
@WebResult(name = "response",
targetNamespace = "")
@RequestWrapper(localName = "hello",
targetNamespace =
"urn:samples.ibm.com/HelloWorld",
className =
"com.ibm.samples.helloworld.Hello")
@ResponseWrapper(localName =
"helloResponse",
targetNamespace =
"urn:samples.ibm.com/HelloWorld",
className =
"com.ibm.samples.helloworld.HelloResponse")
public String hello(
@WebParam(name = "name",
targetNamespace = "")
String name);
}

As you can see, the JAX-WS mapping again has a lot


of annotations, but when you get down to the root
signature, the only difference is that the JAX-RPC
method can throw java.rmi.RemoteException while
the JAX-WS method is not defined to do so.

Exploring document/literal patterns

Both JAX-RPC and JAX-WS support mapping


operations that are document/literal, but are not
wrapped. To accomplish this with the HelloWorld
sample, you would need to remove the wrapper
elements that represent the operation name. Listing
6 shows what the relevant portions of the WSDL
document would look like in comparison to the WSDL
in Listing 1.

Listing 6. Document/literal WSDL


<wsdl:types>
<xsd:schema
targetNamespace="urn:helloWorld/sample/ibm/com"
xmlns:tns="urn:helloWorld/sample/ibm/com"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
<xsd:element name="hello"
type="xsd:string"/>
<xsd:element name="helloResponse"
type="xsd:string"/>
</xsd:schema>
</wsdl:types>

<wsdl:message name="helloRequestMsg">
<wsdl:part element="tns:hello"
name="helloParameters" />
</wsdl:message>

<wsdl:message name="helloResponseMsg">
<wsdl:part element="tns:helloResponse"
name="helloResult" />
</wsdl:message>

Now look at the Java mapping for this new WSDL.


Listings 7 and 8 show the JAX-RPC and JAX-WS
mappings respectively. Do you see how similar the
JAX-RPC mapping is? The only difference is the
parameter name. As with the previous case, putting
the annotations aside, there is no real difference
between the JAX-RPC mapping and the JAX-WS
mapping.

Listing 7. JAX-RPC document/literal mapping


public interface HelloWorld extends
java.rmi.Remote {
public java.lang.String
hello(java.lang.String
helloParameters)
throws
java.rmi.RemoteException;
}
Listing 8. JAX-WS document/literal mapping
@WebService(name = "HelloWorld",
targetNamespace =
"urn:helloWorld/sample/ibm/com")
@SOAPBinding(parameterStyle =
ParameterStyle.BARE)
public interface HelloWorld {

@WebMethod(action =
"urn:helloWorld/sample/ibm/com/hello")
@WebResult(name = "helloResponse",
targetNamespace =
"urn:helloWorld/sample/ibm/com",
partName = "helloResult")
public String hello(
@WebParam(name = "hello",
targetNamespace =
"urn:helloWorld/sample/ibm/com",
partName =
"helloParameters")
String helloParameters);

Notice that for JAX-WS, you no longer see the


@RequestWrapper and @ResponseWrapper annotations.
Also note that a new annotation appears at the
interface level as well, @SOAPBinding. This annotation
provides information about the parameter style. If
absent, the default value for the parameterStyle
attribute is wrapped, which would be like the WSDL
in Listing 1.

Exploring the RPC/literal patterns


The next example is somewhat different from the
previous two. With an RPC/literal style WSDL, the
parts are defined in terms of types rather than
elements. Listing 9 contains the relevant WSDL
differences.

Listing 9. RPC/literal WSDL changes


<wsdl:types/>

<wsdl:message
name="helloRequestMsg">
<wsdl:part name="helloParameters"
type="xsd:string"/>
</wsdl:message>

<wsdl:message
name="helloResponseMsg">
<wsdl:part name="helloResult"
type="xsd:string"/>
</wsdl:message>

The Java mappings in Listings 10 and 11 reflect the


changes to the WSDL. Again, you see an identical
mapping when the annotations are stripped away.

Listing 10. JAX-RPC RPC/literal mapping


public interface HelloWorld extends
java.rmi.Remote {
public java.lang.String
hello(java.lang.String
helloParameters)
throws
java.rmi.RemoteException;
}

Listing 11. JAX-WS RPC/Literal mapping


@WebService(name = "HelloWorld",
targetNamespace =
"urn:helloWorld/sample/ibm/com")
@SOAPBinding(style = Style.RPC)
public interface HelloWorld {

@WebMethod(action =
"urn:helloWorld/sample/ibm/com/hello")
@WebResult(name = "helloResult",
partName = "helloResult")
public String hello(
@WebParam(name =
"helloParameters", partName =
"helloParameters")
String helloParameters);

Comparing this JAX-WS interface to the previous,


you see that the @SOAPBinding annotation remains,
but now it is not used for the parameter style, but
rather the WSDL style.

Exploring the RPC/encoded patterns

There is no comparison for RPC/encoded style


operations that can be made. JAX-WS does not
support any mappings for WSDL documents that
contain an encoded representation for the data. This
comes from JAX-WS's compliance with WS-I's Basic
Profile 1.1, which does not allow usage of encoded
WSDL documents. There are good reasons to build
an RPC/encoded Web service, in which case you
should stick with the JAX-RPC mappings, but if you
want to write interoperable Web services, you should
not use RPC/encoded.

Considering other differences

A major difference in operation mapping for JAX-WS


over JAX-RPC is the introduction of asynchronous
operations. Any WSDL operation with a two-way
message flow, or one where the client expects to
receive a response, can be mapped to an
asynchronous Java representation. There are two
different mechanisms, asynchronous with a callback
and asynchronous polling, that require two different
mappings. A future article will describe how these
two types of operations work. This article just shows
you an example. Listing 12 contains an
asynchronous callback operation, where the
javax.xml.ws.AsyncHandler object is the callback
object. Listing 13 contains an asynchronous polling
operation mapping.

Listing 12. JAX-WS asynchronous callback


@WebMethod(action =
"urn:samples.ibm.com/HelloWorld/hello")
@RequestWrapper(localName = "hello",
targetNamespace =
"urn:samples.ibm.com/HelloWorld",
className =
"com.ibm.samples.helloworld.Hello")
@ResponseWrapper(localName =
"helloResponse",
targetNamespace =
"urn:samples.ibm.com/HelloWorld",
className =
"com.ibm.samples.helloworld.HelloResponse")
public Future<?> helloAsync(
@WebParam(name = "name",
targetNamespace = "")
String name,
@WebParam(name = "asyncHandler",
targetNamespace = "")
AsyncHandler<String> asyncHandler);

Listing 13. JAX-WS asynchronous polling


@WebMethod(action =
"urn:samples.ibm.com/HelloWorld/hello")
@RequestWrapper(localName = "hello",
targetNamespace =
"urn:samples.ibm.com/HelloWorld",
className =
"com.ibm.samples.helloworld.Hello")
@ResponseWrapper(localName =
"helloResponse",
targetNamespace =
"urn:samples.ibm.com/HelloWorld",
className =
"com.ibm.samples.helloworld.HelloResponse")
public Response<String> helloAsync(
@WebParam(name = "name",
targetNamespace = "")
String name);

There is no asynchronous mapping for WSDL


operations in JAX-RPC, so you do not have anything
to make a comparison to here. One important note,
however, is that the asynchronous mappings only
apply to the client side. No such asynchronous
mappings exist for service endpoints, only for clients.

Comparing IN/OUT parameters

Both JAX-RPC and JAX-WS support parameters


known as IN/OUT parameters. In Listing 14, you see
an IN/OUT parameter added to the WSDL from
Listing 1. Notice that the parameter with the name
"inout" appears in both the input and the output. In
this scenario, both JAX-RPC and JAX-WS map that
parameter to a holder parameter, but the impact this
has is different for each mapping.

Listing 14. A WSDL with an IN/OUT parameter


<xsd:element name="hello">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name"
nillable="true" type="xsd:string" />
<xsd:element name="inout"
nillable="true" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:element name="helloResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="response"
nillable="true" type="xsd:string" />
<xsd:element name="inout"
nillable="true" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

Listing 15 has the JAX-RPC mapping for a holder


parameter, and Listing 16 has the JAX-WS mapping.

Listing 15. JAX-RPC SEI with IN/OUT


parameters
public interface HelloWorld extends
java.rmi.Remote {
public java.lang.String hello(
java.lang.String name,
javax.xml.rpc.holders.Strin
gHolder inout) throws
java.rmi.RemoteException;
}

Listing 16. JAX-WS SEI with IN/OUT


parameters
@WebService(name = "HelloWorld",
targetNamespace =
"urn:helloWorld/sample/ibm/com")
public interface HelloWorld {

@WebMethod(action =
"urn:helloWorld/sample/ibm/com/hello")
@RequestWrapper(localName = "hello",
targetNamespace =
"urn:helloWorld/sample/ibm/com",
className =
"helloworld.sample.ibm.com.Hello")
@ResponseWrapper(localName =
"helloResponse",
targetNamespace =
"urn:helloWorld/sample/ibm/com",
className =
"helloworld.sample.ibm.com.HelloResponse")
public void hello(
@WebParam(name = "name",
targetNamespace = "")
String name,
@WebParam(name = "inout",
targetNamespace = "", mode = Mode.INOUT)
Holder<String> inout,
@WebParam(name = "response",
targetNamespace = "", mode = Mode.OUT)
Holder<String> response);

For JAX-RPC, there are a set of classes defined by


the specification as holder classes for known types.
These include types like java.lang.String and other
primitive types. For user defined types, JAX-RPC
requires that custom holder classes be generated
that can handle the user-defined types. JAX-WS, on
the other hand, makes use of the Generics feature in
Java 5 to provide a single class that can work for all
types, including user-defined types.

Another interesting thing to note here is the


difference in return types. Rather than keeping the
return type as JAX-RPC does, JAX-WS makes the
method void and makes use of the holder for what
was the return value. By rule in JAX-WS, when there
is more than one parameter that can be considered
an OUT parameter for an operation, the return type
must be void, and all OUT parameters are mapped to
holder types.

Summary

The above examples illustrate that, while there are a


number of differences between JAX-RPC and JAX-
WS, the mapping from WSDL to the structure of a
service endpoint interface is very similar. The key
differences are:

• The package names are different.


• JAX-RPC requires java.rmi.Remote and
java.rmi.RemoteException, which JAX-WS does
not.
• Holders are defined differently.

Even with all the similarities that exist, there is one


major difference that makes the JAX-WS SEI a very
different entity from the JAX-RPC one. The use of
JSR-181 annotations gives the JAX-WS SEI the
capability to not only represent the Java-centric view
of the Web service, but also the WSDL-centric view.
A number of the annotations included are used to
map the Java information back to WSDL constructs.
This information does not exist in any form in a JAX-
RPC SEI. Some of the other things that are exclusive
to JAX-WS are the asynchronous invocation model
and the fact that it does not require a generated SEI
in the first place. On the other hand, JAX-RPC has
something that JAX-WS does not: it supports an
RPC/encoded WSDL.
Introduction

Both the JAX-RPC 1.1 and the JAX-WS 2.0 client


dynamic model have a similar set of high-level steps
to make an invocation:

1. Define the service.


2. Create the dynamic invocation object from this
service.
3. Build the message.
4. Invoke the operation.

Even though both models follow these same steps,


this tip describes how different the details between
the two models are. You'll use the HelloWorld Web
Services Description Language (WSDL) that you used
in the previous tip. You can find it here in Listing 1.

Listing 1. HelloWorld service's WSDL


<?xml version="1.0" encoding="UTF-
8"?>
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="urn:helloWorld/sample/ibm/com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/
"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="HelloWorld"
targetNamespace="urn:helloWorld/sample/ibm/c
om">
<wsdl:types>
<xsd:schema
targetNamespace="urn:helloWorld/sample/ibm/com"
xmlns:tns="urn:helloWorld/sample/ibm/com"
xmlns:xsd="http://www.w3.org/2001/XMLSchem
a">
<xsd:element name="hello">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name"
nillable="true" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="helloResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="response"
nillable="true" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="helloRequestMsg">
<wsdl:part element="tns:hello"
name="helloParameters" />
</wsdl:message>
<wsdl:message name="helloResponseMsg">
<wsdl:part element="tns:helloResponse"
name="helloResult" />
</wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="hello">
<wsdl:input message="tns:helloRequestMsg"
name="helloRequest" />
<wsdl:output message="tns:helloResponseMsg"
name="helloResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorldBinding"
type="tns:HelloWorld">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" /
>
<wsdl:operation name="hello">
<soap:operation
soapAction="urn:helloWorld/sample/ibm/com/hello" /
>
<wsdl:input name="helloRequest">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="helloResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorldService">
<wsdl:port name="port"
binding="tns:HelloWorldBinding">
<soap:address location="http://tempuri.org/"
/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

Back to top

JAX-RPC's dynamic Call interface

JAX-RPC's dynamic invocation interface (DII) is the


Call object (javax.xml.rpc.Call). Listing 2 contains a
complete client main class that calls Listing 1's
HelloWorld service using the Call object. You can
also see the high-level steps described in the
introduction in Listing 2.

Listing 2. JAX-RPC's DII client


package com.ibm.samples.dii;

import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.encoding.XMLType;

public class HelloWorldClient {

public static void main(String[] args) {


try {
// Define the service.
QName serviceName = new QName(
"urn:helloWorld/sample/ibm/com",
"HelloWorldService");
ServiceFactory factory =
ServiceFactory.newInstance();
Service service =
factory.createService(serviceName);

// Create the dynamic invocation object from


this service.
Call call = service.createCall();
call.setTargetEndpointAddress(
"http://localhost:9081/HelloWorldServ
ice/services/port");

// Build the message.


QName operationName = new QName(
"urn:helloWorld/sample/ibm/com",
"hello");
call.setOperationName(operationName);
call.addParameter(
"name", // parameter name
XMLType.XSD_STRING, // parameter XML
type QName
String.class, // parameter Java
type class
ParameterMode.IN); // parameter mode
call.setReturnType(XMLType.XSD_STRING);
call.setProperty(
Call.OPERATION_STYLE_PROPERTY,
"wrapped");

// Invoke the operation.


Object[] actualArgs = {"Georgia"};
String response = (String)
call.invoke(actualArgs);
System.out.println("response = " + response);
}
catch (Throwable t) {
t.printStackTrace();
}
}
}

Let's look at the details of those high-level steps:

1. Define the service. Using the fully qualified


name of the WSDL's service, you construct a
javax.xml.rpc.Service object.
2. Create the dynamic invocation object from
this service. In JAX-RPC, the dynamic
invocation object is javax.xml.rpc.Call.
3. Build the message. In this step, you populate
the Call object with information about the
operation. There's one thing to point out here:
We call
call.setProperty(Call.OPERATION_STYLE_PROPERTY,
"wrapped"); . wrapped is not a value defined by
JAX-RPC for this property. JAX-RPC defines only
rpc and document. However, rpc really means
RPC/encoded, and document really means
document/literal, non-wrapped. The
document/literal wrapped pattern has become
the industry standard since JAX-RPC was
written, so its Call object doesn't deal well with
it. You can do it, but it's not pretty. Extending
this property to include the wrapped value is
IBM's way of filling this gap of the specification,
but it's a nonstandard extension.
4. Invoke the operation. The input in this
example is a simple string, so you populate the
argument array with a string and pass it to the
invoke function. The response is also a string,
and in this example you simply display it.

JAX-WS's dynamic Dispatch interface

JAX-WS's DII is the Dispatch object


(javax.xml.ws.Dispatch). Listing 3 contains a
complete client main class that calls Listing 1's
HelloWorld service via this Dispatch object. You can
see the high-level steps described in the introduction
in Listing 3.

Listing 3. JAX-WS's DII client


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;

public class HelloWorldClient {

public static void main(String[] args) {


try {
// Define the service.
QName svcQname = new QName(
"urn:helloWorld/sample/ibm/com",
"HelloWorldService");
QName portQName = new QName(
"urn:helloWorld/sample/ibm/com",
"port");
Service svc = Service.create(svcQname);
svc.addPort(
portQName,
SOAPBinding.SOAP11HTTP_BINDING,
"http://localhost:9080/JAXBSampleWebService
HelloWorldService");

// Create the dynamic invocation object from this


service.
Dispatch<Source> dispatch = svc.createDispatch(
portQName,
Source.class,
Service.Mode.PAYLOAD);

// Build the message.


String content =
"<ns2:hello
xmlns:ns2=\"urn:helloWorld/sample/ibm/com\">" +
"<name>Georgie</name>" +
"</ns2:hello>";
ByteArrayInputStream bais = new
ByteArrayInputStream(content.getBytes());
Source input = new StreamSource(bais);

// Invoke the operation.


Source output = dispatch.invoke(input);

// Process the response.


StreamResult result = new StreamResult(new
ByteArrayOutputStream());
Transformer trans =
TransformerFactory.newInstance().newTransformer();
trans.transform(response, result);
ByteArrayOutputStream baos = (ByteArrayOutputStream
result.getOutputStream();

// Write out the response content.


String responseContent = new
String(baos.toByteArray());
System.out.println(responseContent);
}
catch (Throwable t) {
t.printStackTrace();
}
}
}

Let's look at the details of those high-level steps in


this JAX-WS dynamic client:

1. Define the service. Like in JAX-RPC's model,


you define the service based on its fully qualified
name, but you also define the port within that
service.
2. Create the dynamic invocation object from
this service. In JAX-WS, the dynamic
invocation object is javax.xml.ws.Dispatch. This
class leverages the new Generics feature in Java
5 to support multiple parameter types.
3. Build the message. Here you build the raw
SOAP message body contents.
4. Invoke the operation. You send the contents
of the SOAP body to the service and receive the
SOAP response back from the service.

Back to top
The differences between the models

Looking at the high-level steps, it appears that the


dynamic invocation model for JAX-RPC and JAX-WS
are similar. But this is somewhat misleading. When
you look at the details of each example, you can see
that the models are, in fact, very different. Let's take
a look at some of those differences a little more
closely.

Operation style

It should be fairly clear that the primary difference


between the models is that JAX-RPC follows a
remote procedure call (RPC) model (hence the RPC
in the specification name), while JAX-WS's dynamic
client follows a messaging model. With JAX-RPC, the
Call object must be configured to explicitly invoke a
particular operation from the WSDL. In JAX-WS, the
Dispatch object is unaware of what operation is being
invoked and is just sending XML data.

Parameter style

With JAX-RPC, the parameter type(s) passed retain


the XML Schema-to-Java mappings that are defined
by the specification. With JAX-WS, there are two
different ways to use the Dispatch object: either as
an XML-based Dispatch (as shown in this tip) or as a
JAXB-based Dispatch. The XML-based Dispatch
accepts parameters that are based on these object
types: javax.xml.transform.Source,
javax.xml.soap.SOAPMessage, and
javax.activation.DataSource. The JAXB-based
Dispatch requires the user to configure a
javax.xml.bind.JAXBContext that can be used to
marshall and unmarshall instances of the
parameters, which are JAXB Java beans.

Another major difference in the parameter style is in


what the content passed in represents. For JAX-RPC,
the parameter(s) always form the parameter data of
the request. With JAX-WS, there are two different
parameter modes: PAYLOAD and MESSAGE mode.
PAYLOAD mode means the parameter represents
just the contents of the SOAP body, where MESSAGE
mode means the parameter represents the entire
message, including the SOAP envelope.

Invocation patterns

As shown above, JAX-RPC and JAX-WS both provide


a synchronous two-way invocation via the invoke()
method. Both models also provide a method for
invoking one-way Web service operations via the
invokeOneWay method. A major difference between
the two models is that JAX-WS also provides an
asynchronous invocation model. There is an
asynchronous callback model and an asynchronous
polling model. JAX-RPC doesn't provide an option for
asynchronous invocations.

Server-side dynamic programming model

Another major difference, which isn't covered in


detail here, is that JAX-WS adds what JAX-RPC never
had — a dynamic server-side programming model.
Like the client-side model, it too can be configured
for PAYLOAD or MESSAGE mode.

Back to top

Summary

Both JAX-RPC and JAX-WS provide a dynamic client


model. And both can be viewed as equivalent from a
high-level point of view. But when you get down to
the details, you can see that JAX-RPC's dynamic
model is an RPC model, while JAX-WS's dynamic
model is a messaging model. The JAX-WS APIs
provide greater flexibility and are the next step in
the evolution of Web services programming models.
JAX-WS also adds support for asynchronous support
and for a dynamic service, which JAX-RPC doesn't
define.

Introduction

The attachment model for JAX-RPC is Sw/A. Since


JAX-RPC was written, a new attachment model has
come onto the scene: MTOM. JAX-WS provides Sw/A
support just as JAX-RPC does, but adds support for
MTOM. JAX-WS supports MTOM via the Java
Architecture for XML Binding (JAXB) specification,
which includes APIs for marshalling and
unmarshalling both Sw/A and MTOM attachments. In
this tip, you examine both models through examples.
Note: This tip compares only the WSDLs and the
Java programming models; comparing the wire-level
messages is left as an exercise to the reader.
Back to top

JAX-RPC and Sw/A example

Listing 1 shows the WSDL from an attachment tip


written a few years ago (see Resources). Listing 2
shows the Java interface, which the JAX-RPC
mapping produces from this WSDL.

Listing 1. JAX-RPC Sw/A WSDL


<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://attachment.tip/">
<types/>
<message name="sendImage">
<part name="image" type="xsd:base64Binary"/>
</message>
<message name="sendImageResponse"/>
<message name="sendOctet">
<part name="octet" type="xsd:base64Binary"/>
</message>
<message name="sendOctetResponse"/>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</operation>
</portType>
<binding name="AttachmentBinding" type="tns:AttachmentTip">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="sendImage">
<soap:operation soapAction=""/>
<input>
<mime:multipartRelated>
<mime:part>
<soap:body parts="" namespace="http://attachment.ti
use="literal"/>
</mime:part>
<mime:part>
<mime:content part="image" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
</input>
<output>
<soap:body namespace="http://attachment.tip/"
use="literal"/>
</output>
</operation>
<operation name="sendOctet">
<soap:operation soapAction=""/>
<input>
<mime:multipartRelated>
<mime:part>
<soap:body parts="" namespace="http://attachment.ti
use="literal"/>
</mime:part>
<mime:part>
<mime:content part="octet" type="application/octet-
stream"/>
</mime:part>
</mime:multipartRelated>
</input>
<output>
<soap:body namespace="http://attachment.tip/"
use="literal"/>
</output>
</operation>
</binding>
<service name="AttachmentService">
<port binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address
location="http://localhost:9080/SwAService/services/AttachmentT
</port>
</service>
</definitions>

Listing 2. JAX-RPC Sw/A Java interface


package tip.attachment;

import java.awt.Image;
import java.rmi.Remote;
import java.rmi.RemoteException;

import javax.activation.DataHandler;

public interface AttachmentTip


extends Remote {
public void sendImage(Image
image) throws RemoteException;
public void
sendOctet(DataHandler octet) throws
RemoteException;
}

The Java interface mapping from the WSDL is fairly


straightforward: The sendImage operation's image/jpeg
part is mapped to a java.awt.Image parameter; the
sendOctet operation's application/octet-stream is
mapped to a javax.activation.DataHandler
parameter. However, there's a cost to this mapping:
The Multipurpose Internet Mail Extensions (MIME)
type information isn't in the interface portion of the
WSDL (the portType, message, and types sections).
You must dip into the binding to find the MIME
information. This is unfortunate because different
bindings for the same WSDL interface could result in
different types and, therefore, map to different Java
interfaces. It would be better if there were a one-to-
one mapping from WSDL interface to Java interface.
If you have more than one binding, each simply
maps to an implementation, all of which implements
the same Java interface. With Sw/A, you can't do
that; the mapping from WSDL to Java interfaces is
not one to one.

A secondary issue with Sw/A is that it doesn't lend


itself well to the industry convention of
document/literal wrapped WSDL (you'll notice that
the WSDL in Listing 1 is an rpc/literal WSDL). Adding
Sw/A content to a document/literal wrapped
message requires specifying additional message
parts beyond the single operation wrapper.

Does MTOM fix these issues? Let's move on to the


next section to find out.

Back to top

JAX-WS and MTOM example

In Listing 3, we've modified the Sw/A WSDL from


Listing 1 to produce an equivalent MTOM WSDL.

Listing 3. JAX-WS MTOM WSDL


<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<types/>
<message name="sendImage">
<part name="image" type="xsd:base64Binary"/>
</message>
<message name="sendImageResponse"/>
<message name="sendOctet">
<part name="octet" type="xsd:base64Binary"/>
</message>
<message name="sendOctetResponse"/>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</operation>
</portType>
<binding name="AttachmentBinding" type="tns:AttachmentTip">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="sendImage">
<soap:operation soapAction=""/>
<input>
<soap:body namespace="http://attachment.tip/" use="lite
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="lite
</output>
</operation>
<operation name="sendOctet">
<soap:operation soapAction=""/>
<input>
<soap:body namespace="http://attachment.tip/" use="lite
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="lite
</output>
</operation>
</binding>
<service name="AttachmentService">
<port binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address
location="http://localhost:9080/MTOMService/services/Attachment
</port>
</service>
</definitions>

The only real difference between the MTOM WSDL in


Listing 3 and the Sw/A WSDL in Listing 1 is the
binding. The MTOM binding contains no MIME
information. In fact, there's no way to tell, from the
WSDL, that you're dealing with attachments; the
WSDL's binding looks like a normal binding.

Listing 4 shows the Java interface, which a JAX-WS


mapping produces from this WSDL.

Listing 4. JAX-WS MTOM Java interface


package tip.attachment;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(name = "AttachmentTip",
targetNamespace =
"http://attachment.tip/")
@SOAPBinding(style =
SOAPBinding.Style.RPC)
public interface AttachmentTip {
@WebMethod
public void sendImage(
@WebParam(name = "image",
partName = "image")
byte[] image);

@WebMethod
public void sendOctet(
@WebParam(name = "octet",
partName = "octet")
byte[] octet);

Because the WSDL is a normal-looking WSDL with no


hint of attachments, you end up with a Java interface
that reflects that as well. Given parts of type
base64Binary (or hexBinary), JAX-WS maps those to
parameters of type byte[]. With MTOM, the MIME-
ness of the types has all been extracted from the
WSDL with the burden placed on the client or server
run time to format the content appropriately.

Back to top

Comparison of Sw/A and MTOM

The JAX-RPC Sw/A section noted two drawbacks to


Sw/A:

• The MIME type info is in the WSDL binding, not


the WSDL interface.
• It's difficult to create a document/literal wrapped
attachment WSDL.

Let's discuss the document/literal wrapped style first.

document/literal wrapped style and attachments

We left the MTOM WSDL in Listing 3 as rpc/literal


WSDL for comparison purposes; but it's an easy
matter to turn this WSDL into document/literal
wrapped WSDL. Listing 5 in the next section shows
the document/literal wrapped equivalent of the
WSDL in Listing 3 (see Resources for more
information about the differences between various
WSDL styles).

MIME type info in the binding

Because the MTOM WSDL's binding doesn't have any


MIME information, you don't have to dip into the
binding to determine the part types. You have
everything you need in the WSDL interface to
generate the Java interface. However, as you can
see by comparing the Java interfaces in Listing 2 and
Listing 4, we've lost some information.

The interface portion of both WSDLs shows that the


data type in the operations is base64Binary, which
maps to byte[]. In the JAX-RPC Sw/A WSDL,
however, you know from the binding that the part
types are a MIME image and a MIME octet stream. In
the JAX-WS MTOM WSDL, this information is lost.
This may seem like a bad thing, but the positive spin
is that this completely cleans up the interface. No
matter what the binding, the interface is always the
same. In fact, the implementors of the client and the
server codebases shouldn't be bothered with the
notion of whether the parameter is an attachment.
That's merely a detail of the SOAP message, and the
writers of the WSDL-to-Java mappings have tried
their best to abstract the programmer away from the
details of the SOAP message.

However, if you really want to know what the MIME


type is—if you want to get back to the information
you lost—JAX-WS provides support for an attribute
that you can inject into an XML element:
expectedContentTypes. This special attribute is
highlighted in Listing 5. Listing 6 shows the
corresponding Java interface. Ignoring the
annotations, this Java interface is essentially the
same as the interface in Listing 2.

Listing 5. JAX-WS MIME attribute


<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<types>
<xsd:schema
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<xsd:element name="sendImage" type="tns:sendImage"/>
<xsd:complexType name="sendImage">
<xsd:sequence>
<xsd:element
xmlns:ns1="http://www.w3.org/2005/05/xmlmime"
image/*"
name="image"
type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="sendImageResponse" type="tns:sendImage
<xsd:complexType name="sendImageResponse">
<xsd:sequence/>
</xsd:complexType>
<xsd:element name="sendOctet" type="tns:sendOctet"/>
<xsd:complexType name="sendOctet">
<xsd:sequence>
<xsd:element
xmlns:ns1="http://www.w3.org/2005/05/xmlmime"n
pplication/octet-stream"
name="octet"
type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="sendOctetResponse" type="tns:sendOctet
<xsd:complexType name="sendOctetResponse">
<xsd:sequence/>
</xsd:complexType>
</xsd:schema>
</types>
<message name="sendImage">
<part name="parameters" element="tns:sendImage"/>
</message>
<message name="sendImageResponse">
<part name="parameters" element="tns:sendImageResponse"/>
</message>
<message name="sendOctet">
<part name="parameters" element="tns:sendOctet"/>
</message>
<message name="sendOctetResponse">
<part name="parameters" element="tns:sendOctetResponse"/>
</message>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</operation>
</portType>
<binding name="AttachmentBinding" type="tns:AttachmentTip">
<soap:binding style="document" transport="http://schemas.xm
<operation name="sendImage">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="sendOctet">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="AttachmentService">
<port binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address location="http://localhost:9080/MTOMService
</port>
</service>
</definitions>

Notice that this new attribute is wholly contained


within the WSDL interface. It's not in the binding, so
all of the type information is where you want it.
Listing 6. JAX-WS Java interface mapped from
the MIME attribute
package tip.attachment;

import java.awt.Image;
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

@WebService(name = "AttachmentTip",
targetNamespace =
"http://attachment.tip/")
public interface AttachmentTip {

@WebMethod
@RequestWrapper(localName =
"sendImage",
targetNamespace =
"http://attachment.tip/",
className =
"tip.attachment.SendImage")
@ResponseWrapper(localName =
"sendImageResponse",
targetNamespace =
"http://attachment.tip/",
className =
"tip.attachment.SendImageResponse")
public void sendImage(
@WebParam(name = "image",
targetNamespace = "")
Image image);

@WebMethod
@RequestWrapper(localName =
"sendOctet",
targetNamespace =
"http://attachment.tip/",
className =
"tip.attachment.SendOctet")
@ResponseWrapper(localName =
"sendOctetResponse",
targetNamespace =
"http://attachment.tip/",
className =
"tip.attachment.SendOctetResponse")
public void sendOctet(
@WebParam(name = "octet",
targetNamespace = "")
DataHandler octet);
}

As mentioned earlier, JAX-WS relies on JAXB to


handle the data binding for most of its Web services
content. The mapping for the expectedContentTypes
element is defined in Appendix H of the JAXB 2.0
specification (see Resources). The JAXB 2.0
mappings are similar to the JAX-RPC mappings.
Compare these mappings in Table 1.

Table 1. MIME type to Java type mappings


MIME type JAX-RPC mapping JAX-WS/JA
image/gif java.awt.Image java.awt.Ima
image/jpg java.awt.Image java.awt.Ima
text/plain java.lang.String javax.xml.tra
text/xml javax.xml.transform.Source javax.xml.tra
application/xmljavax.xml.transform.Source javax.xml.tra
javax.mail.internet.MimeMultipar
multipart/* javax.activati
t
all other types javax.activation.DataHandler javax.activati
enabling/disabling attachment support

One of the of additional benefits of MTOM is the fact


that you can turn it on or off. In the case of Sw/A, if
one side or the other doesn't support sending Sw/A
attachments, then the contract defined by the WSDL
cannot be honored. On the other hand, if you have
an MTOM WSDL such as that in listing 3 or 5, a client
could choose to send data as an MTOM attachment
or inline in the SOAP message. No matter what the
client chooses, it can still interact with the Web
service. MTOM is just an optimization of sending
content, not a mandate like Sw/A.

Back to top

Sw/A and JAX-WS

JAX-WS still supports the Sw/A model. By default,


JAX-WS maps a Sw/A attachment to a byte[] on the
Java interface, like the sample in Listing 4. To get
the mapping you are used to in JAX-RPC, you can
use the enableMIMEContent WSDL binding definition
(see section 8.7.5 of the JAX-WS specification for
more details). Listing 7 shows the JAX-WS version of
the Java interface equivalent to the JAX-RPC version
of the interface in listing 2.

Listing 7. JAX-WS Java interface with Sw/A


attachments mapped from the mime:content
package tip.attachment;

import java.awt.Image;
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(name = "AttachmentTip",
targetNamespace =
"http://attachment.tip/")
@SOAPBinding(style =
SOAPBinding.Style.RPC)
public interface AttachmentTip {

@WebMethod
public void sendImage(
@WebParam(name = "image",
partName = "image")
Image image);

@WebMethod
public void sendOctet(
@WebParam(name = "octet",
partName = "octet")
DataHandler octet);

Back to top

Summary

JAX-RPC supports the Sw/A model. JAX-WS supports


Sw/A as well, but it has also stepped up to the new
MTOM model. MTOM is an improvement upon Sw/A
in a number of ways:
• Everything necessary to create a Java interface
is now available in the WSDL interface.
• MTOM is usable in a document/literal wrapped
WSDL.
• MTOM allows optimization to attachments, but it
doesn't force attachments like Sw/A does.

You might also like