In this tutorial, we will learn how to create a JAX-RS CRUD example with RESTEasy. The Create, Read, Update, and Delete (CRUD) are the four basic functions of persistent storage.

Before getting started, I would like to give you an overview of JAX-RS Java API.

What is JAX-RS?

JAX-RS (Java API for RESTful Web Services) is a set of Java API that provides support in creating REST APIs. And the framework makes good use of JAX-RS annotations to simplify the development and deployment of these APIs.

JAX-RS 2.0 (JSR-339) and JAX-RS 2.1 (JSR-370), are JCP (Java Community Process) specifications that provide a Java API for RESTful Web Services over the HTTP protocol.

Some of the more well known JAX-RS API implementations are RESTEasy and Jersey.

JAX-RS HTTP annotations

JAX-RS has annotations for responding to HTTP requests.

  • @GET – indicates that the annotated method responds to HTTP GET request
  • @POST – indicates that the annotated method responds to an HTTP POST request
  • @DELETE – indicates that the annotated method responds to an HTTP DELETE request
  • @PUT – indicates that the annotated method responds to HTTP PUT request

What is RESTEasy?

RESTEasy is a Java framework for developing RESTful Web Services. It is a fully certified and portable implementation of the JAX-RS 2.0 specification.

RESTEasy provides tighter integration with the JBoss Application Server but we can deploy it on any servlet container like Tomcat, Jetty, etc.

In this tutorial, we use the tomcat server to deploy the RESTEasy web application.

Tools and Technologies used

  • JDK 1.8 or later
  • Maven 3.5+
  • Eclipse IDE
  • JAX-RS 2.0 +
  • RESTEasy – 3.9.3.Final
  • Tomcat 8.5+

Development Steps

  1. Create a Maven Web project in Eclipse IDE
  2. Add Maven Dependencies
  3. Project Structure
  4. Create a User model class
  5. Create a UserService class
  6. Create a UserResource class
  7. Create an Application Class
  8. RESTEasy Client for REST API
  9. Conclusion

1. Create a Maven Web project in Eclipse IDE

Refer below guide to create a web project in eclipse IDE: 

How to Create a Web Project Using Maven in Eclipse

2. Add maven dependencies

Here is the complete Maven pom.xml file. It contains dependencies for RESTEasy, Jackson provider, and RESTEasy client.

<?xml version="1.0" encoding="UTF-8"?>

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.favtuts</groupId>
	<artifactId>resteasy-crud-example-tutorial</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>resteasy-crud-example-tutorial Maven Webapp</name>
	<!-- FIXME change it to the project's website -->
	<url>https://www.tuts.heomi.net</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.7</maven.compiler.source>
		<maven.compiler.target>1.7</maven.compiler.target>
		<resteasy.version>3.9.3.Final</resteasy.version>
	</properties>
	
	<dependencies>
		<!-- Set up RESTEasy -->
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxrs</artifactId>
			<version>${resteasy.version}</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-servlet-initializer</artifactId>
			<version>${resteasy.version}</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jackson-provider</artifactId>
			<version>${resteasy.version}</version>
		</dependency>
		
		<!--  RESTEasy Client Dependency -->
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-client</artifactId>
			<version>${resteasy.version}</version>
		</dependency>
		
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	
	<build>
		<finalName>resteasy-crud-example-tutorial</finalName>
	</build>
</project>

3. Project Structure

Refer below screenshot for project structure and packaging structure:

resteasy-crud-example-tutorial/
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── favtuts
│   │   │           └── resteasy
│   │   │               ├── model
│   │   │               │   └── User.java
│   │   │               ├── resource
│   │   │               │   ├── RestEasyServices.java
│   │   │               │   └── UserResource.java
│   │   │               └── service
│   │   │                   └── UserService.java
│   │   └── webapp
│   │       ├── index.jsp
│   │       └── WEB-INF
│   │           └── web.xml
│   └── test
│       └── java
│           └── com
│               └── favtuts
│                   └── resteasy
│                       └── UserResourceTest.java
└── target

4. Create a User model class

This is a User model class. It contains three attributes: idname, and email.

package com.favtuts.resteasy.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;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", email=" + email + "]";
	}
		
}

5. Create a UserService class

Let’s create UserService which provides in-memory storage for user objects. UserService contains CRUD contract methods. We have methods for finding users, saving a user, updating a use, and deleting a user.

package com.favtuts.resteasy.service;

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

