JAX-WS, like JAX-RS, uses annotations, and machine-generated JAX-WS code is awash with these. The first example is stingy in its use of annotations in order to underscore exactly what is required for a SOAP-based service. Later examples introduce additional annotations.:
The RandService
class (see Example 4-1) defines a SOAP-based service with two operations, each an annotated Java method:
- Operation next1 takes no arguments and returns one randomly generated integer.
- Operation nextN takes one argument, the number of randomly generated integers desired, and returns a list (in this implementation, an array) of integers.
Example 4-1. A SOAP-based service with two operations
package
rand
;
import
javax.jws.WebService
;
import
javax.jws.WebMethod
;
import
java.util.Random
;
@WebService
public
class
RandService
{
private
static
final
int
maxRands
=
16
;
@WebMethod
// optional but helpful annotation
public
int
next1
()
{
return
new
Random
().
nextInt
();
}
@WebMethod
// optional but helpful annotation
public
int
[
]
nextN
(
final
int
n
)
{
final
int
k
=
(
n
>
maxRands
)
?
maxRands
:
Math
.
abs
(
n
);
int
[
]
rands
=
new
int
[
k
];
Random
r
=
new
Random
();
for
(
int
i
=
0
;
i
<
k
;
i
++)
rands
[
i
]
=
r
.
nextInt
();
return
rands
;
}
}
The @WebService
annotation (line 1) marks the RandService
POJO class as a web service, and the
@WebMethod
annotation (lines 2 and 3) specifies which of the encapsulated methods
is a service operation. In this example, the RandService
class has only two
methods and each of these is annotated as @WebMethod
. The @WebMethod
annotation is optional but
recommended. In a class annotated as a @WebService
, a public
instance
method is thereby a service operation even if the method is
not annotated.
This SOAP service code is compiled in the
usual way, assuming JDK 1.6 or greater.
Recall that core Java 6 or greater includes the Endpoint
class for publishing web services,
SOAP-based (@WebService
) and REST-style (@WebServiceProvider
) alike.
The class RandPublisher
(see Example 4-2) is the
Endpoint
publisher for the RandService
.
The publish
method used here (line 2) takes two arguments: a URL that specifies the
service endpoint (line 1) and an instance of the service implementation class, in this
case the RandService
class (line 2).
In the URL, the port number 8888 and the URI /rs
are arbitrary, although a port number greater than
1023 is recommended because modern operating systems typically reserve port numbers below 1024
for particular applications (e.g., port 80 is typically reserved for HTTP requests to a
web server).
The RandPublisher
as coded here runs indefinitely, but there are various
way to control an Endpoint
publisher’s life span.
The web service publisher can be executed in the usual way:
%
java
rand
.
RandPublisher
The output should be similar to this:
Publishing
RandService
at
endpoint
http:
//localhost:8888/rs
com
.
sun
.
xml
.
internal
.
ws
.
model
.
RuntimeModeler
getRequestWrapperClass
INFO:
Dynamically
creating
request
wrapper
Class
rand
.
jaxws
.
Next1
com
.
sun
.
xml
.
internal
.
ws
.
model
.
RuntimeModeler
getResponseWrapperClass
Dynamically
creating
response
wrapper
bean
Class
rand
.
jaxws
.
Next1Response
com
.
sun
.
xml
.
internal
.
ws
.
model
.
RuntimeModeler
getRequestWrapperClass
INFO:
Dynamically
creating
request
wrapper
Class
rand
.
jaxws
.
NextN
com
.
sun
.
xml
.
internal
.
ws
.
model
.
RuntimeModeler
getResponseWrapperClass
INFO:
Dynamically
creating
response
wrapper
bean
Class
rand
.
jaxws
.
NextNResponse
The first line of output is from the RandPublisher
but the others are from the Java
run-time. The dynamically created wrapper classes such as Next1
and
Next1Response
are JAX-B artifacts that represent the
incoming SOAP request (Next1
) and the outgoing SOAP response (Next1Response
).
Once the service is published, a utility such as curl can be used to confirm that the service is indeed up and running:
%
curl
http:
//localhost:8888/rs?xsd=1
This curl request contains the query string entry xsd=1
that asks for the XML Schema associated with this
service; the schema, like the JAX-B artifacts, is generated dynamically (see Example 4-3).
Example 4-3. The XML Schema generated dynamically for the RandService
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
xs:
schema
xmlns:
tns
=
"http://rand/"
xmlns:
xs
=
"http://www.w3.org/2001/XMLSchema"
version
=
"1.0"
targetNamespace
=
"http://rand/"
>
<
xs:
element
name
=
"next1"
type
=
"tns:next1"
></
xs:
element
>
<
xs:
element
name
=
"next1Response"
type
=
"tns:next1Response"
></
xs:
element
>
<
xs:
element
name
=
"nextN"
type
=
"tns:nextN"
></
xs:
element
>
<
xs:
element
name
=
"nextNResponse"
type
=
"tns:nextNResponse"
></
xs:
element
>
<
xs:
complexType
name
=
"next1"
><
xs:
sequence
></
xs:
sequence
></
xs:
complexType
>
<
xs:
complexType
name
=
"next1Response"
>
<
xs:
sequence
>
<
xs:
element
name
=
"return"
type
=
"xs:int"
></
xs:
element
>
</
xs:
sequence
>
</
xs:
complexType
>
<
xs:
complexType
name
=
"nextN"
>
<
xs:
sequence
>
<
xs:
element
name
=
"arg0"
type
=
"xs:int"
></
xs:
element
>
</
xs:
sequence
>
</
xs:
complexType
>
<
xs:
complexType
name
=
"nextNResponse"
>
<
xs:
sequence
>
<
xs:
element
name
=
"return"
type
=
"xs:int"
minOccurs
=
"0"
maxOccurs
=
"unbounded"
>
</
xs:
element
>
</
xs:
sequence
>
</
xs:
complexType
>
</
xs:
schema
>
The schema will be studied carefully later. For now, the point of interest is that
the schema provides a data type for each SOAP message that travels, in either direction,
between the
service and the client. Each message is of an XML Schema complexType
as opposed to an
simple type such as xsd:date
, xsd:string
, or xsd:integer
.
In the RandService
there are two SOAP messages (for instance, the messages Next1
and
Next1Response
) per web service operation (in this case, the next1 operation) because each operation
implements the familiar request/response pattern: a client issues a request, delivered to the
service as a
Next1
SOAP message, and gets a response, in this case a Next1Response
message, in return.
Accordingly, the schema contains four typed SOAP messages because the RandService
has two
operations in the request/response pattern, which means two messages per operation. The number
of complexType
occurrences in the XML Schema may exceed the total number of messages needed
to implement the service’s operations because special error messages, SOAP faults, also may
be defined in the XML Schema. SOAP faults are covered in the next chapter.
The XML Schema types such as Next1
and Next1Response
are the XML counterparts to
the JAX-B artifacts, noted earlier, with the same names. The schema types and the
JAX-B types together allow the SOAP libraries to transform Java objects into XML documents (in particular, SOAP Envelope
instances)
and SOAP Envelope
instances into Java objects. The Endpoint
publisher’s underlying SOAP libraries
handle the generation of the JAX-B artifacts and the generation of the XML Schema.
Even this first and rather simple example underscores a major appeal of SOAP-based services: underlying SOAP libraries handle the conversions between native language types (in this case, Java types) and XML Schema types. Figure 4-1 depicts the architecture.
Get Java Web Services: Up and Running, 2nd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.