Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (7.32 MB, 392 trang )
PUT requires that you transmit the entire representation, so the original plan was to
include PATCH for scenarios where sending everything is not optimal.
Build and Run the Example Program
Perform the following steps:
1. Open a command prompt or shell terminal and change to the ex04_1 directory of
the workbook example code.
2. Make sure your PATH is set up to include both the JDK and Maven, as described
in Chapter 17.
3. Perform the build and run the example by typing mvn install.
The Server Code
Using PATCH within JAX-RS is very simple. The source code under the ex04_1 direc‐
tory contains a simple annotation that implements PATCH:
src/main/java/org/ieft/annotations/PATCH.java
package org.ieft.annotations;
import javax.ws.rs.HttpMethod;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH
{
}
As described in Chapter 4, all you need to do to use a custom HTTP method is annotate
an annotation class with @javax.ws.rs.HttpMethod. This @HttpMethod declaration
must contain the value of the new HTTP method you are defining.
To illustrate the use of our new @PATCH annotation, I expanded a little bit on the example
code discussed in Chapter 18. A simple JAX-RS method is added to the CustomerRe
source class that can handle PATCH requests:
src/main/java/com/restfully/shop/services/CustomerResource.java
package com.restfully.shop.services;
@Path("/customers")
public class CustomerResource {
...
264
|
Chapter 19: Examples for Chapter 4
www.it-ebooks.info
@PATCH
@Path("{id}")
@Consumes("application/xml")
public void patchCustomer(@PathParam("id") int id, InputStream is)
{
updateCustomer(id, is);
}
...
}
The @PATCH annotation is used on the patchCustomer() method. The implementation
of this method simply delegates to the original updateCustomer() method.
The Client Code
The client code for ex04_1 is pretty straightforward and similar to ex03_1. Let’s look at
some initial minor changes we’ve made:
src/test/java/com/restfully/shop/test/PatchTest.java
package com.restfully.shop.test;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import
import
import
import
javax.ws.rs.client.Client;
javax.ws.rs.client.ClientBuilder;
javax.ws.rs.client.Entity;
javax.ws.rs.core.Response;
/**
* @author Bill Burke
* @version $Revision: 1 $
*/
public class PatchTest
{
private static Client client;
@BeforeClass
public static void initClient()
{
client = ClientBuilder.newClient();
}
@AfterClass
public static void closeClient()
{
client.close();
}
Example ex04_1: HTTP Method Extension
www.it-ebooks.info
|
265
First, we initialize our Client object within a JUNit @BeforeClass block. Any static
method you annotate with @BeforeClass in JUnit will be executed once before all @Test
methods are executed. So, in the initClient() method we initialize an instance of
Client. Static methods annotated with @AfterClass are executed once after all @Test
methods have run. The closeClient() method cleans up our Client object by invoking
close() after all tests have run. This is a nice way of putting repetitive initialization and
cleanup code that is needed for each test in one place.
The rest of the class is pretty straightforward and similar to ex03_1. I’ll highlight only
the interesting parts:
String patchCustomer = "
+ "
+ "
response = client.target(location)
.request().method("PATCH", Entity.xml(patchCustomer));
if (response.getStatus() != 204)
throw new RuntimeException("Failed to update");
response.close();
To make a PATCH HTTP invocation, we use the javax.ws.rs.client.SyncInvok
er.method() method. The parameters to this method are a string denoting the HTTP
method you want to invoke and the entity you want to pass as the message body. Simple
as that.
Example ex04_2: @Path with Expressions
For this section, I’ll illustrate the use of an @Path annotation with regular expressions.
The example is a direct copy of the code in ex03_1 with a few minor modifications.
Build and Run the Example Program
Perform the following steps:
1. Open a command prompt or shell terminal and change to the ex04_2 directory of
the workbook example code.
2. Make sure your PATH is set up to include both the JDK and Maven, as described
in Chapter 17.
3. Perform the build and run the example by typing maven install.
The Server Code
The CustomerResource class copied from the ex03_1 example is pretty much the same
in ex04_2, except that a few of the @Path expressions have been modified. I also added
266
| Chapter 19: Examples for Chapter 4
www.it-ebooks.info
an extra method that allows you to reference customers by their first and last names
within the URL path:
@Path("/customers")
public class CustomerResource {
...
@GET
@Path("{id : \\d+}")
@Produces("application/xml")
public StreamingOutput getCustomer(@PathParam("id") int id)
{
...
}
@PUT
@Path("{id : \\d+}")
@Consumes("application/xml")
public void updateCustomer(@PathParam("id") int id, InputStream is)
{
...
}
The @Path expression for getCustomer() and updateCustomer() was changed a little
bit to use a Java regular expression for the URI matching. The expression dictates that
the id segment of the URI can only be a string of digits. So, /customers/333 is a legal
URI, but /customers/a32ab would result in a 404, “Not Found,” response code being
returned to the client:
@GET
@Path("{first : [a-zA-Z]+}-{last:[a-zA-Z]+}")
@Produces("application/xml")
public StreamingOutput getCustomerFirstLast(
@PathParam("first") String first,
@PathParam("last") String last)
{
...
}
To show a more complex regular expression, I added the getCustomerFirstLast()
method to the resource class. This method provides a URI pointing to a specific cus‐
tomer, using the customer’s first and last names instead of a numeric ID. This @Path
expression matches a string of the first name and last name separated by a hyphen
character. A legal URI is /customers/Bill-Burke. The name can only have letters
within it, so /customers/Bill7-Burke would result in a 404, “Not Found,” being re‐
turned to the client.
Example ex04_2: @Path with Expressions
www.it-ebooks.info
|
267
The Client Code
The client code is in src/test/java/com/restfully/shop/test/ClientResourceTest.java. It is
really not much different than the code in example ex03_1, other than the fact that it
additionally invokes the URI represented by the getCustomerFirstLast() method. If
you’ve examined the code from Chapter 18, you can probably understand what is going
on in this client example, so I won’t elaborate further.
Example ex04_3: Subresource Locators
The ex04_3 example implements the subresource locator example shown in “Full Dy‐
namic Dispatching” on page 52 in Chapter 4.
Build and Run the Example Program
Perform the following steps:
1. Open a command prompt or shell terminal and change to the ex04_3 directory of
the workbook example code.
2. Make sure your PATH is set up to include both the JDK and Maven, as described
in Chapter 17.
3. Perform the build and run the example by typing maven install.
The Server Code
There’s really not much to go over that wasn’t explained in Chapter 4.
The Client Code
The client code lives in src/test/java/com/restfully/shop/test/CustomerResourceT‐
est.java:
public class CustomerResourceTest
{
@Test
public void testCustomerResource() throws Exception {
...
}
@Test
public void testFirstLastCustomerResource() throws Exception {
...
}
}
268
|
Chapter 19: Examples for Chapter 4
www.it-ebooks.info
The code contains two methods: testCustomerResource() and testFirstLastCusto
merResource().
The testCustomerResource() method first performs a POST to /customers/europedb to create a customer using the CustomerResource subresource. It then retrieves the
created customer using GET /customers/europe-db/1.
The testFirstLastCustomerResource() method performs a POST to /customers/
northamerica-db to create a customer using the FirstLastCustomerResource subre‐
source. It then uses GET /customers/northamerica-db/Bill-Burke to retrieve the cre‐
ated customer.
Example ex04_3: Subresource Locators
www.it-ebooks.info
|
269
www.it-ebooks.info
CHAPTER 20
Examples for Chapter 5
Chapter 5 showed you how to use JAX-RS annotations to inject specific information
about an HTTP request into your Java methods and fields. This chapter implements
most of the injection scenarios introduced in Chapter 5 so that you can see these things
in action.
Example ex05_1: Injecting URI Information
This example illustrates the injection annotations that are focused on pulling in infor‐
mation from the incoming request URI. Specifically, it shows how to use @PathParam,
@MatrixParam, and @QueryParam. Parallel examples are also shown using
javax.ws.rs.core.UriInfo to obtain the same data.
The Server Code
The first thing you should look at on the server side is CarResource. This class pulls the
various examples in Chapter 5 together to illustrate using @MatrixParam and @PathPar
am with the javax.ws.rs.core.PathSegment class:
src/main/java/com/restfully/shop/services/CarResource.java
@Path("/cars")
public class CarResource
{
public static enum Color
{
red,
white,
blue,
black
}
271
www.it-ebooks.info
@GET
@Path("/matrix/{make}/{model}/{year}")
@Produces("text/plain")
public String getFromMatrixParam(
@PathParam("make") String make,
@PathParam("model") PathSegment car,
@MatrixParam("color") Color color,
@PathParam("year") String year)
{
return "A " + color + " " + year + " "
+ make + " " + car.getPath();
}
The getFromMatrixParam() method uses the @MatrixParam annotation to inject the
matrix parameter color. An example of a URI it could process is /cars/matrix/
mercedes/e55;color=black/2006. Notice that it automatically converts the matrix pa‐
rameter into the Java enum Color:
@GET
@Path("/segment/{make}/{model}/{year}")
@Produces("text/plain")
public String getFromPathSegment(@PathParam("make") String make,
@PathParam("model") PathSegment car,
@PathParam("year") String year)
{
String carColor = car.getMatrixParameters().getFirst("color");
return "A " + carColor + " " + year + " "
+ make + " " + car.getPath();
}
The getFromPathSegment() method also illustrates how to extract matrix parameter
information. Instead of using @MatrixParam, it uses an injected PathSegment instance
representing the model path parameter to obtain the matrix parameter information:
@GET
@Path("/segments/{make}/{model : .+}/year/{year}")
@Produces("text/plain")
public String getFromMultipleSegments(
@PathParam("make") String make,
@PathParam("model") List
@PathParam("year") String year)
{
String output = "A " + year + " " + make;
for (PathSegment segment : car)
{
output += " " + segment.getPath();
}
return output;
}
The getFromMultipleSegments() method illustrates how a path parameter can match
multiple segments of a URI. An example of a URI that it could process is /cars/
272
| Chapter 20: Examples for Chapter 5
www.it-ebooks.info