Monthly Archives: November 2018

Implementing Basic REST APIs with JAX-RS

This is a guest article promoted by PACKT, the publisher I work with to get my books to the readers.

Learn how to implement basic REST APIs with JAX-RS in this article by Mario-Leander Reimer, a chief technologist for QAware GmbH and a senior Java developer and architect with several years of experience in designing complex and large-scale distributed system architectures.

This article will take a look at how to implement a REST resource using basic JAX-RS annotations. You’ll implement a REST API to get a list of books so that you’ll be able to create new books, get a book by ISBN, update books, and delete a book. The complete code for this book is also available at https://github.com/PacktPublishing/Building-RESTful-Web-Services-with-Java-EE-8.

Conceptual view of this section

You’ll create a basic project skeleton and prepare a simple class called BookResource and use this to implement the CRUD REST API for your books. First, you need to annotate your class using proper annotations. Use the @Path annotation to specify the path for your books API, which is "books" and make a @RequestScoped CDI bean.

Now, to implement your business logic, you can use another CDI bean. So, you need to get it injected into this one. This other CDI bean is called bookshelf, and you’ll use the CDI @Inject annotation to get a reference to your bookshelf. Next, implement a method to get hold of a list of all books.

What you see here is that you have a books() method, which is @GET annotated, and it produces MediaType.APPLICATION_JSON and returns a JAX-RS response. You can see that you construct a response of ok, which is HTTP 200; use bookshelf.findAll() as the body, which is a collection of books and then build the response. The BookResource.java file should look as follows:

@Path("books")
@RequestScoped
public class BookResource {

@Inject
private Bookshelf bookshelf;

@GET
@Produces(MediaType.APPLICATION_JSON)
public Response books() {
return Response.ok(bookshelf.findAll()).build();
}

Next, implement a GET message to get a specific book. To do this, you have a @GET annotated method, but this time you have the @Path annotation with the "/{isbn}" parameter. To get hold of the parameter called isbn, use the @PathParam annotation to pass the value. Use bookshelf to find your book by ISBN and return the book found using the HTTP status code 200 that is, ok:

@GET
@Path("/{isbn}")
public Response get(@PathParam("isbn") String isbn) {
Book book = bookshelf.findByISBN(isbn);
return Response.ok(book).build();
}

In order to create something, it’s a convention to use HTTP POST as a method. You consume the application JSON and expect the JSON structure of a book. You call bookshelf.create with the book parameter and then use UriBuilder to construct the URI for the just-created book; this is also a convention. Return this URI using Response.created, which matches the HTTP status code 201, and call build() to build the final response:

@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response create(Book book) {
if (bookshelf.exists(book.getIsbn())) {
return Response.status(Response.Status.CONFLICT).build();
}

bookshelf.create(book);
URI location = UriBuilder.fromResource(BookResource.class)
.path("/{isbn}")
.resolveTemplate("isbn", book.getIsbn())
.build();
return Response.created(location).build();
}

You can implement the update method for an existing book. Again it’s a convention to use the HTTP method PUT. Update this by putting in a specific location. Use the @Path parameter with a value of "/{isbn}". Give a reference to this isbn here in the update() method parameter, and you have the JSON structure of your book ready. Use bookshelf.update to update the book and in the end, return the status code ok:

@PUT
@Path("/{isbn}")
public Response update(@PathParam("isbn") String isbn, Book book) {
bookshelf.update(isbn, book);
return Response.ok().build();
}

Finally, implement the delete message and use the HTTP method DELETE on the path of an identified ISBN. Using the @PathParam annotation here, call bookshelf.delete() and return ok if everything went well:

@DELETE
@Path("/{isbn}")
public Response delete(@PathParam("isbn") String isbn) {
bookshelf.delete(isbn);
return Response.ok().build();
}

This is the CRUD implementation for your book resource. Use a Docker container and the Payara Server micro edition to run everything. Copy your WAR file to the deployments directory and then you’re up and running:

FROM payara/micro:5-SNAPSHOT

COPY target/library-service.war /opt/payara/deployments

See if everything’s running on your REST client (Postman). First, get a list of books. As you can see here, this works as expected:

If you want to create a new book, issue the POST and create new book request, and you’ll see a status code of OK 200. Get the new book using GET new book; this is the book you just created, as shown in the following screenshot:

Update the book using Update new book, and you’ll get a status code of OK 200. You can get the updated book using GE new bookT. Get the updated title, as shown in the following screenshot:

Finally, you can delete the book. When you get the list of books, your newly created book is not a part of it anymore.

If you found this article interesting, you can explore Building RESTful Web Services with Java EE 8 to learn the fundamentals of Java EE 8 APIs to build effective web services. Building RESTful Web Services with Java EE 8 also guides you in leveraging the power of asynchronous APIs on the server and client side, and you will learn to use server-sent events (SSEs) for push communication.

 

Advertisements