The Java EE 6 Tutorial

Part III Web Services

Part III explores web services. This part contains the following chapters:

Chapter 11 Introduction to Web Services

Part III of the tutorial discusses Java EE 6 web services technologies. For this book, these technologies include Java API for XML Web Services (JAX-WS) and Java API for RESTful Web Services (JAX-RS).

The following topics are addressed here:

What Are Web Services?

Web services are client and server applications that communicate over the World Wide Web’s (WWW) HyperText Transfer Protocol (HTTP). As described by the World Wide Web Consortium (W3C), web services provide a standard means of interoperating between software applications running on a variety of platforms and frameworks. Web services are characterized by their great interoperability and extensibility, as well as their machine-processable descriptions, thanks to the use of XML. Web services can be combined in a loosely coupled way to achieve complex operations. Programs providing simple services can interact with each other to deliver sophisticated added-value services.

Types of Web Services

On the conceptual level, a service is a software component provided through a network-accessible endpoint. The service consumer and provider use messages to exchange invocation request and response information in the form of self-containing documents that make very few assumptions about the technological capabilities of the receiver.

On a technical level, web services can be implemented in various ways. The two types of web services discussed in this section can be distinguished as “big” web services and “RESTful” web services.

“Big” Web Services

In Java EE 6, JAX-WS provides the functionality for “big” web services, which are described in Chapter 12, Building Web Services with JAX-WS. Big web services use XML messages that follow the Simple Object Access Protocol (SOAP) standard, an XML language defining a message architecture and message formats. Such systems often contain a machine-readable description of the operations offered by the service, written in the Web Services Description Language (WSDL), an XML language for defining interfaces syntactically.

The SOAP message format and the WSDL interface definition language have gained widespread adoption. Many development tools, such as NetBeans IDE, can reduce the complexity of developing web service applications.

A SOAP-based design must include the following elements.

RESTful Web Services

In Java EE 6, JAX-RS provides the functionality for Representational State Transfer (RESTful) web services. REST is well suited for basic, ad hoc integration scenarios. RESTful web services, often better integrated with HTTP than SOAP-based services are, do not require XML messages or WSDL service–API definitions.

Project Jersey is the production-ready reference implementation for the JAX-RS specification. Jersey implements support for the annotations defined in the JAX-RS specification, making it easy for developers to build RESTful web services with Java and the Java Virtual Machine (JVM).

Because RESTful web services use existing well-known W3C and Internet Engineering Task Force (IETF) standards (HTTP, XML, URI, MIME) and have a lightweight infrastructure that allows services to be built with minimal tooling, developing RESTful web services is inexpensive and thus has a very low barrier for adoption. You can use a development tool such as NetBeans IDE to further reduce the complexity of developing RESTful web services.

A RESTful design may be appropriate when the following conditions are met.

RESTful web services are discussed in Chapter 13, Building RESTful Web Services with JAX-RS. This chapter contains information about generating the skeleton of a RESTful web service using both NetBeans IDE and the Maven project management tool.

Deciding Which Type of Web Service to Use

Basically, you would want to use RESTful web services for integration over the web and use big web services in enterprise application integration scenarios that have advanced quality of service (QoS) requirements.


Note –

For an article that provides more in-depth analysis of this issue, see “RESTful Web Services vs. “Big” Web Services: Making the Right Architectural Decision,” by Cesare Pautasso, Olaf Zimmermann, and Frank Leymann from WWW '08: Proceedings of the 17th International Conference on the World Wide Web (2008), pp. 805–814.


Chapter 12 Building Web Services with JAX-WS

Java API for XML Web Services (JAX-WS) is a technology for building web services and clients that communicate using XML. JAX-WS allows developers to write message-oriented as well as Remote Procedure Call-oriented (RPC-oriented) web services.

In JAX-WS, a web service operation invocation is represented by an XML-based protocol, such as SOAP. The SOAP specification defines the envelope structure, encoding rules, and conventions for representing web service invocations and responses. These calls and responses are transmitted as SOAP messages (XML files) over HTTP.

Although SOAP messages are complex, the JAX-WS API hides this complexity from the application developer. On the server side, the developer specifies the web service operations by defining methods in an interface written in the Java programming language. The developer also codes one or more classes that implement those methods. Client programs are also easy to code. A client creates a proxy (a local object representing the service) and then simply invokes methods on the proxy. With JAX-WS, the developer does not generate or parse SOAP messages. It is the JAX-WS runtime system that converts the API calls and responses to and from SOAP messages.

