RESTful Resources - Java EE and HTML5 Enterprise Application Developmentb (2014)

Java EE and HTML5 Enterprise Application Developmentb (2014)

CHAPTER

3

RESTful Resources

REST, or Representational State Transfer, is an architectural style for distributed systems such as the World Wide Web. This term was originally introduced and defined in 2000 by Roy Fielding in his dissertation Architectural Styles and the Design of Network-based Software Architectures. Fielding’s motivation for choosing the dissertation topic was his “desire to understand and evaluate the architectural design of network-based application software through principled use of architectural constraints, thereby obtaining the functional, performance, and social properties desired of an architecture.” See www.ics.uci.edu/~fielding/pubs/dissertation/introduction.htm. This was achieved by defining a framework to understand the software architecture of network-based applications. The thesis then describes how REST is used to guide the design and development of the architecture for the modern Web.

Modern applications typically publish their APIs using REST architecture. For example, Twitter’s REST API is published at https://dev.twitter.com/docs/api. Integrating any Twitter functionality, such as searching for tweets with a particular hashtag or obtaining a collection of the most recent tweets, can be accomplished by invoking the Twitter REST API and processing the result in your application.

This chapter explains the key REST principles and how REST services can be published and invoked from Java.

REST Principles

The World Wide Web is the largest implementation of a system conforming to the REST architectural style. In that context, REST is a set of principles that defines how web standards, such as HTTP and URIs, are supposed to be used for building your applications. To successfully build Java EE applications that utilize web standards, you’ll need to understand the guiding principles of REST architecture. These principles will guide you as you define resources and set up services.

The guiding principles of REST architecture are

image Resource The key information in this architecture is a resource. Any information that can be named can be a resource: a document or image, a book, an author, a collection of other resources, and so on.

image Client and server A client-server model is used where a client initiates a request to the server; the server processes the request and returns an appropriate response to the client. Requests and responses are built around the transfer of resources.

image Identification of resources Every resource can be uniquely identified on the client and server. Everything on the Web can be identified as a resource, and each resource can be uniquely identified by a URI.

image Resources are available in multiple representations A resource can be represented in multiple formats, defined by a media type. The client and server can negotiate on the content type of the resource.

image Standard methods can be used to manipulate these resources Each resource can be created, read, updated, and deleted using standard methods. HTTP defines verbs such as GET, PUT, POST, and DELETE to manipulate resources on the Web.

image Communicate statelessly The server does not retain any communication state for any of the clients beyond a single request. If state is required, then it should be kept on the client or converted into resource state. This allows the server to scale much better.

You will see how each of these principles is used with the Java API for REST as you continue in this chapter, and with the JavaScript API for REST in Chapter 5.

Java API for RESTful Web Services

Java API for RESTful Web Services (JAX-RS) defines a standard, annotation-driven API that helps developers develop and invoke a RESTful web service in Java. JAX-RS 1.1 was first included in the Java EE 6 platform. Java EE 7 includes JAX-RS 2.0, which is a deep revision of JAX-RS that adds several features that can handle the most modern style of web applications.

Let’s consider a REST resource that provides create, read, update, and delete operations on an author database. Such a REST resource can be invoked using any of the standard HTTP verbs such as POST, GET, PUT, or DELETE. The endpoint should have the capability to publish and consume resource representations in multiple formats. A complete list of authors or a specific author should be accessible. A REST endpoint that publishes and consumes multiple representations of the author resource using common HTTP verbs is shown in Listing 3-1.

image

Listing 3-1 Author REST Resource

image

image

The following information will help you to understand this code:

image A POJO can be converted to a REST resource by adding @javax.ws.rs.Path annotation to the class. The annotation defines the URI where the resource is accessible—authors in this case. Paths are relative. For an annotated class, the base URI is defined using@javax.ws.rs.ApplicationPath annotation on a class that extends the javax.ws.rs.core.Application class. The complete URI of the resource is defined as:

image

So if the resource is packaged in a WAR file with the context root “sahara” and deployed on the host “localhost” and the port “8080” with the base URI “webresources,” then the complete path of the resource would be

