Welcome to RESTEasy Tutorial. RESTEasy is the JAX-RS implementation provided by JBoss project. We can use RESTEasy to create restful web services. RESTEasy provides tighter integration with the JBoss Application Server but we can deploy it on any servlet container. So today we will learn how to create restful web service using RestEasy framework and deploy in Tomcat servlet container to test it.

RESTEasy Tutorial

Some of the features of RESTEasy framework are:

  • JAX-RS API compliant – so mostly you need to plug it with JAX-RS API coding to create rest web services.
  • Runs on almost any servlet container supporting Java 6 or higher
  • Provides support for writing client programs using JAX-RS 2.0 client API. We will look into test program too.
  • Rich set of providers – XML, JSON, YAML, Multipart, XOP, Atom, etc.
  • OAuth2 and Distributed SSO with JBoss AS7
  • EJB, Seam, Guice, Spring, and Spring MVC integration

RESTEasy Example

Below are the URIs we will be exposing in our RestEasy web service implementation.

URIHTTP MethodDescription
/employee/addPOSTAdd an employee
/employee/getDummyGETreturns a dummy employee object
/employee/{id}/getGETGet the employee with ‘id’ in the URI
/employee/getAllGETGet all employees
/employee/{id}/deleteDELETEDelete employee with ‘id’ in the URI

RESTEasy Example Eclipse Project

First of all create a “Dynamic Web Application” in Eclipse and then convert it to Maven project to get the web project skeleton.

In Eclipse => File => New => Dynamic Web Project. Name it as “resteasy-eclipse-tomcat-tutorial“.

Make sure you set:

  • Target runtime: Apache Tomcat v9.0
  • Dynamic web module version: 4.0

Press Next button:

Press Next Button, remember to check on “Generate web.xml deployment descriptor

Press Finish button to complete creating project

If you don’t see web.xml (deployment descriptor) then

  • Right click on project
  • Select Java EE Tools
  • Click on Generate Deployment Descriptor Stub

This will create web.xml file under /WebContent/WEB-INF/ folder.

Now convert Project to Maven Project so we could add required .jar files as dependencies.

Steps:

  • Right click on project
  • Click on Configure
  • Select option Convert to Maven Project.

The pom.xml is generated with initial content as bellow:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.favtuts</groupId>
  <artifactId>resteasy-eclipse-tomcat-tutorial</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.3</version>
      </plugin>
    </plugins>
  </build>
</project>

RESTEasy maven dependencies

Next step is to add RESTEasy maven dependencies in our pom.xml file as shown below.

<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-jaxrs</artifactId>
	<version>3.0.13.Final</version>
</dependency>
<!-- Below dependency is for JAXB integration -->
<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-jaxb-provider</artifactId>
	<version>3.0.13.Final</version>
</dependency>

After update pom.xml, you should choose the project and right click, select Maven -> Update Project to force update the new dependencies.

RESTEasy Example Model Classes

We have two model classes – Employee for employee object and GenericResponse for sending client response object for status, message and error code.

package com.favtuts.jaxrs.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "employee")
public class Employee {
	private String name;
	private double salary;
	private int id;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return id + "::" + name + "::" + salary;
	}

}
package com.favtuts.jaxrs.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "response")
public class GenericResponse {

	private boolean status;
	private String message;
	private String errorCode;

	public boolean isStatus() {
		return status;
	}

	public void setStatus(boolean status) {
		this.status = status;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(String errorCode) {
		this.errorCode = errorCode;
	}

	@Override
	public String toString() {
		return status + "|" + message + "|" + errorCode;
	}
}

Notice that both the java beans are annotated with @XmlRootElement annotation. This is required for JAXB API for converting objects to xml and vice versa.

RESTEasy Example Service Classes

Let’s first create an interface for all the operations we are trying to expose in our restful web service.

package com.favtuts.jaxrs.service;

import javax.ws.rs.core.Response;

import com.favtuts.jaxrs.model.Employee;

public interface EmployeeService {

	public Response addEmployee(Employee e);
	
	public Response deleteEmployee(int id);
	
	public Employee getEmployee(int id);
	
