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 )
Every exercise in this book will follow the directory structure shown in Figure 18-1.
Table 18-1 describes the purpose of the various directories.
Figure 18-1. Example directory structure
Table 18-1. Directory structure description
Directory
Description
src
Top-level directory that contains all source and configuration files.
src/main
Contains all Java source code and configuration files that are used to create your package. In this case, we’re
creating a WAR file.
src/main/java
Contains server-side Java source code.
src/main/webapp Contains servlet configuration files, specifically web.xml.
src/test/java
Contains Java source code that will be used to run tests on the packaged archive. This code will not be included
within our WAR file.
Deconstructing pom.xml
The pom.xml file provided for each workbook exercise gives the Maven utility infor‐
mation about how to compile and deploy your Java programs. In our case, Maven will
use the information within the pom.xml file to compile the code within src/main/java,
create a WAR file using the web.xml file within src/main/webapp, deploy the WAR file
automatically using the Jetty-embedded servlet container, and finally, run any test code
that is within the src/test/java directory.
254
|
Chapter 18: Examples for Chapter 3
www.it-ebooks.info
Here’s a breakdown of what is contained within pom.xml:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/
POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
In this initial part of the pom.xml file, we’re inheriting from a parent Maven module.
This parent module defines the default configuration for Maven plug-ins as well as the
location of remote Maven repositories to use to download library dependencies.
artifactId is the name of the project. It is also used for the name of the WAR file that
is created by the build unless you override it with the finalName element in the build
section of the POM. This artifact belongs to a family of packages defined by the element
groupId.
The version element identifies the version of the project we are creating. Generally, this
version text is appended to the artifactId when Maven creates the WAR file, but you’ll
see later that we have overridden this with the finalName element.
The packaging element tells Maven that this project is building a WAR file. Other values
for packaging could be jar, if we were creating a JAR, or ear for a Java EE enterprise
archive.
Build and Run the Example Program
www.it-ebooks.info
|
255
The dependencies element lists all library dependencies our ex03_1 project needs to
compile and run. We are dependent on the RESTEasy project, as this is the JAX-RS
implementation we are using. We are also dependent on the JUnit library for running
the test code in our project. Prior to building, Maven will search for these libraries within
the remote repositories listed in the parent POM. It will then download these libraries
to your machine along with each of the transitive dependencies that these libraries have.
What do I mean by transitive dependencies? Well, for example, RESTEasy depends on
a multitude of third-party libraries like the servlet and JAXB APIs. The repository in
which RESTEasy resides contains metadata about RESTEasy’s dependencies. Maven
will discover these extra dependencies when it tries to download the RESTEasy JAR.
Unless you define a scope element, each dependency and its transitive dependencies
will be included in your WAR’s WEB-INF/lib directory when it is built. Take a look
specifically at the junit dependency:
The junit dependency has a scope of test. This means that this library is only used to
run the tests and therefore does not need to be included within the WAR. If you were
building this WAR file to be deployed on the JBoss or Wildfly application servers, you
would not want to include all of these RESTEasy dependencies within the WAR file.
This is because these application servers already come with JAX-RS preinstalled. In this
case, you would define a scope of provided for each of the other dependencies listed
in this file. For example:
256
|
Chapter 18: Examples for Chapter 3
www.it-ebooks.info
The provided scope tells Maven that this is a dependency that is needed to compile your
code, but that the environment in which you will deploy this WAR already includes the
dependency.
OK, now that we’ve got that covered. Let’s look at the rest of our pom.xml file:
The build element contains configuration information related to how Maven should
build our project. The first item we have under this section is the finalName element.
This element overrides the default file naming conventions of Maven. Here we’re stating
that we want our WAR file to be named ex03_1.war.
Next we have the plugins element. This section defines the configuration for the Maven
plug-ins that will be used to build the project:
The first plugin listed is the compiler plug-in, which is used to configure the Java com‐
piler. Here, the plug-in is configured to compile our source code into the Java 6 bytecode
format:
Build and Run the Example Program
www.it-ebooks.info
|
257
The next plug-in we need to configure is surefire-it. This plug-in controls how our
test execution works. By default, Maven will compile the source code under src/main/
java and src/test/java and then try to run the tests under src/test/java. If the tests succeed,
it packages the .class files into a WAR or JAR file. In our case, though, we want to create
a WAR file and deploy it to the Jetty-embedded servlet container before we run our test
code. The surefire-it configuration listed tells Maven not to run the test code until
the WAR file has been built and deployed to Jetty:
The final plug-in is the Jetty plug-in, which is responsible for running the Jettyembedded servlet container. After the WAR file is built, the Jetty container will boot up
an HTTP server under port 8080. The WAR file is then deployed into Jetty.
258
| Chapter 18: Examples for Chapter 3
www.it-ebooks.info
I don’t really need to explain the specifics of the entire Jetty plug-in configuration. The
interesting bits that you might want to tweak are the port (8080) and the stopPort
(9999). You may have to change these if there is a service on your computer already
using these network ports.
Running the Build
To run the build, simply type mvn install at the command prompt from the ex03_1
directory. The output will look something like this:
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------------------------------------------------[INFO] Building ex03_1 2.0
[INFO] -----------------------------------------------------------------------[INFO]
Downloading: http://download.java.net/maven/1
/org.jboss.resteasy/poms/resteasy-jaxrs-3.0.5.Final.pom
...
You’ll see Maven downloading a bunch of files from the repositories. This may take a
while the first time you run the build script, as Maven needs to pull down a huge number
of dependencies:
[INFO] Compiling 3 source files to C:\resteasy\p1b-repo\master\jaxrs
\examples\oreilly-jaxrs-2.0-workbook
\ex03_1\target\classes
[INFO]
[INFO]
[INFO] Compiling 1 source file to C:\resteasy\p1b-repo\master\jaxrs
\examples\oreilly-jaxrs-2.0-workbook
\ex03_1\target\test-classes
Next, you’ll see Maven compiling your main and test source code:
[INFO] Tests are skipped.
[INFO]
[INFO] Packaging webapp
[INFO] Assembling webapp [jaxrs-2.0-workbook-ex03_1] in
[C:\resteasy\p1b-repo\master\jaxrs
\examples\oreilly-jaxrs-2.0-workbook
\ex03_1\target\ex03_1]
[INFO] Processing war project
[INFO] Copying webapp resources [C:\resteasy\p1b-repo
\master\jaxrs
\examples\oreilly-jaxrs-2.0-workbook
\ex03_1\src\main\webapp]
[INFO] Webapp assembled in [172 msecs]
[INFO] Building war: C:\resteasy\p1b-repo\master\jaxrs
\examples
\oreilly-jaxrs-2.0-workbook
\ex03_1\target\ex03_1.war
Build and Run the Example Program
www.it-ebooks.info
|
259
Then you’ll see that the WAR file is built:
[INFO] Started Jetty Server
[INFO]
[INFO] Surefire report directory: C:\resteasy\p1b-repo
\master\jaxrs\examples
\oreilly-jaxrs-2.0-workbook\
ex03_1\target\surefire-reports
[source,java]
------------------------------------------------------T E S T S
------------------------------------------------------Running com.restfully.shop.test.CustomerResourceTest
*** Create a new Customer ***
Created customer 1
Location: http://localhost:8080/services/customers/1
*** GET Created Customer **
**** After Update ***
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.487 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Finally, Maven will start Jetty, deploy the WAR file created, and run the test code under
src/test/java:
[INFO]
[INFO]
[INFO] -----------------------------------------------------------------------[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
260
|
Chapter 18: Examples for Chapter 3
www.it-ebooks.info
[INFO]
[INFO]
[INFO]
[INFO]
Total time: 4.462s
Finished at: Mon Aug 26 12:44:11 EDT 2013
Final Memory: 23M/618M
------------------------------------------------------------------------
The output of the build should end with BUILD SUCCESS.
Examining the Source Code
The server-side source code is exactly as posted in Chapter 3. The guts of the client code
are the same as in Chapter 3, but the client code is structured as a JUnit class. JUnit is
an open source Java library for defining unit tests. Maven automatically knows how to
find JUnit-enabled test code and run it with the build. It scans the classes within the
src/test/java directory, looking for classes that have methods annotated with @org.ju
nit.Test. This example has only one: com.restfully.shop.test.CustomerResour
ceTest. Let’s go over the code for it that is different from the book:
src/test/java/com/restfully/shop/test/CustomerResourceTest.java
package com.restfully.shop.test;
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 CustomerResourceTest
{
@Test
public void testCustomerResource() throws Exception {
Our test class has only one method: testCustomerResource(). It is annotated with
@Test. This tells Maven that this method is a JUnit test. The code for this method is
exactly the same as the client code in Chapter 3. When you run the build, Maven will
execute the code within this method to run the example.
That’s it! The rest of the examples in this book have the same Maven structure as ex03_1
and are tested using JUnit.
Examining the Source Code
www.it-ebooks.info
|
261
www.it-ebooks.info
CHAPTER 19
Examples for Chapter 4
Chapter 4 discussed three things. First, it mentioned how the @javax.ws.rs.HttpMe
thod annotation works and how to define and bind Java methods to new HTTP meth‐
ods. Next, it talked about the intricacies of the @Path annotation, and explained how
you can use complex regular expressions to define your application’s published URIs.
Finally, the chapter went over the concept of subresource locators.
This chapter walks you through three different example programs that you can build
and run to illustrate the concepts in Chapter 4. The first example uses @HttpMethod to
define a new HTTP method called PATCH. The second example expands on the cus‐
tomer service database example from Chapter 18 by adding some funky regular ex‐
pression mappings with @Path. The third example implements the subresource locator
example shown in “Full Dynamic Dispatching” on page 52 in Chapter 4.
Example ex04_1: HTTP Method Extension
This example shows you how your JAX-RS services can consume HTTP methods other
than the common standard ones defined in HTTP 1.1. Specifically, the example imple‐
ments the PATCH method. The PATCH method was originally mentioned in an earlier
draft version of the HTTP 1.1 specification:1
The PATCH method is similar to PUT except that the entity contains a list of differences
between the original version of the resource identified by the Request-URI and the desired
content of the resource after the PATCH action has been applied.
The idea of PATCH is that instead of transmitting the entire representation of a resource
to update it, you only have to provide a partial representation in your update request.
1. For more information, see http://www.ietf.org/rfc/rfc2068.txt.
263
www.it-ebooks.info
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