JAX-RS, Restlet, and the JAX-WS @WebServiceProvider
frameworks for RESTful services include client-side APIs.
These APIs are meant to simplify the task of writing RESTful clients in general, not just clients against a
RESTful service implemented in a particular framework. To underscore the point, this section takes a look
at the JAX-RS client-side API (see Example 3-18); the client, however, goes against the servlet-based predictions2 RESTful service
from Chapter 2.
Example 3-18. A sample client using the JAX-RS client-side API
package
jerseyClient
;
import
com.sun.jersey.api.client.Client
;
import
com.sun.jersey.api.client.WebResource
;
import
javax.ws.rs.core.MediaType
;
import
com.sun.jersey.api.representation.Form
;
public
class
JerseyClient
{
private
static
final
String
baseUrl
=
"http://localhost:8080/predictions2"
;
public
static
void
main
(
String
[
]
args
)
{
new
JerseyClient
().
demo
();
}
private
void
demo
()
{
Client
client
=
Client
.
create
();
client
.
setFollowRedirects
(
true
);
// in case the service redirects
WebResource
resource
=
client
.
resource
(
baseUrl
);
getAllDemo
(
resource
);
postDemo
(
resource
);
// same resource but different verb
String
url
=
baseUrl
+
"?id=32"
;
resource
=
client
.
resource
(
url
);
getOneDemo
(
resource
);
deleteDemo
(
resource
);
// delete id = 32
}
private
void
getAllDemo
(
WebResource
resource
)
{
// GET all XML
String
response
=
resource
.
accept
(
MediaType
.
APPLICATION_XML_TYPE
).
get
(
String
.
class
);
report
(
"GET all in XML:\n"
,
response
);
// GET all JSON
response
=
resource
.
accept
(
MediaType
.
APPLICATION_JSON_TYPE
).
get
(
String
.
class
);
report
(
"GET all in JSON:\n"
,
response
);
}
private
void
getOneDemo
(
WebResource
resource
)
{
String
response
=
resource
.
accept
(
MediaType
.
APPLICATION_XML_TYPE
).
get
(
String
.
class
);
report
(
"GET one in XML:\n"
,
response
);
response
=
resource
.
accept
(
MediaType
.
APPLICATION_JSON_TYPE
).
get
(
String
.
class
);
report
(
"GET one in JSON:\n"
,
response
);
}
private
void
postDemo
(
WebResource
resource
)
{
Form
form
=
new
Form
();
// HTTP body, a simple hash
form
.
add
(
"who"
,
"William Butler Yeats"
);
form
.
add
(
"what"
,
"I know that I shall meet my fate"
);
String
response
=
resource
.
type
(
MediaType
.
APPLICATION_FORM_URLENCODED_TYPE
)
.
accept
(
MediaType
.
TEXT_PLAIN_TYPE
)
.
post
(
String
.
class
,
form
);
report
(
"POST:\n"
,
response
);
}
private
void
deleteDemo
(
WebResource
resource
)
{
String
response
=
resource
.
accept
(
MediaType
.
TEXT_PLAIN_TYPE
).
delete
(
String
.
class
);
report
(
"DELETE:\n"
,
response
);
}
private
void
report
(
String
msg
,
String
response
)
{
System
.
out
.
println
(
"\n"
+
msg
+
response
);
}
}
The JerseyClient
(see Example 3-18) against the servlet-based predictions2 RESTful service supports all of the CRUD operations. (An executable JAR with the client is included in the
ZIP with the sample code.) This client underscores that the JAX-RS client API is not restricted to
JAX-RS services.
In any case, the JerseyClient
uses some nice features of the
JAX-RS client-side API. For example, the predictions2 service uses the same URI in a GET request
that returns XML as in one that returns JSON. What differentiates the two requests is that
the one for JSON has the key/value pair:
accept:
application
/
json
or the equivalent in the HTTP headers of a GET request.
In the getAllDemo
method of the JerseyClient
, the two forms of the GET request are
expressed at a high level:
resource
.
accept
(
MediaType
.
APPLICATION_XML_TYPE
).
get
(
String
.
class
);
// XML
resource
.
accept
(
MediaType
.
APPLICATION_JSON_TYPE
).
get
(
String
.
class
);
// JSON
There is no need for the programmer to inject, using a low-level API, inject this key/value pair into the HTTP headers using a low-level API:
accept:
application
/
json
By the way, the get(String.class)
at the end of each statement signals that
the response to the GET request should be text, a Java String
. The API accepts JAX-B types as well so that,
for example, a GET request could indicate that it expects a Prediction
object rather than a String
one.
The setup for making CRUD calls is uncomplicated. A Client
instance is created, which can be used to
create arbitrarily many WebResource
instances, each of which wraps a URL. Here, for review, is a
slice of the JerseyClient
:
Client
client
=
Client
.
create
();
client
.
setFollowRedirects
(
true
);
// in case the service redirects
WebResource
resource
=
client
.
resource
(
baseUrl
);
// service URL
In version 2, the JAX-RS client API introduces some advanced features such as
filters and asynchronous requests. These features will be examined in the next chapter but in the
context of SOAP-based web services. Restlet has a client API comparable to the one in JAX-RS. The JAX-WS
client API for calls against the @WebServiceProvider
is at a lower level than both JAX-RS and Restlet. This
is appropriate in that the @WebServiceProvider
service-side API is deliberately low-level. All of these
client-side APIs add a RESTful layer to the familiar Java classes such as URLConnection
.