	public Employee[] getAllEmployees();

}

Below is the implementation class for above employee service interface.

package com.favtuts.jaxrs.service;


import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
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.jaxrs.model.Employee;
import com.favtuts.jaxrs.model.GenericResponse;

@Path("/employee")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public class EmployeeServiceImpl implements EmployeeService {

	private static Map<Integer,Employee> emps = new HashMap<Integer,Employee>();
	
	@Override
	@POST
    @Path("/add")
	public Response addEmployee(Employee e) {
		GenericResponse response = new GenericResponse();
		if(emps.get(e.getId()) != null){
			response.setStatus(false);
			response.setMessage("Employee Already Exists");
			response.setErrorCode("EC-01");
			return Response.status(422).entity(response).build();
		}
		emps.put(e.getId(), e);
		response.setStatus(true);
		response.setMessage("Employee created successfully");
		return Response.ok(response).build();
	}

	@Override
	@DELETE
    @Path("/{id}/delete")
	public Response deleteEmployee(@PathParam("id") int id) {
		GenericResponse response = new GenericResponse();
		if(emps.get(id) == null){
			response.setStatus(false);
			response.setMessage("Employee Doesn't Exists");
			response.setErrorCode("EC-02");
			return Response.status(404).entity(response).build();
		}
		emps.remove(id);
		response.setStatus(true);
		response.setMessage("Employee deleted successfully");
		return Response.ok(response).build();
	}

	@Override
	@GET
	@Path("/{id}/get")
	public Employee getEmployee(@PathParam("id") int id) {
		return emps.get(id);
	}
	
	@GET
	@Path("/{id}/getDummy")
	public Employee getDummyEmployee(@PathParam("id") int id) {
		Employee e = new Employee();
		e.setSalary(8976.55);
		e.setName("Dummy");
		e.setId(id);
		return e;
	}

	@Override
	@GET
	@Path("/getAll")
	public Employee[] getAllEmployees() {
		Set<Integer> ids = emps.keySet();
		Employee[] e = new Employee[ids.size()];
		int i=0;
		for(Integer id : ids){
			e[i] = emps.get(id);
			i++;
		}
		return e;
	}

}

We are using only JAX-RS API annotations such as @Path@PathParamResponse etc. Notice that I am using javax.ws.rs.core.Response as response object in some of the methods where I want to send the HTTP status code other than 200.

RESTEasy Configuration

We haven’t done anything related to RestEasy till now, it’s time now to configure RestEasy as our JAX-RS API implementation for our restful web service.

Next step is to extend javax.ws.rs.core.Application class and override few of the methods to inject our service class implementation.

package com.favtuts.jaxrs.resteasy.app;

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

import javax.ws.rs.core.Application;

import com.favtuts.jaxrs.service.EmployeeServiceImpl;

public class EmployeeApplication extends Application {
	
	private Set<Object> singletons = new HashSet<Object>();

	public EmployeeApplication() {
		singletons.add(new EmployeeServiceImpl());
	}

	@Override
	public Set<Object> getSingletons() {
		return singletons;
	}

}

Final step is to configure RESTEasy servlet class in deployment descriptor as front controller.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>RestEasy-Example</display-name>
  <listener>
  	<listener-class>
  		org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
  	</listener-class>
  </listener>
  <servlet>
  	<servlet-name>resteasy-servlet</servlet-name>
  	<servlet-class>
  		org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
  	</servlet-class>
  	<init-param>
  		<param-name>javax.ws.rs.Application</param-name>
  		<param-value>com.favtuts.jaxrs.resteasy.app.EmployeeApplication</param-value>
  	</init-param>
  </servlet>
  <servlet-mapping>
  	<servlet-name>resteasy-servlet</servlet-name>
  	<url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

That’s it. Our web service is ready. You can see how easy it was to plugin RestEasy as our JAX-RS implementation for restful web service.

RESTEasy Complete project structure

RESTEasy Eclipse Maven clean and build project

Hello.

For people who, like me, are a bit young to Maven/Java/Eclipse/Tomcat etc…
I was missing one step in my configuration: telling Tomcat about the Maven libraries.
This is done as follow:
– right-click on project and choose “Properties”,
– click on “Deployment Assembly”, then click on “Add” button
– select “Java Build Path Entries” and click on “Next” button
– selecting “Maven Dependencies” and clicking on “Finish” button
This, way, all Maven libraries become visible to Tomcat!

Many things for that well-designed tutorial,
Daniel

Now let’s clean eclipse workspace and build project.

1 – Project -> Clean

  • Ref: https://stackoverflow.com/questions/18494722/getting-classnotfoundexception-resteasybootstrap-and-classnotfoundexception

If your project is maven base project then run

mvn eclipse:clean

mvn eclipse:eclipse

it will add jar from m2 repo to lib folder then redeploy webapp and restart tomcat/server

2 – Project -> Right click -> Maven -> Update Project

3 – Project -> Right click -> Run As.. -> Maven Build -> Add “clean install” goals -> Run

You should see build success message.

[INFO] Scanning for projects...
[INFO] 
[INFO] ------------< com.favtuts:resteasy-eclipse-tomcat-tutorial >------------
[INFO] Building resteasy-eclipse-tomcat-tutorial 0.0.1-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ resteasy-eclipse-tomcat-tutorial ---
[INFO] Deleting C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ resteasy-eclipse-tomcat-tutorial ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\src\main\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ resteasy-eclipse-tomcat-tutorial ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\target\classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ resteasy-eclipse-tomcat-tutorial ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\src\test\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ resteasy-eclipse-tomcat-tutorial ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ resteasy-eclipse-tomcat-tutorial ---
[INFO] No tests to run.
[INFO] 
[INFO] --- maven-war-plugin:3.2.3:war (default-war) @ resteasy-eclipse-tomcat-tutorial ---
[INFO] Packaging webapp
[INFO] Assembling webapp [resteasy-eclipse-tomcat-tutorial] in [C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\target\resteasy-eclipse-tomcat-tutorial-0.0.1-SNAPSHOT]
[INFO] Processing war project
[INFO] Copying webapp resources [C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\src\main\webapp]
[INFO] Webapp assembled in [71 msecs]
[INFO] Building war: C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\target\resteasy-eclipse-tomcat-tutorial-0.0.1-SNAPSHOT.war
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ resteasy-eclipse-tomcat-tutorial ---
[INFO] Installing C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\target\resteasy-eclipse-tomcat-tutorial-0.0.1-SNAPSHOT.war to C:\Users\tranvt\.m2\repository\com\favtuts\resteasy-eclipse-tomcat-tutorial\0.0.1-SNAPSHOT\resteasy-eclipse-tomcat-tutorial-0.0.1-SNAPSHOT.war
[INFO] Installing C:\Devspaces\MyProjects\Favtuts.COM\Github\java-jax-rs-tutorials\resteasy-eclipse-tomcat-tutorial\pom.xml to C:\Users\tranvt\.m2\repository\com\favtuts\resteasy-eclipse-tomcat-tutorial\0.0.1-SNAPSHOT\resteasy-eclipse-tomcat-tutorial-0.0.1-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.437 s
[INFO] Finished at: 2022-07-09T00:58:01+07:00
[INFO] ------------------------------------------------------------------------

RESTEasy Eclipse deploy and start on Tomcat

Deploy project resteasy-eclipse-tomcat-tutorial on Tomcat. Here are detailed steps on how to setup Tomcat on Eclipse if you haven’t done so.