With JAX-WS, clients and web services have a big advantage: the platform independence of the Java programming language. In addition, JAX-WS is not restrictive: A JAX-WS client can access a web service that is not running on the Java platform, and vice versa. This flexibility is possible because JAX-WS uses technologies defined by the W3C: HTTP, SOAP, and WSDL. WSDL specifies an XML format for describing a service as a set of endpoints operating on messages.


Note –

Several files in the JAX-WS examples depend on the port that you specified when you installed the GlassFish Server. These tutorial examples assume that the server runs on the default port, 8080. They do not run with a nondefault port setting.


The following topics are addressed here:

Creating a Simple Web Service and Clients with JAX-WS

This section shows how to build and deploy a simple web service and two clients: an application client and a web client. The source code for the service is in the directory tut-install/examples/jaxws/helloservice/, and the clients are in the directories tut-install/examples/jaxws/appclient/ and tut-install/examples/jaxws/webclient/.

Figure 12–1 illustrates how JAX-WS technology manages communication between a web service and a client.

Figure 12–1 Communication between a JAX-WS Web Service and a Client

Diagram showing a client and web service communicating
through a SOAP message.

The starting point for developing a JAX-WS web service is a Java class annotated with the javax.jws.WebService annotation. The @WebService annotation defines the class as a web service endpoint.

A service endpoint interface or service endpoint implementation (SEI) is a Java interface or class, respectively, that declares the methods that a client can invoke on the service. An interface is not required when building a JAX-WS endpoint. The web service implementation class implicitly defines an SEI.

You may specify an explicit interface by adding the endpointInterface element to the @WebService annotation in the implementation class. You must then provide an interface that defines the public methods made available in the endpoint implementation class.

    The basic steps for creating a web service and client are as follows:

  1. Code the implementation class.

  2. Compile the implementation class.

  3. Package the files into a WAR file.

  4. Deploy the WAR file. The web service artifacts, which are used to communicate with clients, are generated by the GlassFish Server during deployment.

  5. Code the client class.

  6. Use a wsimport Ant task to generate and compile the web service artifacts needed to connect to the service.

  7. Compile the client class.

  8. Run the client.

If you use NetBeans IDE to create a service and client, the IDE performs the wsimport task for you.

The sections that follow cover these steps in greater detail.

Requirements of a JAX-WS Endpoint

JAX-WS endpoints must follow these requirements.

Coding the Service Endpoint Implementation Class

In this example, the implementation class, Hello, is annotated as a web service endpoint using the @WebService annotation. Hello declares a single method named sayHello, annotated with the @WebMethod annotation, which exposes the annotated method to web service clients. The sayHello method returns a greeting to the client, using the name passed to it to compose the greeting. The implementation class also must define a default, public, no-argument constructor.

package helloservice.endpoint;

import javax.jws.WebService;
import javax.jws.webMethod;

@WebService
public class Hello {
    private String message = new String("Hello, ");

    public void Hello() {
    }

    @WebMethod
    public String sayHello(String name) {
        return message + name + ".";
    }
}

Building, Packaging, and Deploying the Service

You can build, package, and deploy the helloservice application by using either NetBeans IDE or Ant.

ProcedureTo Build, Package, and Deploy the Service Using NetBeans IDE

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to:


    tut-install/examples/jaxws/
    
  3. Select the helloservice folder.

  4. Select the Open as Main Project check box.

  5. Click Open Project.

  6. In the Projects tab, right-click the helloservice project and select Deploy.

    This command builds and packages the application into helloservice.war, located in tut-install/examples/jaxws/helloservice/dist/, and deploys this WAR file to the GlassFish Server.

Next Steps

You can view the WSDL file of the deployed service by requesting the URL http://localhost:8080/helloservice/HelloService?wsdl in a web browser. Now you are ready to create a client that accesses this service.

ProcedureTo Build, Package, and Deploy the Service Using Ant

  1. In a terminal window, go to:


    tut-install/examples/jaxws/helloservice/
    
  2. Type the following command:


    ant
    

    This command calls the default target, which builds and packages the application into a WAR file, helloservice.war, located in the dist directory.

  3. Make sure that the GlassFish Server is started.

  4. Type the following:


    ant deploy
    
Next Steps

You can view the WSDL file of the deployed service by requesting the URL http://localhost:8080/helloservice/HelloService?wsdl in a web browser. Now you are ready to create a client that accesses this service.

Testing the Methods of a Web Service Endpoint

GlassFish Server allows you to test the methods of a web service endpoint.

ProcedureTo Test the Service without a Client

To test the sayHello method of HelloService, follow these steps.

  1. Open the web service test interface by typing the following URL in a web browser:


    http://localhost:8080/helloservice/HelloService?Tester
  2. Under Methods, type a name as the parameter to the sayHello method.

  3. Click the sayHello button.

    This takes you to the sayHello Method invocation page.

    Under Method returned, you’ll see the response from the endpoint.

