Jersey JAX-RS Client for CRUD Restful Web Services

In this guide, we will learn how to create Jersey JAX-RS Client for GET, POST, PUT, DELETE Rest API's.

What will we learn?

  • Overview of Jersey JAX-RS Client
  • Jersey JAX-RS Client for UserResource Rest API
  • Jersey JAX-RS Client for CRUD Restful Web Services

Overview of Jersey JAX-RS Client

The Jersey JAX-RS Client API, which is a fluent Java-based API for communication with RESTful Web services. The JAX-RS client API can be utilized to consume any Web service exposed on top of an HTTP protocol. Follow below standard steps to write Jersey JAX RS Client API
  • Creating and configuring a Client instance
  • Targeting a web resource
  • Identifying resource on WebTarget
  • Invoking an HTTP request
  • Complete Example
Let's write Jersey JAX RS Client for below Rest API's
HTTP GET - Collection/List of Users Example
HTTP GET - Get single User Rest API
HTTP POST - Create User Rest API
HTTP PUT - Update User Rest API
HTTP DELETE - Delete User Rest API

Jersey JAX-RS Client for UserResource Rest API

Let's write Jersey JAX RS Client for below Rest API's
HTTP GET - Collection/List of Users Example
HTTP GET - Get single User Rest API
HTTP POST - Create User Rest API
HTTP PUT - Update User Rest API
HTTP DELETE - Delete User Rest API
package com.javadevelopersguide.jersey.client;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.javadevelopersguide.jersey.model.User;

public class UserResourceClient {

 public static void main(String[] args) {
   //getUsers();
   getUser();
  // createUser();
  // updateUser();
  //deleteUser();
 }

 private static void getUsers() {
  Client client = ClientBuilder.newClient();

  String entity = client.target("http://localhost:8080/jersey-crud-example/api").path("users")
    .request(MediaType.APPLICATION_JSON).header("some-header", "true").get(String.class);

  System.out.println(entity);
 }

 private static void getUser() {
  Client client = ClientBuilder.newClient();

  String entity = client.target("http://localhost:8080/jersey-crud-example/api").path("users").path("user/100")
    .request(MediaType.APPLICATION_JSON).header("some-header", "true").get(String.class);

  System.out.println(entity);
 }
 
 private static void createUser() {
  Client client = ClientBuilder.newClient();
  WebTarget webTarget = client.target("http://localhost:8080/jersey-crud-example/api").path("users");

  User user = new User();
  user.setId(1);
  user.setName("Ramesh");

  Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
  Response response = invocationBuilder.post(Entity.entity(user, MediaType.APPLICATION_JSON));

  System.out.println(response.getStatus());
  System.out.println(response.readEntity(String.class));
 }

 private static void updateUser() {
  Client client = ClientBuilder.newClient();
  WebTarget webTarget = client.target("http://localhost:8080/jersey-crud-example/api").path("users")
    .path("user/1");

  User user = new User();
  user.setId(1);
  user.setName("Ramesh");

  Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
  Response response = invocationBuilder.put(Entity.entity(user, MediaType.APPLICATION_JSON));

  String userJson = response.readEntity(String.class);

  System.out.println(response.getStatus());
  System.out.println(userJson);
 }

 private static void deleteUser() {

  Client client = ClientBuilder.newClient();
  WebTarget webTarget = client.target("http://localhost:8080/jersey-crud-example/api").path("users")
    .path("user/100");

  User user = new User();
  user.setId(1);
  user.setName("Ramesh");

  Invocation.Builder invocationBuilder = webTarget.request();
  Response response = invocationBuilder.delete();

  System.out.println(response.getStatus());
  System.out.println(response.readEntity(String.class));
 }
}
Let's develop step by step complete web application of Jersey JAX-RS Client for CRUD Restful Web Services.

Jersey JAX-RS Client for CRUD Restful Web Services