  • Go to Server Tab
  • Right click on Server
  • Click on Add and Remove Projects
  • Selection project from left side and click on Add
  • Click finish

Start Tomcat Server 9.0

RESTEasy Restful Web Service Test

I am using Chrome Postman extension to perform testing for our web service. Below are some of the test cases with response.
One common part is the headers in all the requests as shown in below image.

1 – getDummy

2 – add Employee

Need 2 Headers

  • Accept : application/xml
  • Content-Type: application/xml

3 – get

4 – get All

5 – delete

6 – add error – HTTP response 422

7 – delete error – HTTP response 404

As you can see that all the tests passed with flying colors, our rest web service is working fine.

RestEasy Client – ResteasyClient example

As I mentioned earlier, RestEasy also provides API for testing rest web services through java program. For this we need to add another dependency in our pom.xml file.

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

Below is the simple test program where I am testing our web service programmatically. I am providing example for testing GET, POST and DELETE HTTP methods.

package com.favtuts.jaxrs.resteasy.client;

import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
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 com.favtuts.jaxrs.model.Employee;
import com.favtuts.jaxrs.model.GenericResponse;

public class RestEasyTestClient {
	
	public static void main(String[] args) {
		
		ResteasyClient client = new ResteasyClientBuilder().build();
		
		//GET example
		ResteasyWebTarget getDummy = client.target("http://localhost:8080/resteasy-eclipse-tomcat-tutorial/employee/99/getDummy");
		Response getDummyResponse = getDummy.request().get();
		String value = getDummyResponse.readEntity(String.class);
		System.out.println(value);
		getDummyResponse.close();
				
		//POST example
		ResteasyWebTarget add = client.target("http://localhost:8080/resteasy-eclipse-tomcat-tutorial/employee/add");
		Employee emp = new Employee();
		emp.setId(50);
		emp.setName("Rick");
		emp.setSalary(1000);
		Response addResponse = add.request().post(Entity.entity(emp, MediaType.APPLICATION_XML));
		System.out.println(addResponse.readEntity(GenericResponse.class));
		System.out.println("HTTP Response Code:" + addResponse.getStatus());
		addResponse.close();
		
		addResponse = add.request().post(Entity.entity(emp, MediaType.APPLICATION_XML));
		System.out.println(addResponse.readEntity(GenericResponse.class));
		System.out.println("HTTP Response Code:"+addResponse.getStatus());
		addResponse.close();
				
		//DELETE example
		ResteasyWebTarget delete = client.target("http://localhost:8080/resteasy-eclipse-tomcat-tutorial/employee/50/delete");
		Response deleteResponse = delete.request().delete();
		System.out.println(deleteResponse.readEntity(GenericResponse.class));
		System.out.println("HTTP Response Code:"+deleteResponse.getStatus());
		deleteResponse.close();
		
		deleteResponse = delete.request().delete();
		System.out.println(deleteResponse.readEntity(GenericResponse.class));
		System.out.println("HTTP Response Code:"+deleteResponse.getStatus());
		deleteResponse.close();
		
	}
	
}

Below is the output produced by above RESTEasy client program.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><employee><id>99</id><name>Dummy</name><salary>8976.55</salary></employee>
true|Employee created successfully|null
HTTP Response Code:200
false|Employee Already Exists|EC-01
HTTP Response Code:422
true|Employee deleted successfully|null
HTTP Response Code:200
false|Employee Doesn't Exists|EC-02
HTTP Response Code:404

That’s all for RESTEasy tutorial. RESTEasy is a very easy framework for creating Restful web services in java easily. You can download the project from below link and play around with it to learn more.

Download Source Code

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

Leave a Reply

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