A Simple JAX-WS Application Client

The HelloAppClient class is a stand-alone application client that accesses the sayHello method of HelloService. This call is made through a port, a local object that acts as a proxy for the remote service. The port is created at development time by the wsimport task, which generates JAX-WS portable artifacts based on a WSDL file.

Coding the Application Client

    When invoking the remote methods on the port, the client performs these steps:

  1. Uses the generated helloservice.endpoint.HelloService class, which represents the service at the URI of the deployed service’s WSDL file:

    import helloservice.endpoint.HelloService;
    import javax.xml.ws.WebServiceRef;
    
    public class HelloAppClient {
        @WebServiceRef(wsdlLocation = 
          "META-INF/wsdl/localhost_8080/helloservice/HelloService.wsdl")
        private static HelloService service;
  2. Retrieves a proxy to the service, also known as a port, by invoking getHelloPort on the service:

    helloservice.endpoint.Hello port = service.getHelloPort();

    The port implements the SEI defined by the service.

  3. Invokes the port’s sayHello method, passing a string to the service:

    return port.sayHello(arg0);

Here is the full source of HelloAppClient, which is located in the following directory:


tut-install/examples/jaxws/appclient/src/appclient/
package appclient;

import helloservice.endpoint.HelloService;
import javax.xml.ws.WebServiceRef;

public class HelloAppClient {
    @WebServiceRef(wsdlLocation = 
      "META-INF/wsdl/localhost_8080/helloservice/HelloService.wsdl")
    private static HelloService service;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       System.out.println(sayHello("world"));
    }

    private static String sayHello(java.lang.String arg0) {
        helloservice.endpoint.Hello port = service.getHelloPort();
        return port.sayHello(arg0);
    }
}

Building, Packaging, Deploying, and Running the Application Client

You can build, package, deploy, and run the appclient application by using either NetBeans IDE or Ant. To build the client, you must first have deployed helloservice, as described in Building, Packaging, and Deploying the Service.

ProcedureTo Build, Package, Deploy, and Run the Application Client Using NetBeans IDE

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to:


    tut-install/examples/jaxws/
    
  3. Select the appclient folder.

  4. Select the Open as Main Project check box.

  5. Click Open Project.

  6. In the Projects tab, right-click the appclient project and select Run.

    You will see the output of the application client in the Output pane.

ProcedureTo Build, Package, Deploy, and Run the Application Client Using Ant

  1. In a terminal window, go to:


    tut-install/examples/jaxws/appclient/
    
  2. Type the following command:


    ant
    

    This command calls the default target, which runs the wsimport task and builds and packages the application into a JAR file, appclient.jar, located in the dist directory.

  3. To run the client, type the following command:


    ant run
    

A Simple JAX-WS Web Client

HelloServlet is a servlet that, like the Java client, calls the sayHello method of the web service. Like the application client, it makes this call through a port.

Coding the Servlet

    To invoke the method on the port, the client performs these steps:

  1. Imports the HelloService endpoint and the WebServiceRef annotation:

    import helloservice.endpoint.HelloService;
    ...
    import javax.xml.ws.WebServiceRef;
  2. Defines a reference to the web service by specifying the WSDL location:

    @WebServiceRef(wsdlLocation = 
      "WEB-INF/wsdl/localhost_8080/helloservice/HelloService.wsdl")
  3. Declares the web service, then defines a private method that calls the sayHello method on the port:

    private HelloService service;
    ...
    private String sayHello(java.lang.String arg0) {
        helloservice.endpoint.Hello port = service.getHelloPort();
        return port.sayHello(arg0);
    }
  4. In the servlet, calls this private method:

    out.println("<p>" + sayHello("world") + "</p>");

The significant parts of the HelloServlet code follow. The code is located in the tut-install/examples/jaxws/src/java/webclient directory.

package webclient;

import helloservice.endpoint.HelloService;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.WebServiceRef;

@WebServlet(name="HelloServlet", urlPatterns={"/HelloServlet"})
public class HelloServlet extends HttpServlet {
    @WebServiceRef(wsdlLocation = 
      "WEB-INF/wsdl/localhost_8080/helloservice/HelloService.wsdl")
    private HelloService service;
   
