Java CRUD RESTful Web Services Examples with Jersey and Tomcat
- Details
- Written by Nam Ha Minh
- Last Updated on 05 November 2023   |   Print Email
1. Configure Java Dynamic Web Project for RESTful Web Services with Jersey
Add the following dependencies into your project’s pom.xml file:<dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>2.29.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>2.29.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.29.1</version> </dependency>The first dependency is for Jersey container servlet that processes requests for RESTful webservices. The second one is for an injection library required by Jersey. And the third one is for processing data in JSON format (convert Java objects to JSON and vice-versa). The version 2.29.1 (or newer) works well on JDK 8 or newer (tested with JDK 11).Then open the web.xml file and insert the following code:
<servlet> <servlet-name>Jersey REST Service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>net.codejava.ws</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey REST Service</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping>This is to specify Jersey Container servlet is responsible to handle all requests coming to the web application with URL starts with /rest/ (after the webapp’s context path). We also specify the package net.codejava.ws contains RESTful webservices classes to be exposed to the clients.
2. Code Domain Model Class
package net.codejava.ws; public class Product { private int id; private String name; private float price; public Product(int id) { this.id = id; } public Product() { } public Product(int id, String name, float price) { this.id = id; this.name = name; this.price = price; } // getters and setters are not shown for brevity @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Product other = (Product) obj; if (id != other.id) return false; return true; } }As you can see, in this model class we implement equals()and hashCode() based on product ID so a Product object can be found in an ArrayList as shown below in the DAO class.
3. Code DAO Class
For the shake of simplicity, I don’t use a real database. Instead, I code a DAO class with some mock data so we can focus on the RESTful webservices methods for CRUD operations. Create the ProductDAO class with the following code:package net.codejava.ws; import java.util.ArrayList; import java.util.List; public class ProductDAO { private static ProductDAO instance; private static List<Product> data = new ArrayList<>(); static { data.add(new Product(1, "iPhone X", 999.99f)); data.add(new Product(2, "XBOX 360", 329.50f)); } private ProductDAO() { } public static ProductDAO getInstance() { if (instance == null) { instance = new ProductDAO(); } return instance; } public List<Product> listAll() { return new ArrayList<Product>(data); } public int add(Product product) { int newId = data.size() + 1; product.setId(newId); data.add(product); return newId; } public Product get(int id) { Product productToFind = new Product(id); int index = data.indexOf(productToFind); if (index >= 0) { return data.get(index); } return null; } public boolean delete(int id) { Product productToFind = new Product(id); int index = data.indexOf(productToFind); if (index >= 0) { data.remove(index); return true; } return false; } public boolean update(Product product) { int index = data.indexOf(product); if (index >= 0) { data.set(index, product); return true; } return false; } }As you can see, this DAO class implements CRUD operations to manage products. It will be used by RESTful web services class in the next section below.
Spring Boot REST APIs Ultimate Course
Hands-on REST API Development with Spring Boot: Design, Implement, Document, Secure, Test, Consume RESTful APIs
4. Code CRUD RESTful Web Services Class
Now, let’s code a RESTful webservices class that provides REST API for the clients. Write the initial code as below:package net.codejava.ws; import java.net.*; import java.util.*; import javax.ws.rs.*; import javax.ws.rs.core.*; @Path("/products") public class ProductResource { private ProductDAO dao = ProductDAO.getInstance(); // RESTful API methods go here... }Then write code to implement API method for each operation in the CRUD.\
Code RESTful API method for Retrieval (list all items):
Put the following method in to the ProductResource class:@GET @Produces(MediaType.APPLICATION_JSON) public List<Product> list() { return dao.listAll(); }This method serves HTTP GET request and returns a list of products in JSON format. Type the following command to test with curl:
curl http://localhost:8080/MyWebsite/rest/productsResponse from the server:
[{"id":1,"name":"iPhone X","price":999.99},{"id":2,"name":"XBOX 360","price":329.5}]NOTE: The best practice for this retrieval operation is returning HTTP status code 204 No Content if no data in the response. Hence update the code as below:
@GET @Produces(MediaType.APPLICATION_JSON) public Response list() { List<Product> listProducts = dao.listAll(); if (listProducts.isEmpty()) { return Response.noContent().build(); } return Response.ok(listProducts).build(); }
Code RESTful API method for Retrieval (get a specific item):
Add the following method to the ProductResource class:@GET @Path("{id}") @Produces(MediaType.APPLICATION_JSON) public Response get(@PathParam("id") int id) { Product product = dao.get(id); if (product != null) { return Response.ok(product, MediaType.APPLICATION_JSON).build(); } else { return Response.status(Response.Status.NOT_FOUND).build(); } }This method returns information of a particular product based on a given product ID. If a product is found, it returns the response with HTTP 200 status and includes JSON data of the product. Command to test:
curl http://localhost:8080/MyWebsite/rest/products/2Response from the server:
{"id":2,"name":"XBOX 360","price":329.5}
Code RESTful API method for Create (add a new item):
Put the following code that exposes an API method allowing the client to add a new product:@POST @Consumes(MediaType.APPLICATION_JSON) public Response add(Product product) throws URISyntaxException { int newProductId = dao.add(product); URI uri = new URI("/products/" + newProductId); return Response.created(uri).build(); }As you can see, this method serves HTTP POST request and requires content type of JSON posted from the client. It returns a Response object with HTTP 201 (Created) status and the URI of the newly added item. Run the following command to test (type all in one line):
curl -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"MacBook\",\"price\":1000}" http://localhost:8080/MyWebsite/rest/products/The server’s response includes something like this:
HTTP/1.1 201 Location: http://localhost:8080/products/3 Content-Length: 0
Code RESTful API method for Update (update an existing item):
The following method exposes a RESTful API that allows the client to update a product with a given ID:@PUT @Consumes(MediaType.APPLICATION_JSON) @Path("{id}") public Response update(@PathParam("id") int id, Product product) { product.setId(id); if (dao.update(product)) { return Response.ok().build(); } else { return Response.notModified().build(); } }As you can see, this method requires HTTP PUT method and application/json content type. ID of the product is passed as a path parameter in the request URI. If the product is update successfully, return HTTP 200 (OK) status. Else if the product is not found, return HTTP 304 (Not Modified) status.Run this command to update the product with ID 1:
curl -v -X PUT -H "Content-Type: application/json" -d "{\"name\":\"iPad\",\"price\":888}" http://localhost:8080/MyWebsite/rest/products/1You can see the following information in the server’s response:
HTTP/1.1 200 Content-Length: 0If you try to update a product with non-exist ID, the server will return this response:
HTTP/1.1 304
Code RESTful API method for Delete (remove an item):
And the following method allows the client to delete a product by ID:@DELETE @Path("{id}") public Response delete(@PathParam("id") int id) { if (dao.delete(id)) { return Response.ok().build(); } else { return Response.notModified().build(); } }You see, this method requires HTTP DELETE method with ID of the product as a path parameter in the request URI. If the product is removed successfully, the server returns HTTP 200 (OK) status; else returns HTTP 304 (Not Modified) status.Type the following command to test:
curl -v -X DELETE http://localhost:8080/MyWebsite/rest/products/2This will remove the product with ID 2.NOTE: the best practice for delete operation if successful is returning HTTP status code 204 No Content. So update the code as below:
if (dao.delete(id)) { return Response.noContent().build(); }
5. Code RESTful Web Services Client Program
In this section, I will guide you how to code a client program to consume RESTful web services using Jersey Client API. Create a new client project and add the following dependencies to the pom.xml file:<dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> <version>2.29.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>2.29.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.29.1</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.2</version> </dependency>Write initial code for the client program as follows:
package net.codejava.ws; import javax.ws.rs.client.*; import javax.ws.rs.core.*; import org.glassfish.jersey.client.ClientConfig; public class ProductClientTest { private static String baseURI = "http://localhost:8080/MyWebsite/rest/products"; static WebTarget getWebTarget() { ClientConfig config = new ClientConfig(); Client client = ClientBuilder.newClient(config); return client.target(baseURI); } public static void main(String[] args) { // call a test method: testList(), testAdd(), testGet()... } }To test listing all items, code the following method:
static void testList() { WebTarget target = getWebTarget(); String response = target.request().accept(MediaType.APPLICATION_JSON).get(String.class); System.out.println(response); }Test to get a specific item by ID:
static void testGet() { WebTarget target = getWebTarget(); String productId = "3"; Product product = target.path(productId) .request().accept(MediaType.APPLICATION_JSON) .get(Product.class); System.out.println(product); }Test to add a new item:
static void testAdd() { WebTarget target = getWebTarget(); Product product = new Product("ZenFoneX", 888.88f); Response response = target.request() .post(Entity.entity(product, MediaType.APPLICATION_JSON), Response.class); System.out.println(response.getLocation().toString()); }The following method tests updating an item:
private static void testUpdate() { WebTarget target = getWebTarget(); Product product = new Product("ZenFoneX", 100f); String productId = "4"; Response response = target.path(productId).request() .put(Entity.entity(product, MediaType.APPLICATION_JSON), Response.class); System.out.println(response); }And code the method that tests deleting an item as follows:
private static void testDelete() { WebTarget target = getWebTarget(); String productId = "3"; Response response = target.path(productId).request() .delete(Response.class); System.out.println(response); }That’s how to code a RESTful webservices client program to test CRUD operations.So far you have learned how to code a RESTful webservices application with CRUD (Create, Retrieve, Update and Delete) operations. I hope you found this tutorial helpful. And for your reference, you can download the sample project in the attachments section below. You can also get code from GitHub here.You can also watch the video version below: What's Next? I recommend you follow this one: Spring Boot Hello World RESTful Web Services Tutorial
Recommended Course:
Other Java Web Services Tutorial:
- Java RESTful Web Services Tutorial for Beginner with Jersey and Tomcat
- Java Client Server XML Web Services (JAX-WS) Tutorial
- Java Web Services Tutorial using Apache Axis2, Ant and Tomcat
- How to code and deploy Java XML Web Services (JAX-WS) on Tomcat
- Monitoring SOAP Messages using TCP/IP Monitor in Eclipse
- Using MTOM to optimize binary data transfer with JAX-WS web services
- Java Web Services Binary Data Transfer Example (base64 encoding)
Spring-based Web Services and REST API Tutorials:
- Spring Boot Hello World RESTful Web Services Tutorial
- Spring Boot RESTful CRUD API Examples with MySQL database
- Spring Boot File Download and Upload REST API Examples
- Spring Boot REST API CRUD with HATEOAS Tutorial
Comments