Jersey Spring Integration CRUD Example

In this guide, we demonstrate the integration of Jersey Framework with Spring Framework by developing CRUD rest API example.

1. Overview

Jersey provides an extension to support Spring DI. If you want to use Jersey Spring DI support you will need to add the jersey-spring4 module into the list of your dependencies:
<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-spring4</artifactId>
    <version>2.27</version>
</dependency>
Let's implement the Jersey Spring Integration CRUD Example step by step.

Technology and tools used

  • Spring Framework 4.3.5 Release
  • Maven 3
  • JDK 8
  • Jersey 2.27
  • Apache Tomcat 8.5
  • Eclipse Neon

2. 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-spring-integration
 -DarchetypeArtifactId=maven-archetype-webapp 
 -DinteractiveMode=false

3. Project Packaging Structure

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

4. Update Jersey and Spring 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-spring-integration</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>jersey-spring-integration 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.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.5.RELEASE</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-spring4</artifactId>
            <version>${jersey.version}</version>
        </dependency>

    </dependencies>
  
  <properties>
  <jersey.version>2.27</jersey.version>
  <junit.version>4.12</junit.version>
 </properties>
 
  <build>
    <finalName>jersey-spring-integration</finalName>
  </build>
</project>

5. Data Model - User

User class is a data model for this RESTful CRUD services. We use 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;
 }
}

6. Jersey Resource Registration using ResourceConfig

package com.javadevelopersguide.jersey.config;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;

import com.javadevelopersguide.jersey.resources.CustomExceptionMapper;
import com.javadevelopersguide.jersey.resources.JerseyResource;
import com.javadevelopersguide.jersey.resources.SpringRequestResource;
import com.javadevelopersguide.jersey.resources.SpringSingletonResource;
import com.javadevelopersguide.jersey.resources.UserResource;

public class MyApplication extends ResourceConfig {
 /**
     * Register JAX-RS application components.
     */
    public MyApplication() {
        register(RequestContextFilter.class);
        register(JerseyResource.class);
        register(SpringSingletonResource.class);
        register(SpringRequestResource.class);
        register(CustomExceptionMapper.class);
        register(UserResource.class);
    }
}

7. Create Services - UserService.java and UserServiceImpl.java

In order to demonstrate jersey and spring integration, let's create a UserService interface and it's implementation UserServiceImpl class. Autowire or inject UserService interface in UserResourceclass and use it.

package com.javadevelopersguide.jersey.services;

import java.util.List;

import javax.ws.rs.NotFoundException;

import com.javadevelopersguide.jersey.model.User;

public interface UserService {

    List<User> fetchAll();

    User fetchBy(long id) throws NotFoundException;

    void create(User user);

    void update(User user);

    void delete(long id) throws NotFoundException;

}
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 UserServiceImpl implements UserService {

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

 @Override
 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;
 }

 @Override
 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;
 }

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

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

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

8. 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", "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();
 }
}

9. Create a Spring configuration file - applicationContext.xml

Let's create Spring XML-based configuration file applicationContext.xml to register and configure beans.
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="greetingService" class="com.javadevelopersguide.jersey.services.GreetingServiceImpl"/>

    <bean class="com.javadevelopersguide.jersey.services.DateTimeService" scope="request"/>

    <bean class="com.javadevelopersguide.jersey.resources.SpringSingletonResource"/>

    <bean class="com.javadevelopersguide.jersey.resources.SpringRequestResource" scope="request"/>

    <bean class="com.javadevelopersguide.jersey.resources.CustomExceptionMapper"/>

</beans>

10. Update web.xml (deployment descriptor)

Let's configure jersey servlet container and spring configurations in web.xml.
Add spring configurations to web.xml. Example:
     <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
The complete web.xml file looks:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <module-name>SpringApplication</module-name>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>SpringApplication</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.javadevelopersguide.jersey.config.MyApplication</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringApplication</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

11. Deployment

It is a 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":"demo@gmail.com","id":100,"name":"A"},{"email":"demo1@gmail.com","id":101,"name":"B"},{"email":"demo2@gmail.com","id":102,"name":"C"}]

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"}

Create a new user

Http Method : POST
http://localhost:8080/jersey-spring-integration/users
Request JSON : {"email":"demod@gmail.com","id":106,"name":"D"}
Response : 201

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

Delete User

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

12. Conclusion

This guide illustrated how to the integration of Jersey Framework with Spring Framework by developing CRUD rest API.

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.

Comments