In this guide, we have used latest technologies to demonstrate CRUD Rest API using Jersey JAX-RS and JAX-RS Client. 
Technology and tools used:
  • Maven 3
  • JDK 8
  • Jersey 2.27
  • Apache Tomcat 8.5
  • Eclipse Neon

1. Create Maven Web Application Project

You can create a quick start Java web application project by using the Maven maven-archetype-webapp template. In a terminal (*uix or Mac) or command prompt (Windows), navigate to the folder you want to create the project.
Type this command :
$ mvn archetype:generate -DgroupId={project-packaging} 
 -DartifactId={project-name} 
 -DarchetypeArtifactId=maven-archetype-webapp 
 -DinteractiveMode=false

//for example 
$ mvn archetype:generate -DgroupId=com.ramesh
 -DartifactId=Jersey-crud-example
 -DarchetypeArtifactId=maven-archetype-webapp 
 -DinteractiveMode=false

2. Project Packaging Structure

In a typical Jersey application, the project packaging structure may look:

Production

  • src/main/java – Java Source code packages and classes
  • src/main/resources – NON-Java Resources, such as property files and configuration files
  • src/main/webapp - deployment descriptor(web.xml), WEB-INF, JSP views under WEB-INF folder, static resources

Test

  • src/test/java – Test Source code packages and classes
  • src/test/resources – NON-Java Resources, such as property files and configuration files

── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── javadevelopersguide
    │   │           └── jersey
    │   │               ├── model
    │   │               │   └── User.java
    │   │               ├── service
    │   │               │   ├── UserService.java
    │   │               │   └── impl
    │   │               │       └── UserServiceImpl.java
    │   │               └── resources
    │   │               |    └── UserResource.java
    │   │               └── client
    │   │                     └── UserResourceClient.java
    │   ├── resources
            └── logback.xml
    │   └── webapp
    │       ├── WEB-INF
    │       │   ├── classes
    │       │   └── web.xml
    │       ├── images
    │       └── styles
    └── test
        ├── java
        │   └── com
        │       └── javadevelopersguide
        │           └── jersey
        │               └── resources
        │                   └── UserResourceTest.java
        └── resources
            └── logback-test.xml

3. Update Jersey Dependencies in a Pom.Xml File

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.javadevelopersguide.jersey</groupId>
 <artifactId>jersey-crud-example</artifactId>
 <packaging>war</packaging>
 <version>0.0.1-SNAPSHOT</version>
 <name>jersey-crud-example Maven Webapp</name>
 <url>http://maven.apache.org</url>

 <dependencies>
  <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
   <scope>provided</scope>
  </dependency>

  <dependency>
   <groupId>org.glassfish.jersey.core</groupId>
   <artifactId>jersey-server</artifactId>
   <version>${jersey.version}</version>
  </dependency>
  <dependency>
   <groupId>org.glassfish.jersey.containers</groupId>
   <artifactId>jersey-container-servlet</artifactId>
   <version>${jersey.version}</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-moxy -->
  <dependency>
   <groupId>org.glassfish.jersey.media</groupId>
   <artifactId>jersey-media-moxy</artifactId>
   <version>${jersey.version}</version>
  </dependency>

  <dependency>
   <groupId>org.glassfish.jersey.inject</groupId>
   <artifactId>jersey-hk2</artifactId>
   <version>${jersey.version}</version>
  </dependency>

  <!-- Required only when you are using JAX-RS Client -->
  <dependency>
   <groupId>org.glassfish.jersey.core</groupId>
   <artifactId>jersey-client</artifactId>
   <version>${jersey.version}</version>
  </dependency>
 </dependencies>

 <build>
  <finalName>jersey-crud-example</finalName>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
     <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
   </plugin>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.0.2</version>
    <configuration>
     <source>1.8</source>
     <target>1.8</target>
    </configuration>
   </plugin>
   <plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
   </plugin>
  </plugins>
 </build>

 <properties>
  <jersey.version>2.26</jersey.version>
 </properties>