import javax.ws.rs.NotFoundException;

import com.favtuts.resteasy.model.User;

public class UserService {

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

	public List<User> findAll() {
		if (users.size() <= 0) {
			users.add(new User(100L, "Ramesh", "ramesh@gmail.com"));
			users.add(new User(101L, "Tony", "tony@gmail.com"));
			users.add(new User(102L, "Tom", "tom@gmail.com"));
		}
		return users;
	}

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

	public boolean create(User newUser) {
		for (User user : users) {
			if (user.getId().equals(newUser.getId())) {
				return false;
			}
		}
		return users.add(newUser);
	}

	public boolean update(User updateUser) {
		for (User user : users) {
			if (user.getId().equals(updateUser.getId())) {
				users.remove(user);
				users.add(updateUser);
				return true;
			}
		}
		return false;
	}

	public boolean delete(Long id) throws NotFoundException {
		for (User user : users) {
			if (user.getId().equals(id)) {
				users.remove(user);
				return true;
			}
		}
		return false;
	}
}

6. Create UserResource class

Finally, let’s see an actual CRUD API definition here:

package com.favtuts.resteasy.resource;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
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 com.favtuts.resteasy.model.User;
import com.favtuts.resteasy.service.UserService;

/*
 * CRUD Rest APIs for User Resource
 * @author FAVTUTS.COM
 * 
 */
@Path("users")
public class UserResource {

	private UserService userService = new UserService();

	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response getUsers() {

		List<User> users = userService.findAll();

		if (!users.isEmpty()) {
			return Response.ok(users).build();
		} else {
			return Response.status(Response.Status.NOT_FOUND).build();
		}
	}

	@GET
	@Path("/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getUserById(@PathParam("id") Long id) {

		User user = userService.fetchBy(id);

		if (user.getId() != null) {
			return Response.ok(user).build();
		} else {
			return Response.status(Response.Status.NOT_FOUND).build();
		}
	}

	@POST
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_JSON)
	public Response createUser(User user) {
		boolean result = userService.create(user);
		if (result) {
			return Response.ok().status(Response.Status.CREATED).build();
		} else {
			return Response.notModified().build();
		}
	}

	@PUT
	@Path("/{id}")
	@Consumes(MediaType.APPLICATION_JSON)
	public Response updateUser(@PathParam("id") long id, User user) {
		user.setId(id);
		boolean result = userService.update(user);
		// return Response.ok().status(Response.Status.NO_CONTENT).build();
		if (result) {
			return Response.ok().status(Response.Status.NO_CONTENT).build();
		} else {
			return Response.notModified().build();
		}
	}

	@DELETE
	@Path("/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response deleteUser(@PathParam("id") Long id) {
		boolean result = userService.delete(id);
		if (result) {
			return Response.ok().status(Response.Status.NO_CONTENT).build();
		} else {
			return Response.notModified().build();
		}
	}
}

Let’s understand the JAX-RS annotations from the above code:

  • The @Path annotation specifies the URL to which the resource responds.
  • The @GET annotation indicates that the annotated method responds to HTTP GET requests.
  • The @Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client.
  • When creating a new resource, we use @POST annotation.
  • The @Consumes annotation is used to specify which MIME media types of representations a resource can accept, or consume, from the client.

7. Create Application Class

Let’s create an application configuration class. The Application defines the components of a JAX-RS application and supplies additional meta-data. The javax.ws.rs.core.Application class is a standard JAX-RS class that you may implement to provide information on your deployment:

package com.favtuts.resteasy.resource;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/restapi")
public class RestEasyServices extends Application {
	
	private Set<Object> singletons = new HashSet<Object>();
	
	public RestEasyServices() {
		singletons.add(new UserResource());
	}
	
	@Override
	public Set<Object> getSingletons() {
		return singletons;
	}
}

Notice that with the @ApplicationPath annotation, we set the path to RESTful web services.

8. RESTEasy Client for REST API

JAX-RS 2.0 introduces a new client API so that you can make HTTP requests to your remote RESTful web services. It is a ‘fluent’ request building API with really 3 main classes: ClientWebTarget, and Response

The Client interface is a builder of WebTarget instances. 

WebTarget represents a distinct URL or URL template from which you can build more sub-resource WebTargets or invoke requests on.

