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 RESTFul API's.

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
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 Guide

In this guide, we have used the 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 a 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 (*Unix 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
Or You can use Guide to Create a Simple Maven Web Application
guide to creating a maven web project in eclipse.

2. Project Packaging Structure

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

── 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

Let's create a User class, which is a 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 a Resource class - UserResource.java

Let's create a resource class named UserResource class with following RESTFul APIs:
- Create User
- Get All User
- Update User
- Delete User
- Get User By Id
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", "[email protected]")).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() {
        packages("com.javadevelopersguide.jersey.resources");
    }
}

7. Create Sample UserService class

Let's create a 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", "[email protected]"));
        users.add(new User(101, "B", "[email protected]"));
        users.add(new User(102, "C", "[email protected]"));
        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 {
      // TODO: delete operation
    }
}

8. Jersey JAX-RS Client for Rest API

Jersey Test Framework originated as an internal tool used for verifying the correct implementation of server-side components. 
If you want to develop a test using Jersey Test Framework, you need to subclass JerseyTest and configure the set of resources and/or providers that will be deployed as part of the test application.
The below short code snippet shows basic resource class UserResource used in tests defined as part of the UserResourceTest class. The overridden configure method returns a ResourceConfig of the test application, that contains only the UserResource resource class. ResourceConfig is a sub-class of JAX-RS Application. It is a Jersey convenience class for configuring JAX-RS applications. ResourceConfig also implements JAX-RS Configurable interface to make the application configuration more flexible. 
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

Development is completed, it's time to deploy this web application, so either it can be deployed from an external Tomcat server or run from eclipse.

Rest endpoint URLs, request and response details for your reference.

To fetch all the users.

Http Method : GET
http://localhost:8080/jersey-spring-integration/users
Response JSON :
[{"email":"[email protected]","id":100,"name":"A"},{"email":"[email protected]","id":101,"name":"B"},{"email":"[email protected]","id":102,"name":"C"}]

Get specific user by id

Http Method : GET
http://localhost:8080/jersey-spring-integration/users/user/100
Response : {"email":"[email protected]","id":100,"name":"me"}

Create a new user

Http Method : POST
http://localhost:8080/jersey-spring-integration/users
Request JSON : {"email":"[email protected]","id":106,"name":"D"}
Response : 201

Update a user

Http Method : PUT
http://localhost:8080/jersey-spring-integration/users/user/100
Request JSON : {"email":"[email protected]","id":100,"name":"D"}
Response : 200

Delete a user

Http Method : DELETE
http://localhost:8080/jersey-spring-integration/users/user/100
Response : 204

10. Conclusion

This article illustrated how to implement a Jersey Client for JAX-RS Restful CRUD Web Services using the latest jersey rest 2.27jersey client and ResourceConfig @ApplicationPath annotation based configuration.

In the next article 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 Restful CRUD Web Services Example

Comments