    /** 
     * Processes requests for both HTTP <code>GET</code> 
     *   and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, 
            HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet HelloServlet</title>");  
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet HelloServlet at " + 
                request.getContextPath () + "</h1>");
            out.println("<p>" + sayHello("world") + "</p>");
            out.println("</body>");
            out.println("</html>");
            
        } finally { 
            out.close();
        }
    } 
    
    // doGet and doPost methods, which call processRequest, and
    //   getServletInfo method
    
    private String sayHello(java.lang.String arg0) {
        helloservice.endpoint.Hello port = service.getHelloPort();
        return port.sayHello(arg0);
    }
}

Building, Packaging, Deploying, and Running the Web Client

You can build, package, deploy, and run the webclient application by using either NetBeans IDE or Ant. To build the client, you must first have deployed helloservice, as described in Building, Packaging, and Deploying the Service.

ProcedureTo Build, Package, Deploy, and Run the Web Client Using NetBeans IDE

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to:


    tut-install/examples/jaxws/
    
  3. Select the webclient folder.

  4. Select the Open as Main Project check box.

  5. Click Open Project.

  6. In the Projects tab, right-click the webclient project and select Deploy.

    This task runs the wsimport tasks, builds and packages the application into a WAR file, webclient.war, located in the dist directory, and deploys it to the server.

  7. In a web browser, navigate to the following URL:

    http://localhost:8080/webclient/HelloServlet

    The output of the sayHello method appears in the window.

ProcedureTo Build, Package, Deploy, and Run the Web Client Using Ant

  1. In a terminal window, go to:


    tut-install/examples/jaxws/webclient/
    
  2. Type the following command:


    ant
    

    This command calls the default target, which runs the wsimport tasks, then builds and packages the application into a WAR file, webclient.war, located in the dist directory.

  3. Type the following command:


    ant deploy
    

    This task deploys the WAR file to the server.

  4. In a web browser, navigate to the following URL:

    http://localhost:8080/webclient/HelloServlet

    The output of the sayHello method appears in the window.

Types Supported by JAX-WS

JAX-WS delegates the mapping of Java programming language types to and from XML definitions to JAXB. Application developers don’t need to know the details of these mappings but should be aware that not every class in the Java language can be used as a method parameter or return type in JAX-WS. For information on which types are supported by JAXB, see the list of JAXB default data type bindings at http://download.oracle.com/javaee/5/tutorial/doc/bnazq.html#bnazs.

Web Services Interoperability and JAX-WS

JAX-WS supports the Web Services Interoperability (WS-I) Basic Profile Version 1.1. The WS-I Basic Profile is a document that clarifies the SOAP 1.1 and WSDL 1.1 specifications to promote SOAP interoperability. For links related to WS-I, see Further Information about JAX-WS.

To support WS-I Basic Profile Version 1.1, the JAX-WS runtime supports doc/literal and rpc/literal encodings for services, static ports, dynamic proxies, and the Dynamic Invocation Interface (DII).

Further Information about JAX-WS

For more information about JAX-WS and related technologies, see

Chapter 13 Building RESTful Web Services with JAX-RS

This chapter describes the REST architecture, RESTful web services, and the Java API for RESTful Web Services (JAX-RS, defined in JSR 311).

Jersey, the reference implementation of JAX-RS, implements support for the annotations defined in JSR 311, making it easy for developers to build RESTful web services by using the Java programming language.

If you are developing with GlassFish Server, you can install the Jersey samples and documentation by using the Update Tool. Instructions for using the Update Tool can be found in Java EE 6 Tutorial Component. The Jersey samples and documentation are provided in the Available Add-ons area of the Update Tool.

The following topics are addressed here:

What Are RESTful Web Services?

RESTful web services are built to work best on the Web. Representational State Transfer (REST) is an architectural style that specifies constraints, such as the uniform interface, that if applied to a web service induce desirable properties, such as performance, scalability, and modifiability, that enable services to work best on the Web. In the REST architectural style, data and functionality are considered resources and are accessed using Uniform Resource Identifiers (URIs), typically links on the Web. The resources are acted upon by using a set of simple, well-defined operations. The REST architectural style constrains an architecture to a client/server architecture and is designed to use a stateless communication protocol, typically HTTP. In the REST architecture style, clients and servers exchange representations of resources by using a standardized interface and protocol.

The following principles encourage RESTful applications to be simple, lightweight, and fast:

Creating a RESTful Root Resource Class

Root resource classes are 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 13–1 lists some of the Java programming annotations that are defined by JAX-RS, with a brief description of how each is used. Further information on the JAX-RS APIs can be viewed at http://download.oracle.com/javaee/6/api/.

Table 13–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.

@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.

Overview of a JAX-RS Application

The following code sample is a very simple example of a root resource class that uses JAX-RS annotations:

package com.sun.jersey.samples.helloworld.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;

// The Java class will be hosted at the URI path "/helloworld"
@Path("/helloworld")
public class HelloWorldResource {
    
    // The Java method will process HTTP GET requests
    @GET
    // The Java method will produce content identified by the MIME Media
    // type "text/plain"
    @Produces("text/plain")
    public String getClichedMessage() {
        // Return some cliched textual content
        return "Hello World";
    }
}

The following sections describe the annotations used in this example.

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 whether or not they have leading or trailing spaces.

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.

For example, if you want to deploy a resource that responds to the URI path template http://example.com/myContextRoot/resources/{name1}/{name2}/, you must deploy the application to a Java EE server that responds to requests to the http://example.com/myContextRoot URI and then decorate your resource with the following @Path annotation:

@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>My JAX-RS Resource</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 13–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:


Note –

The value of the name3 variable is an empty string.


Table 13–2 Examples of URI Path Templates

URI Path Template 

URI After Substitution 

http://example.com/{name1}/{name2}/

http://example.com/james/gatz/

http://example.com/{question}/{question}/{question}/

http://example.com/why/why/why/

http://example.com/maps/{location}

http://example.com/maps/Main%20Street

http://example.com/{name3}/home/

http://example.com//home/

Responding to HTTP Resources

The behavior of a resource is determined by the HTTP methods (typically, GET, POST, PUT, DELETE) to which the resource is responding.

The Request Method Designator Annotations

Request method designator annotations are runtime annotations, defined by JAX-RS, that correspond to the similarly named HTTP methods. Within a resource class file, HTTP methods are mapped to Java programming language methods by using the request method designator annotations. The behavior of a resource is determined by which HTTP method the resource is responding to. JAX-RS defines a set of request method designators for the common HTTP methods @GET, @POST, @PUT, @DELETE, and @HEAD; you can also create your own custom request method designators. Creating custom request method designators is outside the scope of this document.

The following example, an extract from the storage service sample, shows the use of the PUT method to create or update a storage container:

@PUT
public Response putContainer() {
    System.out.println("PUT CONTAINER " + container);

    URI uri =  uriInfo.getAbsolutePath();
    Container c = new Container(container, uri.toString());

    Response r;
    if (!MemoryStore.MS.hasContainer(c)) {
        r = Response.created(uri).build();
    } else {
        r = Response.noContent().build();
    }

    MemoryStore.MS.createContainer(c);
    return r;
}

By default, the JAX-RS runtime will automatically support the methods HEAD and OPTIONS if not explicitly implemented. For HEAD, the runtime will invoke the implemented GET method, if present, and ignore the response entity, if set. For OPTIONS, the Allow response header will be set to the set of HTTP methods supported by the resource. In addition, the JAX-RS runtime will return a Web Application Definition Language (WADL) document describing the resource; see https://wadl.dev.java.net/ for more information.

Methods decorated with request method designators must return void, a Java programming language type, or a javax.ws.rs.core.Response object. Multiple parameters may be extracted from the URI by using the PathParam or QueryParam annotations as described in Extracting Request Parameters. Conversion between Java types and an entity body is the responsibility of an entity provider, such as MessageBodyReader or MessageBodyWriter. Methods that need to provide additional metadata with a response should return an instance of the Response class. The ResponseBuilder class provides a convenient way to create a Response instance using a builder pattern. The HTTP PUT and POST methods expect an HTTP request body, so you should use a MessageBodyReader for methods that respond to PUT and POST requests.

Both @PUT and @POST can be used to create or update a resource. POST can mean anything, so when using POST, it is up to the application to define the semantics. PUT has well-defined semantics. When using PUT for creation, the client declares the URI for the newly created resource.

PUT has very clear semantics for creating and updating a resource. The representation the client sends must be the same representation that is received using a GET, given the same media type. PUT does not allow a resource to be partially updated, a common mistake when attempting to use the PUT method. A common application pattern is to use POST to create a resource and return a 201 response with a location header whose value is the URI to the newly created resource. In this pattern, the web service declares the URI for the newly created resource.

Using Entity Providers to Map HTTP Response and Request Entity Bodies

Entity providers supply mapping services between representations and their associated Java types. The two types of entity providers are 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 by using Response.ResponseBuilder.

Table 13–3 shows the standard types that are supported automatically for entities. You need to write an entity provider only if you are not choosing one of these standard types.

Table 13–3 Types Supported for Entities

Java Type 

Supported Media Types 

byte[]

All media types (*/*)