There are really two ways to create a Client. The standard way or you can use the ResteasyClientBuilder class. The advantage of the latter is that it gives you a few more helper methods to configure your client. Sample code:

            Client client = ClientBuilder.newClient();
            ... or...
            Client client = ClientBuilder.newBuilder().build();
            WebTarget target = client.target("http://foo.com/resource");
            Response response = target.request().get();
            String value = response.readEntity(String.class);
            response.close();  // You should close connections!

            ResteasyClient client = new ResteasyClientBuilder().build();
            ResteasyWebTarget target = client.target("http://foo.com/resource");

To user RESTEasy Client, we need to add a resteasy-client dependency in the pom.xml:

<dependency>
   <groupId>org.jboss.resteasy</groupId>
   <artifactId>resteasy-client</artifactId>
   <version>3.9.3.Final</version>
</dependency>

Let’s create a JUnit test cases to GET, POST, PUT and DELETE Rest web services with RESTEasy:

package com.favtuts.resteasy;

import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

import com.favtuts.resteasy.model.User;

@FixMethodOrder(MethodSorters.NAME_ASCENDING) // force name ordering
public class UserResourceTest {

	private static final String FULL_PATH = "http://localhost:8080/resteasy-crud-example-tutorial/restapi/users";
	
	@Test
	public void test1ListAllUsers() {
		System.out.println("test1ListAllUsers ...");
		final ResteasyClient client = new ResteasyClientBuilder().build();
		final ResteasyWebTarget target = client.target(FULL_PATH);
		String response = target.request().get(String.class);		
		System.out.println(response);
	}
	
	@Test
	public void test2CreateUser() {
		System.out.println("test2CreateUser ...");
		User user = new User(103L, "Amir", "amir@gmail.com");
		final ResteasyClient client = new ResteasyClientBuilder().build();
		final ResteasyWebTarget target = client.target(FULL_PATH);
		Response response = target.request()
				.post(Entity.entity(user, "application/json"));
		System.out.println(response.getStatus());
		response.close();
	}
	
	@Test
	public void test3UpdateUser() {
		System.out.println("test3UpdateUser ...");
		User user = new User();
		user.setName("Ram");
		user.setEmail("ram@gmail.com");
		final ResteasyClient client = new ResteasyClientBuilder().build();
		final ResteasyWebTarget target = client.target(FULL_PATH + "/100");
		Response response = target.request()
				.put(Entity.entity(user, "application/json"));
		System.out.println(response.getStatus());
		response.close();
	}
	
	@Test
	public void test4DeleteUser() {
		System.out.println("test4DeleteUser ...");
		final ResteasyClient client = new ResteasyClientBuilder().build();
		final ResteasyWebTarget target = client.target(FULL_PATH + "/101");
		Response response = target.request()
				.delete();
		System.out.println(response.getStatus());
        response.close();
        
        final ResteasyWebTarget target1 = client.target(FULL_PATH);
        String response1 = target1.request().get(String.class);
        System.out.println(response1);
	}
}

Run above the JUnit test case to test all CRUD REST APIs. Here is the output of JUnit test cases:

9. Test CRUD APIs with Postman or cURL

List all users

curl --location --request GET 'http://localhost:8080/resteasy-crud-example-tutorial/restapi/users'

Create new user

curl --location --request POST 'http://localhost:8080/resteasy-crud-example-tutorial/restapi/users' \
--header 'Content-Type: application/json' \
--data-raw '{
    "id":103,
    "name": "Amir",
    "email": "amir@gmail.com"
}'

Update user info

curl --location --request PUT 'http://localhost:8080/resteasy-crud-example-tutorial/restapi/users/100' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Ram",
    "email": "ram@gmail.com"
}'

Delete the user

curl --location --request DELETE 'http://localhost:8080/resteasy-crud-example-tutorial/restapi/users/101'

Conclusion

In this tutorial, we have created a CRUD RESTFul application with RESTEasy. The application was deployed on Tomcat/JBoss EAP 7.4.

Download Source Code

$ git clone https://github.com/favtuts/java-jax-rs-tutorials.git
$ cd resteasy-crud-example-tutorial

Run web project on JBoss EAP 7.4 or Tomcat
$ mvn test

References

  1. Maven – How to create a Java web application project
  2. How to Create a Web Project Using Maven in Eclipse
  3. Create a Simple Maven Web Application using Command Line
  4. RESTEasy Hello World Example Tutorial
  5. RESTEasy hello world example

Leave a Reply

Your email address will not be published. Required fields are marked *