Java API for RESTful web services

In Java EE, the Java API for RESTful web services (JAX-RS) is used to both define and access REST services. JAX-RS is widely used in the Java ecosystem, even by other enterprise technologies. Developers especially like the declarative development model that makes it easy to develop REST services in a productive way.

So-called JAX-RS resources specify REST resources which will be available under a certain URL. The JAX-RS resources are methods in a resource class that implement the business logic once the URL is accessed with a specific HTTP method. The following shows an example of a JAX-RS resource class for users:

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

@Path("users")
@Produces(MediaType.APPLICATION_JSON)
public class UsersResource {

    @Inject
    UserStore userStore;

    @GET
    public List<User> getUsers() {
        return userStore.getUsers();
    }
}

The getUsers() method is the JAX-RS resource method that will be invoked by the container once the HTTP call GET .../users is performed by a client. The list of users is then returned to the client in the JSON format, that is, as a JSON array containing JSON objects for each of the users. That is specified via the @Produces annotation that will here implicitly use the Java API for JSON Binding (JSON-B) to map Java types to their corresponding JSON representation.

Here you can see the inversion of control principle at work. We don't have to wire up or register the URL ourselves, the declaration using the @Path annotation is sufficient. The same is true for mapping Java types into representations such as JSON. We specify in a declarative way which representation formats we want to provide. The rest is handled by the container. The JAX-RS implementation also takes care of the required HTTP communication. By returning an object, here the list of users, JAX-RS implicitly assumes the HTTP status code 200 OK, which is returned to the client together with our JSON representation.

In order to register JAX-RS resources to the container, the application can ship a sub-class of Application which bootstraps the JAX-RS runtime. Annotating this class with @ApplicationPath automatically registers the provided path as Servlet. The following shows a JAX-RS configuration class which is sufficient for the vast majority of use cases:

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("resources")
public class JAXRSConfiguration extends Application {
    // no configuration required
}

JAX-RS, as well as the other standards in the Java EE umbrella, make use of the convention over configuration principle. The default behavior of this REST resource is plausibly sufficient for most of the use cases. If not, then the default behavior can always be overridden with custom logic. This is the reason why JAX-RS, among others, provides a productive programming model. The default cases are realizable very quickly with the option to enhance further.

Let's look at a more comprehensive example. Assuming we want to create a new user in the system that is provided by a client using our REST service. Following HTTP semantics, that action would be a POST request to the user's resource, since we are creating a new resource that may not be identified yet. The difference between the POST and the PUT method is that the latter is omnipotent, only changing the accessed resource with the provided representation, whereas POST will create new resources in the form of new URLs. This is the case here. We are creating a new user that will be identifiable with a new, generated URL. If the resource for the new user is created, the client should be directed toward that URL. For creating resources, this is typically realized with the 201 Created status code, which indicates that a new resource has been created successfully, and the Location header, which contains the URL where the resource will be found.

In order to fulfill that requirement, we have to provide more information in our JAX-RS resource. The following demonstrates how this is accomplished in the createUser() method:

import javax.ws.rs.Consumes;
import javax.ws.rs.PathParam;
import javax.ws.rs.POST;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

@Path("users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class UsersResource {

    @Inject
    UserStore userStore;

    @Context
    UriInfo uriInfo;

    @GET
    public List<User> getUsers() {
        return userStore.getUsers();
    }

    @GET
    @Path("{id}")
    public User getUser(@PathParam("id") long id) {
        return userStore.getUser(id);
    }

    @POST
    public Response createUser(User user) {
        long id = userStore.create(user);

        URI userUri = uriInfo.getBaseUriBuilder()
                .path(UsersResource.class)
                .path(UsersResource.class, "getUser")
                .build(id);

        return Response.created(userUri).build();
    }

}

We make use of the UriInfo feature included in JAX-RS, so that we don't need to repeat ourselves when constructing the new URL. That feature uses the path information which is already present in the annotations of our resource class. The Response method is used to specify the actual HTTP response using a builder pattern approach. JAX-RS notices that the return type of our method is now a response specification and will respond to the client appropriately. By this approach, we have full control and flexibility as to what the response to the client looks like.

As you can see, these methods are the entry point to our business use cases. We inject the UserStore boundary which in our case is implemented as EJB, providing the logic to return the list of users and creating new users, respectively.

JAX-RS provides a productive and straightforward way to expose business functionality with RESTful web services. Developers don't have to write any low-level HTTP plumbing if the default behavior is sufficient.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.179.35