Root resource classes are "plain old Java objects" (POJOs) that are
either annotated with @Path
or have at least one method annotated with
@Path
or a request method designator, such as @GET
, @PUT
, @POST
,
or @DELETE
. Resource methods are methods of a resource class annotated
with a request method designator. This section explains how to use
JAX-RS to annotate Java classes to create RESTful web services.
Developing RESTful Web Services with JAX-RS
JAX-RS is a Java programming language API designed to make it easy to
develop applications that use the REST architecture.
The JAX-RS API uses Java programming language annotations to simplify
the development of RESTful web services. Developers decorate Java
programming language class files with JAX-RS annotations to define
resources and the actions that can be performed on those resources.
JAX-RS annotations are runtime annotations; therefore, runtime
reflection will generate the helper classes and artifacts for the
resource. A Java EE application archive containing JAX-RS resource
classes will have the resources configured, the helper classes and
artifacts generated, and the resource exposed to clients by deploying
the archive to a Java EE server.
Table 30-1 Summary of JAX-RS Annotations
Annotation |
Description |
@Path
|
The @Path annotation’s value is a relative URI path
indicating where the Java class will be hosted: for example,
/helloworld . You can also embed variables in the URIs to make a URI
path template. For example, you could ask for the name of a user and
pass it to the application as a variable in the URI:
/helloworld/{username} . |
@GET
|
The @GET annotation is a request method designator and
corresponds to the similarly named HTTP method. The Java method
annotated with this request method designator will process HTTP GET
requests. The behavior of a resource is determined by the HTTP method to
which the resource is responding. |
@POST
|
The @POST annotation is a request method designator and
corresponds to the similarly named HTTP method. The Java method
annotated with this request method designator will process HTTP POST
requests. The behavior of a resource is determined by the HTTP method to
which the resource is responding. |
@PUT
|
The @PUT annotation is a request method designator and
corresponds to the similarly named HTTP method. The Java method
annotated with this request method designator will process HTTP PUT
requests. The behavior of a resource is determined by the HTTP method to
which the resource is responding. |
@DELETE
|
The @DELETE annotation is a request method designator and
corresponds to the similarly named HTTP method. The Java method
annotated with this request method designator will process HTTP DELETE
requests. The behavior of a resource is determined by the HTTP method to
which the resource is responding. |
@HEAD
|
The @HEAD annotation is a request method designator and
corresponds to the similarly named HTTP method. The Java method
annotated with this request method designator will process HTTP HEAD
requests. The behavior of a resource is determined by the HTTP method to
which the resource is responding. |
@OPTIONS
|
The @OPTIONS annotation is a request method designator
and corresponds to the similarly named HTTP method. The Java method
annotated with this request method designator will process HTTP OPTIONS
requests. The behavior of a resource is determined by the HTTP method to
which the resource is responding. |
@PATCH
|
The @PATCH annotation is a request method designator and
corresponds to the similarly named HTTP method. The Java method
annotated with this request method designator will process HTTP PATCH
requests. The behavior of a resource is determined by the HTTP method to
which the resource is responding. |
@PathParam
|
The @PathParam annotation is a type of parameter that
you can extract for use in your resource class. URI path parameters are
extracted from the request URI, and the parameter names correspond to
the URI path template variable names specified in the @Path
class-level annotation. |
@QueryParam
|
The @QueryParam annotation is a type of parameter that
you can extract for use in your resource class. Query parameters are
extracted from the request URI query parameters. |
@Consumes
|
The @Consumes annotation is used to specify the MIME
media types of representations a resource can consume that were sent by
the client. |
@Produces
|
The @Produces annotation is used to specify the MIME
media types of representations a resource can produce and send back to
the client: for example, "text/plain" . |
@Provider
|
The @Provider annotation is used for anything that is of
interest to the JAX-RS runtime, such as MessageBodyReader and
MessageBodyWriter . For HTTP requests, the MessageBodyReader is used
to map an HTTP request entity body to method parameters. On the response
side, a return value is mapped to an HTTP response entity body by using
a MessageBodyWriter . If the application needs to supply additional
metadata, such as HTTP headers or a different status code, a method can
return a Response that wraps the entity and that can be built using
Response.ResponseBuilder . |
@ApplicationPath
|
The @ApplicationPath annotation is used to define
the URL mapping for the application. The path specified by
@ApplicationPath is the base URI for all resource URIs specified by
@Path annotations in the resource class. You may only apply
@ApplicationPath to a subclass of javax.ws.rs.core.Application . |
The @Path Annotation and URI Path Templates
The @Path
annotation identifies the URI path template to which the
resource responds and is specified at the class or method level of a
resource. The @Path
annotation’s value is a partial URI path template
relative to the base URI of the server on which the resource is
deployed, the context root of the application, and the URL pattern to
which the JAX-RS runtime responds.
URI path templates are URIs with variables embedded within the URI
syntax. These variables are substituted at runtime in order for a
resource to respond to a request based on the substituted URI. Variables
are denoted by braces ({
and }
). For example, look at the following
@Path
annotation:
@Path("/users/{username}")
In this kind of example, a user is prompted to type his or her name, and
then a JAX-RS web service configured to respond to requests to this URI
path template responds. For example, if the user types the user name
"Galileo," the web service responds to the following URL:
http://example.com/users/Galileo
To obtain the value of the user name, the @PathParam
annotation may be
used on the method parameter of a request method, as shown in the
following code example:
@Path("/users/{username}")
public class UserResource {
@GET
@Produces("text/xml")
public String getUser(@PathParam("username") String userName) {
...
}
}
By default, the URI variable must match the regular expression
"[^/]+?"
. This variable may be customized by specifying a different
regular expression after the variable name. For example, if a user name
must consist only of lowercase and uppercase alphanumeric characters,
override the default regular expression in the variable definition:
@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]*}")
In this example, the username
variable will match only user names that
begin with one uppercase or lowercase letter and zero or more
alphanumeric characters and the underscore character. If a user name
does not match that template, a 404 (Not Found) response will be sent to
the client.
A @Path
value isn’t required to have leading or trailing slashes (/).
The JAX-RS runtime parses URI path templates the same way, whether or
not they have leading or trailing slashes.
A URI path template has one or more variables, with each variable name
surrounded by braces: {
to begin the variable name and }
to end it.
In the preceding example, username
is the variable name. At runtime, a
resource configured to respond to the preceding URI path template will
attempt to process the URI data that corresponds to the location of
{username}
in the URI as the variable data for username
.
@Path("/{name1}/{name2}/")
public class SomeResource {
...
}
In this example, the URL pattern for the JAX-RS helper servlet,
specified in web.xml
, is the default:
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
A variable name can be used more than once in the URI path template.
If a character in the value of a variable would conflict with the
reserved characters of a URI, the conflicting character should be
substituted with percent encoding. For example, spaces in the value of a
variable should be substituted with %20
.
When defining URI path templates, be careful that the resulting URI
after substitution is valid.
Table 32-2 lists some examples of URI path template
variables and how the URIs are resolved after substitution. The
following variable names and values are used in the examples:
-
name1
: james
-
name2
: gatz
-
name3
:
-
location
: Main%20Street
-
question
: why
The value of the name3 variable is an empty string.
|
Table 32-2 Examples of URI Path Templates
Parameters of a resource method may be annotated with parameter-based
annotations to extract information from a request. A previous example
presented the use of the @PathParam
parameter to extract a path
parameter from the path component of the request URL that matched the
path declared in @Path
.
You can extract the following types of parameters for use in your
resource class:
-
Query
-
URI path
-
Form
-
Cookie
-
Header
-
Matrix
Query parameters are extracted from the request URI query parameters and
are specified by using the javax.ws.rs.QueryParam
annotation in the
method parameter arguments. The following example demonstrates using
@QueryParam
to extract query parameters from the Query
component of
the request URL:
@Path("smooth")
@GET
public Response smooth(
@DefaultValue("2") @QueryParam("step") int step,
@DefaultValue("true") @QueryParam("min-m") boolean hasMin,
@DefaultValue("true") @QueryParam("max-m") boolean hasMax,
@DefaultValue("true") @QueryParam("last-m") boolean hasLast,
@DefaultValue("blue") @QueryParam("min-color") ColorParam minColor,
@DefaultValue("green") @QueryParam("max-color") ColorParam maxColor,
@DefaultValue("red") @QueryParam("last-color") ColorParam lastColor
) { ... }
If the query parameter step
exists in the query component of the
request URI, the value of step
will be extracted and parsed as a
32-bit signed integer and assigned to the step
method parameter. If
step
does not exist, a default value of 2, as declared in the
@DefaultValue
annotation, will be assigned to the step
method
parameter. If the step
value cannot be parsed as a 32-bit signed
integer, an HTTP 400 ("Client Error") response is returned.
User-defined Java programming language types may be used as query
parameters. The following code example shows the ColorParam
class used
in the preceding query parameter example:
public class ColorParam extends Color {
public ColorParam(String s) {
super(getRGB(s));
}
private static int getRGB(String s) {
if (s.charAt(0) == '#') {
try {
Color c = Color.decode("0x" + s.substring(1));
return c.getRGB();
} catch (NumberFormatException e) {
throw new WebApplicationException(400);
}
} else {
try {
Field f = Color.class.getField(s);
return ((Color)f.get(null)).getRGB();
} catch (Exception e) {
throw new WebApplicationException(400);
}
}
}
}
The constructor for ColorParam
takes a single String
parameter.
Both @QueryParam
and @PathParam
can be used only on the following
Java types.
-
All primitive types except char
.
-
All wrapper classes of primitive types except Character
.
-
Any class with a constructor that accepts a single String
argument.
-
Any class with the static method named valueOf(String)
that accepts
a single String
argument.
-
List<T>
, Set<T>
, or SortedSet<T>
, where T matches the already
listed criteria. Sometimes, parameters may contain more than one value
for the same name. If this is the case, these types may be used to
obtain all values.
If @DefaultValue
is not used in conjunction with @QueryParam
, and
the query parameter is not present in the request, the value will be an
empty collection for List
, Set
, or SortedSet
; null for other
object types; and the default for primitive types.
URI path parameters are extracted from the request URI, and the
parameter names correspond to the URI path template variable names
specified in the @Path
class-level annotation. URI parameters are
specified using the javax.ws.rs.PathParam
annotation in the method
parameter arguments. The following example shows how to use @Path
variables and the @PathParam
annotation in a method:
@Path("/{username}")
public class MyResourceBean {
...
@GET
public String printUsername(@PathParam("username") String userId) {
...
}
}
In the preceding snippet, the URI path template variable name username
is specified as a parameter to the printUsername
method. The
@PathParam
annotation is set to the variable name username
. At
runtime, before printUsername
is called, the value of username
is
extracted from the URI and cast to a String
. The resulting String
is
then available to the method as the userId
variable.
If the URI path template variable cannot be cast to the specified type,
the JAX-RS runtime returns an HTTP 400 ("Bad Request") error to the
client. If the @PathParam
annotation cannot be cast to the specified
type, the JAX-RS runtime returns an HTTP 404 ("Not Found") error to the
client.
The @PathParam
parameter and the other parameter-based annotations
(@MatrixParam
, @HeaderParam
, @CookieParam
, and @FormParam
) obey
the same rules as @QueryParam
.
Cookie parameters, indicated by decorating the parameter with
javax.ws.rs.CookieParam
, extract information from the cookies declared
in cookie-related HTTP headers. Header parameters, indicated by
decorating the parameter with javax.ws.rs.HeaderParam
, extract
information from the HTTP headers. Matrix parameters, indicated by
decorating the parameter with javax.ws.rs.MatrixParam
, extract
information from URL path segments.
Form parameters, indicated by decorating the parameter with
javax.ws.rs.FormParam
, extract information from a request
representation that is of the MIME media type
application/x-www-form-urlencoded
and conforms to the encoding
specified by HTML forms, as described in
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
. This
parameter is very useful for extracting information sent by POST in HTML
forms.
The following example extracts the name
form parameter from the POST
form data:
@POST
@Consumes("application/x-www-form-urlencoded")
public void post(@FormParam("name") String name) {
// Store the message
}
To obtain a general map of parameter names and values for query and path
parameters, use the following code:
@GET
public String get(@Context UriInfo ui) {
MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
MultivaluedMap<String, String> pathParams = ui.getPathParameters();
}
The following method extracts header and cookie parameter names and
values into a map:
@GET
public String get(@Context HttpHeaders hh) {
MultivaluedMap<String, String> headerParams = hh.getRequestHeaders();
Map<String, Cookie> pathParams = hh.getCookies();
}
In general, @Context
can be used to obtain contextual Java types
related to the request or response.
For form parameters, it is possible to do the following:
@POST
@Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// Store the message
}