java.lang.String

All text media types (text/*)

java.io.InputStream

All media types (*/*)

java.io.Reader

All media types (*/*)

java.io.File

All media types (*/*)

javax.activation.DataSource

All media types (*/*)

javax.xml.transform.Source

XML media types (text/xml, application/xml, and application/*+xml)

javax.xml.bind.JAXBElement and application-supplied JAXB classes

XML media types (text/xml, application/xml, and application/*+xml)

MultivaluedMap<String, String>

Form content (application/x-www-form-urlencoded)

StreamingOutput

All media types (*/*), MessageBodyWriter only

The following example shows how to use MessageBodyReader with the @Consumes and @Provider annotations:

@Consumes("application/x-www-form-urlencoded")
@Provider
public class FormReader implements MessageBodyReader<NameValuePair> {

The following example shows how to use MessageBodyWriter with the @Produces and @Provider annotations:

@Produces("text/html")
@Provider
public class FormWriter implements 
        MessageBodyWriter<Hashtable<String, String>> {

The following example shows how to use ResponseBuilder:

@GET
public Response getItem() {
    System.out.println("GET ITEM " + container + " " + item);
    
    Item i = MemoryStore.MS.getItem(container, item);
    if (i == null)
        throw new NotFoundException("Item not found");
    Date lastModified = i.getLastModified().getTime();
    EntityTag et = new EntityTag(i.getDigest());
    ResponseBuilder rb = request.evaluatePreconditions(lastModified, et);
    if (rb != null)
        return rb.build();
        
    byte[] b = MemoryStore.MS.getItemData(container, item);
    return Response.ok(b, i.getMimeType()).
            lastModified(lastModified).tag(et).build();
}

Using @Consumes and @Produces to Customize Requests and Responses

The information sent to a resource and then passed back to the client is specified as a MIME media type in the headers of an HTTP request or response. You can specify which MIME media types of representations a resource can respond to or produce by using the following annotations:

By default, a resource class can respond to and produce all MIME media types of representations specified in the HTTP request and response headers.

The @Produces Annotation

The @Produces annotation is used to specify the MIME media types or representations a resource can produce and send back to the client. If @Produces is applied at the class level, all the methods in a resource can produce the specified MIME types by default. If applied at the method level, the annotation overrides any @Produces annotations applied at the class level.

If no methods in a resource are able to produce the MIME type in a client request, the JAX-RS runtime sends back an HTTP “406 Not Acceptable” error.

The value of @Produces is an array of String of MIME types. For example:

@Produces({"image/jpeg,image/png"})

The following example shows how to apply @Produces at both the class and method levels:

@Path("/myResource")
@Produces("text/plain")
public class SomeResource {
	@GET
	public String doGetAsPlainText() {
		...
	}

	@GET
	@Produces("text/html")
	public String doGetAsHtml() {
		...
	}
}

The doGetAsPlainText method defaults to the MIME media type of the @Produces annotation at the class level. The doGetAsHtml method’s @Produces annotation overrides the class-level @Produces setting and specifies that the method can produce HTML rather than plain text.

If a resource class is capable of producing more than one MIME media type, the resource method chosen will correspond to the most acceptable media type as declared by the client. More specifically, the Accept header of the HTTP request declares what is most acceptable. For example, if the Accept header is Accept: text/plain, the doGetAsPlainText method will be invoked. Alternatively, if the Accept header is Accept: text/plain;q=0.9, text/html, which declares that the client can accept media types of text/plain and text/html but prefers the latter, the doGetAsHtml method will be invoked.

More than one media type may be declared in the same @Produces declaration. The following code example shows how this is done:

@Produces({"application/xml", "application/json"})
public String doGetAsXmlOrJson() {
	...
}

The doGetAsXmlOrJson method will get invoked if either of the media types application/xml and application/json is acceptable. If both are equally acceptable, the former will be chosen because it occurs first. The preceding examples refer explicitly to MIME media types for clarity. It is possible to refer to constant values, which may reduce typographical errors. For more information, see the constant field values of MediaType at https://jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/core/MediaType.html.

The @Consumes Annotation

The @Consumes annotation is used to specify which MIME media types of representations a resource can accept, or consume, from the client. If @Consumes is applied at the class level, all the response methods accept the specified MIME types by default. If applied at the method level, @Consumes overrides any @Consumes annotations applied at the class level.

If a resource is unable to consume the MIME type of a client request, the JAX-RS runtime sends back an HTTP 415 (“Unsupported Media Type”) error.

The value of @Consumes is an array of String of acceptable MIME types. For example:

@Consumes({"text/plain,text/html"})

The following example shows how to apply @Consumes at both the class and method levels:

@Path("/myResource")
@Consumes("multipart/related")
public class SomeResource {
	@POST
	public String doPost(MimeMultipart mimeMultipartData) {
		...
	}

	@POST
	@Consumes("application/x-www-form-urlencoded")
	public String doPost2(FormURLEncodedProperties formData) {
		...
	}
}

The doPost method defaults to the MIME media type of the @Consumes annotation at the class level. The doPost2 method overrides the class level @Consumes annotation to specify that it can accept URL-encoded form data.

If no resource methods can respond to the requested MIME type, an HTTP 415 (“Unsupported Media Type”) error is returned to the client.

The HelloWorld example discussed previously in this section can be modified to set the message by using @Consumes, as shown in the following code example:

@POST
@Consumes("text/plain")
public void postClichedMessage(String message) {
    // Store the message
}

In this example, the Java method will consume representations identified by the MIME media type text/plain. Note that the resource method returns void. This means that no representation is returned and that a response with a status code of HTTP 204 (“No Content”) will be returned.

Extracting Request Parameters

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 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, from the sparklines sample application, 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:

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 = ui.getRequestHeaders();
    Map<String, Cookie> pathParams = ui.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
}

Example Applications for JAX-RS

This section provides an introduction to creating, deploying, and running your own JAX-RS applications. This section demonstrates the steps that are needed to create, build, deploy, and test a very simple web application that uses JAX-RS annotations.

A RESTful Web Service

This section explains how to use NetBeans IDE to create a RESTful web service. NetBeans IDE generates a skeleton for the application, and you simply need to implement the appropriate methods. If you do not use an IDE, try using one of the example applications that ship with Jersey as a template to modify.

ProcedureTo Create a RESTful Web Service Using NetBeans IDE