image

image A subresource of the main resource can be defined by annotating a method of the root resource with @javax.ws.rs.Path annotation. The base URI of this subresource is the effective URI of the containing class. The annotated method is invoked whenever the resource is accessed using the complete path defined by the base URI and the path specified on the method. In Listing 3-1, the count() method is called if the resource is accessed at the webresources/authors/count path. Note that the count() method is also annotated with @javax.ws.rs.GET annotation, but it is available at a different path because it is defined as a subresource.

The @javax.ws.rs.Path annotation can take a URI template parameter. The value passed to this template parameter can be bound to a resource method parameter using @javax.ws.rs.PathParam annotation. In Listing 3-1, the find() method is called if the resource is accessed at thewebresources/authors/nnn path, where nnn is some value. The id() method parameter is populated with the value nnn and invokes the find() method on the EJB.

image In addition, although not shown in Listing 3-1, cookies can be bound to a parameter using @javax.ws.rs.CookieParam annotation, HTTP headers can be bound to a parameter using @javax.ws.rs.HeaderParam annotation, a matrix parameter can be bound to a method parameter using@javax.ws.rs.MatrixParam annotation, and parameters coming through an HTML form can be bound to a method parameter using @javax.ws.rs.FormParam annotation.

image Validation constraints, although not shown in Listing 3-1, can be specified on the method parameters to ensure that only valid values are accepted for method parameters. A javax.constraint.ConstraintViolation exception is thrown if the incoming values do not meet the criteria (for example, an alphabetic value is sent when only a numeric value is expected). This can be easily specified using any of the @javax.validation.constraints.Min, @javax.validation.constraints.Max, @javax.validation.constraints.Digits, or similar annotations on the method parameter. The specification even defines an extensible mechanism by which custom constraints meeting application needs can be easily defined.

image Any Java EE component can be injected into the resource using Dependency Injection. An Enterprise JavaBean, AuthorSessionBean, is injected in Listing 3-1 to ensure that all the business logic is defined in the bean. This ensures that any code related to retrieving, adding, or updating from the database is automatically done within a transaction and stays within the EJB. This is important as the runtime container starts and commits or rolls back the transaction to ensure the ACID properties of the underlying database are preserved automatically. Otherwise, the application will have to manually create a transaction and manage it by itself.

image Java EE 7 introduces @javax.transaction. Transactional annotation, although not shown in Listing 3-1, allows all methods within a bean or any method in the bean to be selectively transactional. This is implemented as a CDI interceptor binding and allows the application developer a choice of using EJB or a POJO for container-managed transactions.

image Different HTTP verbs such as GET, PUT, POST, and DELETE are identified by the corresponding annotations in the javax.ws.rs package.

image The findAll() method is called when the resource is accessed using HTTP GET. The path of the resource or subresource is defined as explained earlier. The media type generated by a method is described using @javax.ws.rs.Produces annotation. A method can support one or more media types, and the client requesting the resource can ask for a specific media type using the standard HTTP Accept header. The return value from the method is converted to the appropriate media type and sent on the wire to the client. If this annotation is not specified, then the container assumes that any type can be produced. It is recommended to specify the return media type to ensure that the client and endpoint are aware of the contract.

image JAX-RS provides the javax.ws.rs.core.MediaType class, which provides strongly typed fields for commonly used media types. For example, MediaType.APPLICATION_JSON_TYPE can be used instead of application/json. However, some developers prefer the literal to be specified in their endpoint because it improves the readability of the code.

