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.