  1. In NetBeans IDE, create a simple web application. This example creates a very simple “Hello, World” web application.

    1. In NetBeans IDE, select File -> New Project.

    2. From Categories, select Java Web. From Projects, select Web Application. Click Next.


      Note –

      For this step, you could also create a RESTful web service in a Maven web project by selecting Maven as the category and Maven Web Project as the project. The remaining steps would be the same.


    3. Type a project name, HelloWorldApplication, and click Next.

    4. Make sure that the Server is GlassFish Server (or similar wording.)

    5. Click Finish.

    The project is created. The file index.jsp appears in the Source pane.

  2. Right-click the project and select New; then select RESTful Web Services from Patterns.

    1. Select Simple Root Resource and click Next.

    2. Type a Resource Package name, such as helloWorld.

    3. Type helloworld in the Path field. Type HelloWorld in the Class Name field. For MIME Type, select text/html.

    4. Click Finish.

      The REST Resources Configuration page appears.

    5. Click OK.

      A new resource, HelloWorld.java, is added to the project and appears in the Source pane. This file provides a template for creating a RESTful web service.

  3. In HelloWorld.java, find the getHtml() method. Replace the //TODO comment and the exception with the following text, so that the finished product resembles the following method.


    Note –

    Because the MIME type produced is HTML, you can use HTML tags in your return statement.