image If a resource is represented using multiple media types and the client has not indicated any preference, then the endpoint can indicate a media preference using the qs attribute (short for “quality of service”). qs is a floating-point number with a value in the range of 0.000 through 1.000 and indicates the relative quality of a representation compared to the others available, independent of the client’s capabilities. A representation with a qs value of 0.000 will never be chosen. A representation with no qs parameter value is given a qs factor of 1.0. In Listing 3-1, if a client requests the resource with the */* media type or no preferred representation, then JSON representation of the resource is returned because that has a higher priority (qs=1) than the only other media type listed, XML (qs=0.75). However, if the client explicitly asks for the application/xmlmedia type, then an XML representation is returned instead.

image By default, standard media types such as application/xml and application/json are supported. Providing entity providers that know how to read/write media types from the stream can support application-specific media types.

image The @javax.ws.rs.Consumes annotation is used to define the media type that can be consumed by a method. A method can consume multiple media types, and the actual media type is identified using the HTTP Content-Type header. If this annotation is not specified, then the container assumes that any type can be consumed.

image A resource can be updated by annotating a method with @javax.ws.rs.PUT annotation. Similarly, a resource can be deleted by annotating a method with @javax.ws.rs.DELETE annotation.

Out of the box, NetBeans IDE provides many wizards to help you get started developing web services, many of which are shown in Figure 3-1.

image

image

image

FIGURE 3-1. New File dialog showing web service wizards

For example, RESTful web services can be generated directly from your database. Figure 3-2 shows one step in this process. No entity classes need be present in your application because the wizard will create those from your database, too.

image

image

image

FIGURE 3-2. RESTful Web Services from Database

JAX-RS Client API

Prior to the release of JAX-RS 2.0, invoking a REST resource required writing boilerplate code using java.net.URL and a related set of classes. Marshaling and unmarshaling Java objects to resource representations had to be done manually. Any errors received from the endpoint had to be again manually mapped to more meaningful exceptions on the client side. JAX-RS 2.0 introduces a Client API that can be used to invoke a REST resource from a Java application. This API can be used to consume any web service exposed on top of an HTTP protocol or its extension (e.g., WebDAV) and is not restricted to services implemented using JAX-RS.

Let’s see how a REST endpoint can be invoked using this API (Listing 3-2).

image

Listing 3-2 JAX-RS Client API Usage

image

image

The following list explains this code:

image The javax.ws.rs.client.ClientBuilder is the entry point to the fluent JAX-RS Client API. A new javax.ws.rs.client.Client instance can be created by calling the newClient() method. This instance is then used to build and execute client requests in order to consume responses returned. It is recommended to create only a required number of Client instances in the application, as the initialization and disposal of a Client instance may be a rather expensive operation.

image The web resource URI is passed to the target() method and builds a javax.ws.rs.client.WebTarget instance. A builder-style API is used to build a request to the targeted web resource. The request() method starts building the request. Optionally, the media types acceptable in the response can be specified as a method parameter. These types can also be specified as parameters to request().accept() method. Once the request is prepared, it can be invoked using the intuitive get(), put(), post(), and delete() methods. The response can be automatically converted to a Java type by specifying the type as a method parameter. In this case, the response is returned as an array of Author.

Out of the box, NetBeans IDE provides a New RESTful Java Client wizard to let you quickly and easily create a Java web service client for an existing RESTful web service. Figure 3-3 shows the final step in this wizard.

image

image

image

FIGURE 3-3. New RESTful Java Client wizard

After you select the location of the web service and click Finish, the IDE will create the Java client for you. Alternatively, you can create an HTML/JavaScript/CSS front end for your RESTful web service via the RESTful JavaScript Client wizard, as shown in Figure 3-4.

image

image

image

FIGURE 3-4. New RESTful JavaScript Client wizard

In a standard HTTP request-response scenario, a JavaScript client or a Java client using the JAX-RS Client API opens a connection to the resource endpoint, sends an HTTP request to the server (for example, an HTTP GET request), and then receives an HTTP response back; the server closes the connection once the response is fully sent/received. The client always initiates the request and “pulls” the information from the server as required. Sometimes there may be a need for a server to asynchronously “push” information to the client. For example, a stock ticker endpoint can push the updated stock price to the client. In our example, information about a new book can be pushed to the client.

Server-Sent Events

Typically, a client initiates a request to the server and receives a response. Server-Sent Events (SSE) is a mechanism that allows the server to asynchronously push the data from the server to the client whenever a new “chunk” of data is available. The client is still responsible for establishing the connection with the server. When new data is ready to be sent on the server, the server sends the data event to the client, hence the name, Server-Sent Events.

A server-sent event is generated on the server side with a predefined media type of text/event-stream. There is no restriction for a media type used in individual event messages. On the client side, the standard EventSource JavaScript API is used to open an HTTP connection for receiving push notifications from the server. These events are received in callback handlers registered in the client JavaScript and are used to update the client.

Note that SSE will be a final specification along with the rest of HTML5. This is targeted to be final in late 2014. Until then, SSE cannot be added as a standard API to JAX-RS. However, the JAX-RS reference implementation, Jersey, has added support for SSE. This chapter will use Jersey to implement that functionality in our application and explain SSE.

Let’s say you have a Book resource to represent the books written by an author. This resource can be described following the design pattern used for the Author resource. Now let’s say you update the Book resource endpoint such that it generates a server-sent event whenever a new book is added.

First of all, you need to enable support for SSE for the JAX-RS application. As this is not part of the standard JAX-RS API, you need to update the pom.xml file to include the SSE media type module, as shown in Listing 3-3.

image

Listing 3-3 Jersey SSE Media Dependency

image

image

Next, you need to register org.glassfish.jersey.media.sse.SseFeature in the Application class, as shown in Listing 3-4.

image

Listing 3-4 Adding SseFeature to JAX-RS

image

image

The getClasses() method returns a set of root resources, feature, and feature classes. Adding SseFeature, in addition to other resources, to the set of classes returned from this method takes care of registering the feature.

Then, you need to add or update methods that push SSE to the client, as shown in Listing 3-5.

image

Listing 3-5 Updating SSE Methods

image

image

Listing 3-5 shows only the updated methods. The following list explains this code:

image Generating SSE on the server side is a two-step process. First, clients that want to listen to SSE send a GET request to this resource at /books/events, which is handled by the getEvents() method. Second, the method creates a new EventOutput instance representing a connection to the requesting client and registers it with the broadcaster using the add(eventOutput) method. EventOutput allows the underlying connection to remain open so that the application can push SSE later.

image @Produces on this method ensures that the media type of the returned type is text/event-stream.

image SseBroadcaster provides a convenient way of grouping multiple EventOutput instances and broadcasting new events to all the client connections grouped in the broadcaster.

image SseFeature adds support for a new entity Java type, namely OutboundEvent. This entity can be used to create any server outbound events. SseFeature also adds support for InboundEvent, which can be used for inbound client events for the JAX-RS Client API.

image The create() method is updated to broadcast a message to all the clients listening on their SSE connections. A new SSE outbound event is built in the standard way and passed to the broadcaster by calling the broadcast message. The broadcaster internally invokes write(OutboundEvent)on all registered EventOutput instances. As mentioned earlier, there is no restriction on the media type for individual event messages. This application is sending a plain text message as a server-sent event.

image Individual EventOutput instances can be stored in a collection and iterated over in the create() method. However, SseBroadcaster also internally identifies and handles client disconnects. When a client closes the connection, the broadcaster detects this and removes the stale connection from the internal collection of the registered EventOutput instances. The broadcaster also frees all the serverside resources associated with the stale connection. Additionally, SseBroadcaster is implemented to be thread-safe so that clients can connect and disconnect at any time;SseBroadcaster will always broadcast messages only to the most recent collection of registered and active set of clients.

In addition to addressing many other HTML5 client-specific topics, Chapter 5 will show you how SSE is consumed on the client side.

Summary

You started this chapter by learning about the origins of REST and what the guiding principles are for a RESTful architecture. You then learned from the Java EE perspective how a RESTful resource can be developed, deployed, and invoked using the standard Java API for RESTful Web Services (JAX-RS). Design patterns for integrating other Java EE technologies with your RESTful resources were discussed. Finally, you were introduced to how support for Server-Sent Events can be easily incorporated using the JAX-RS reference implementation, Jersey. You were also shown throughout the chapter how NetBeans IDE can speed the creation and implementation of these Java EE features. In the next chapter, you will be shown how to work with an exciting new area of HTML5 called WebSocket.

image