</project>

4. Data Model - User

User class is data model for this RESTful CRUD services. 
I have used jersey-moxy- json support for JSON binding feature from jersey-media-moxy.
package com.javadevelopersguide.jersey.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class User {
 private long id;
 private String name;
 private String email;
 
 public User() {
  
 }
 
 
 public User(long id, String name, String email) {
  super();
  this.id = id;
  this.name = name;
  this.email = email;
 }
 public long getId() {
  return id;
 }
 public void setId(long id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
}

5. Create Resource class - UserResource.java

Create GET,POST,PUT,DELETE Rest API's in root UserResource class.
package com.javadevelopersguide.jersey.resources;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import com.javadevelopersguide.jersey.model.User;
import com.javadevelopersguide.jersey.services.UserService;

@Path("/users")
public class UserResource {

 private UserService userService = new UserService();

 @GET
 @Produces(MediaType.APPLICATION_JSON)
 public List<User> fetchAll() {
  return userService.fetchAll();
 }

 @GET
 @Path("user/{id}")
 @Produces(MediaType.APPLICATION_JSON)
 public Response get(@PathParam("id") int id) {
  return Response.ok().entity(new User(100, "me", "me@gmail.com")).build();
 }
 
 @POST
 @Produces(MediaType.APPLICATION_JSON)
 @Consumes(MediaType.APPLICATION_JSON)
 public Response create(User user) {
  // create notification
  userService.create(user);
  return Response.status(Status.CREATED).build();
 }
 
 @PUT
 @Path("/user/{id}")
 @Consumes(MediaType.APPLICATION_JSON)
 public Response update(@PathParam("id") long id, User user) {
  userService.update(user);
  return Response.noContent().build();
 }

 @DELETE
 @Path("/user/{id}")
 public Response delete(@PathParam("id") long id) {
  userService.delete(id);
  return Response.status(202).entity("User deleted successfully !!").build();
 }
}

6. Descriptor-Less Deployment Configuration

Here are multiple deployment options in the Servlet 3.0 container for a JAX-RS application defined by implementing a custom Application subclass. For simple deployments, no web.xml is necessary at all. 

Instead, an @ApplicationPath annotation can be used to annotate the custom Application subclass and define the base application URI for all JAX-RS resources configured in the application:
import javax.ws.rs.ApplicationPath;

// Deployment of a JAX-RS application using @ApplicationPath with Servlet 3.0
// Descriptor-less deployment
import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("/api")
public class JerseyServletContainerConfig extends ResourceConfig {
 public JerseyServletContainerConfig() {
  // if there are more than two packanges then separate them with semicolon
  // exmaple : packages("org.foo.rest;org.bar.rest");
  packages("com.javadevelopersguide.jersey.resources");
 }
}

7. Create Sample UserService class 

Created UserService class to serve in-memory objects to UserResource class.
package com.javadevelopersguide.jersey.services;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.NotFoundException;

import com.javadevelopersguide.jersey.model.User;

public class UserService {

 private List<User> users = new ArrayList<User>();

 public List<User> fetchAll() {

  users.add(new User(100, "A", "demo@gmail.com"));
  users.add(new User(101, "B", "demo1@gmail.com"));
  users.add(new User(102, "C", "demo2@gmail.com"));
  return users;
 }

 public User fetchBy(long id) throws NotFoundException {
  for (User user2 :  fetchAll()) {
   if (id == user2.getId()) {
    return user2;
   }else{
    throw new NotFoundException("Resource not found with Id :: " + id);
   }
  }
  return null;
 }

 public void create(User user) {
  users.add(user);
 }

 public void update(User user) {
  for (User user2 : users) {
   if (user.getId() == user2.getId()) {
    users.remove(user2);
    users.add(user);
   }
  }
 }

 public void delete(long id) throws NotFoundException {
  // delete operation
 }
}

8. Jersey JAX-RS Client for Rest API

package com.javadevelopersguide.jersey.client;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.javadevelopersguide.jersey.model.User;

public class UserResourceClient {

 public static void main(String[] args) {
   //getUsers();
   getUser();
  // createUser();
  // updateUser();
  //deleteUser();
 }

 private static void getUsers() {
  Client client = ClientBuilder.newClient();

  String entity = client.target("http://localhost:8080/jersey-crud-example/api").path("users")
    .request(MediaType.APPLICATION_JSON).header("some-header", "true").get(String.class);

  System.out.println(entity);
 }

 private static void getUser() {
  Client client = ClientBuilder.newClient();

  String entity = client.target("http://localhost:8080/jersey-crud-example/api").path("users").path("user/100")
    .request(MediaType.APPLICATION_JSON).header("some-header", "true").get(String.class);

  System.out.println(entity);
 }
 
 private static void createUser() {
  Client client = ClientBuilder.newClient();
  WebTarget webTarget = client.target("http://localhost:8080/jersey-crud-example/api").path("users");

  User user = new User();
  user.setId(1);
  user.setName("Ramesh");

  Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
  Response response = invocationBuilder.post(Entity.entity(user, MediaType.APPLICATION_JSON));

  System.out.println(response.getStatus());
  System.out.println(response.readEntity(String.class));
 }

 private static void updateUser() {
  Client client = ClientBuilder.newClient();
  WebTarget webTarget = client.target("http://localhost:8080/jersey-crud-example/api").path("users")
    .path("user/1");

  User user = new User();
  user.setId(1);
  user.setName("Ramesh");

  Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
  Response response = invocationBuilder.put(Entity.entity(user, MediaType.APPLICATION_JSON));

  String userJson = response.readEntity(String.class);

  System.out.println(response.getStatus());
  System.out.println(userJson);
 }

 private static void deleteUser() {

  Client client = ClientBuilder.newClient();
  WebTarget webTarget = client.target("http://localhost:8080/jersey-crud-example/api").path("users")
    .path("user/100");

  User user = new User();
  user.setId(1);
  user.setName("Ramesh");

  Invocation.Builder invocationBuilder = webTarget.request();
  Response response = invocationBuilder.delete();

  System.out.println(response.getStatus());
  System.out.println(response.readEntity(String.class));
 }
}

9. Deployment

it is a web application, so either it can be deployed from external tomcat server or run from eclipse.
Rest endpoint URLs, request and response details for your reference.
  1. To fetch all the users.
Http Method : GET
http://localhost:8080/jersey-spring-integration/users
Response JSON :
[{"email":"demo@gmail.com","id":100,"name":"A"},{"email":"demo1@gmail.com","id":101,"name":"B"},{"email":"demo2@gmail.com","id":102,"name":"C"}]
  1. Get specific user by id
Http Method : GET
http://localhost:8080/jersey-spring-integration/users/user/100
Response : {"email":"me@gmail.com","id":100,"name":"me"}
  1. Create new user
Http Method : POST
http://localhost:8080/jersey-spring-integration/users
Request JSON : {"email":"demod@gmail.com","id":106,"name":"D"}
Response : 201
  1. Update user
Http Method : PUT
http://localhost:8080/jersey-spring-integration/users/user/100
Request JSON : {"email":"demod@gmail.com","id":100,"name":"D"}
Response : 200
  1. Delete User
Http Method : DELETE
http://localhost:8080/jersey-spring-integration/users/user/100
Response : 204

10. Conclusion

This guide illustrated how to implement a Jersey JAX-RS Restful CRUD Web Services Example using latest jersey rest 2.27jersey client and ResourceConfig @ApplicationPath annotation based configuration.
In the next guide of the series, we will focus on more Jersey rest examples, concepts, and more.
All the code of this article is available over on Github. This is a Maven-based project, so it should be easy to import and run as it is.

Github Repository: Jersey JAX-RS Client for CRUD Restful Web Services

Comments