    /**
     * Retrieves representation of an instance of helloWorld.HelloWorld
     * @return an instance of java.lang.String
     */
    @GET
    @Produces("text/html")
    public String getHtml() {
        return "<html><body><h1>Hello, World!!</body></h1></html>";
    }
  4. Test the web service. To do this, right-click the project node and click Test RESTful Web Services.

    This step deploys the application and brings up a test client in the browser.

  5. When the test client appears, select the helloworld resource in the left pane, and click the Test button in the right pane.

    The words Hello, World!! appear in the Response window below.

  6. Set the Run Properties:

    1. Right-click the project node and select Properties.

    2. In the dialog, select the Run category.

    3. Set the Relative URL to the location of the RESTful web service relative to the Context Path, which for this example is resources/helloworld.


    Tip –

    You can find the value for the Relative URL in the Test RESTful Web Services browser window. In the top of the right pane, after Resource, is the URL for the RESTful web service being tested. The part following the Context Path (http://localhost:8080/HelloWorldApp) is the Relative URL that needs to be entered here.

    If you don’t set this property, the file index.jsp will appear by default when the application is run. As this file also contains Hello World as its default value, you might not notice that your RESTful web service isn’t running, so just be aware of this default and the need to set this property, or update index.jsp to provide a link to the RESTful web service.


  7. Right-click the project and select Deploy.

  8. Right-click the project and select Run.

    A browser window opens and displays the return value of Hello, World!!

See Also

For other sample applications that demonstrate deploying and running JAX-RS applications using NetBeans IDE, see The rsvp Example Application and Your First Cup: An Introduction to the Java EE Platform at http://download.oracle.com/javaee/6/firstcup/doc/. You may also look at the tutorials on the NetBeans IDE tutorial site, such as the one titled “Getting Started with RESTful Web Services” at http://www.netbeans.org/kb/docs/websvc/rest.html. This tutorial includes a section on creating a CRUD application from a database. Create, read, update, and delete (CRUD) are the four basic functions of persistent storage and relational databases.

The rsvp Example Application

The rsvp example application, located in tut-install/examples/jaxrs/rsvp, allows invitees to an event to indicate whether they will attend. The events, people invited to the event, and the responses to the invite are stored in a Java DB database using the Java Persistence API. The JAX-RS resources in rsvp are exposed in a stateless session enterprise bean.

Components of the rsvp Example Application

The three enterprise beans in the rsvp example application are rsvp.ejb.ConfigBean, rsvp.ejb.StatusBean, and rsvp.ejb.ResponseBean.

ConfigBean is a singleton session bean that initializes the data in the database.

StatusBean exposes a JAX-RS resource for displaying the current status of all invitees to an event. The URI path template is declared as follows:

@Path("/status/{eventId}/"}

The URI path variable eventId is a @PathParam variable in the getResponse method, which responds to HTTP GET requests and has been annotated with @GET. The eventId variable is used to look up all the current responses in the database for that particular event.

ResponseBean exposes a JAX-RS resource for setting an invitee's response to a particular event. The URI path template for ResponseBean is declared as follows:

@Path("/{eventId}/{inviteId}

Two URI path variables are declared in the path template: eventId and inviteId. As in StatusBean, eventId is the unique ID for a particular event. Each invitee to that event has a unique ID for the invitation, and that is the inviteId. Both of these path variables are used in two JAX-RS methods in ResponseBean: getResponse and putResponse. The getResponse method responds to HTTP GET requests and displays the invitee's current response and a form to change the response.

An invitee who wants to change his or her response selects the new response and submits the form data, which is processed as an HTTP PUT request by the putResponse method. One of the parameters to the putResponse method, the userResponse string, is annotated with @FormParam("attendeeResponse"). The HTML form created by getResponse stores the changed response in the select list with an ID of attendeeResponse. The annotation @FormParam("attendeeResponse") indicates that the value of the select response is extracted from the HTTP PUT request and stored as the userResponse string. The putResponse method uses userResponse, eventId, and inviteId to update the invitee's response in the database.

The events, people, and responses in rsvp are encapsulated in Java Persistence API entities. The rsvp.entity.Event, rsvp.entity.Person, and rsvp.entity.Response entities respectively represent events, invitees, and responses to an event.

The rsvp.util.ResponseEnum class declares an enumerated type that represents all the possible response statuses an invitee may have.

Running the rsvp Example Application

Both NetBeans IDE and Ant can be used to deploy and run the rsvp example application.

ProcedureTo Run the rsvp Example Application in NetBeans IDE

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to:


    tut-install/examples/jaxrs/
    
  3. Select the rsvp folder.

  4. Select the Open as Main Project check box.

  5. Click Open Project.

  6. Right-click the rsvp project in the left pane and select Run.

    The project will be compiled, assembled, and deployed to GlassFish Server. A web browser window will open to http://localhost:8080/rsvp.

  7. In the web browser window, click the Event Status link for the Duke’s Birthday event.

    You’ll see the current invitees and their responses.

  8. Click on the name of one of the invitees, select a response, and click Submit response; then click Back to event page.

    The invitee’s new status should now be displayed in the table of invitees and their response statuses.

ProcedureTo Run the rsvp Example Application Using Ant

Before You Begin

You must have started the Java DB database before running rsvp.

  1. In a terminal window, go to:


    tut-install/examples/jaxrs/rsvp
    
  2. Type the following command:


    ant all
    

    This command builds, assembles, and deploys rsvp to GlassFish Server.

  3. Open a web browser window to http://localhost:8080/rsvp.

  4. In the web browser window, click the Event Status link for the Duke’s Birthday event.

    You’ll see the current invitees and their responses.

  5. Click on the name of one of the invitees, select a response, and click Submit response, then click Back to event page.

    The invitee’s new status should now be displayed in the table of invitees and their response statuses.

Real-World Examples

Most blog sites use RESTful web services. These sites involve downloading XML files, in RSS or Atom format, that contain lists of links to other resources. Other web sites and web applications that use REST-like developer interfaces to data include Twitter and Amazon S3 (Simple Storage Service). With Amazon S3, buckets and objects can be created, listed, and retrieved using either a REST-style HTTP interface or a SOAP interface. The examples that ship with Jersey include a storage service example with a RESTful interface. The tutorial at http://netbeans.org/kb/docs/websvc/twitter-swing.html uses NetBeans IDE to create a simple, graphical, REST-based client that displays Twitter public timeline messages and lets you view and update your Twitter status.

Further Information about JAX-RS

For more information about RESTful web services and JAX-RS, see