RESTEasy tutorial

RESTEasy is an portable implementation of JAX-RS specification which provides a Java API for RESTful Web Services over the HTTP protocol. The Java API for RESTful web services (JAX-RS) defines a standard annotation-driven API that helps developers to create Web services in Java and invoke it. RESTFul Web services are based on the following set of principles that are different from the SOAP based Web services

  • Addressable resources: which means that everything can be identified as a resource, and each resource is uniquely identified by a URI.
  • The use standard HTTP methods (GET, POST; PUT, DELETE) to interact with the resource.
  • Representation-oriented: you interact with services using representations of that service. A resource referenced by one URI can have different formats, as different platforms need different formats. (e.g. browsers need HTML, JavaScript needs JSON and so on).
  • Communication between the client and the endpoint is stateless. All the associated state required by the server is passed by the client in each invocation.

In this tutorial we will show a step-by-step guide how to create some simple RESTful Web services to be deployed on WildFly using its Resteasy implementation.

Create your first RESTful service.

Create a Maven project named rest-demo, starting with a webapp-javaee7 Maven archetype:

$ mvn -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee7 -DarchetypeRepository=https://nexus.codehaus.org/content/repositories/snapshots -DgroupId=com.mastertheboss -DartifactId=rest-demo -Dversion=1.0 -Dpackage=com.demo -Darchetype.interactive=false --batch-mode --update-
snapshots archetype:generate

Not using Maven ? As an alternative, you can create a new Dynamic Web project with Eclipse, and point to WildFly Runtime, so you will be able to compile and deploy the project

Now include the required dependencies in your pom.xml file:

 <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.wildfly.bom</groupId>
        <artifactId>wildfly-jakartaee8-with-tools</artifactId>
        <version>${version.server.bom}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
      <groupId>org.jboss.spec.javax.ws.rs</groupId>
      <artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>jakarta.enterprise</groupId>
      <artifactId>jakarta.enterprise.cdi-api</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.jboss.spec.javax.xml.bind</groupId>
      <artifactId>jboss-jaxb-api_2.3_spec</artifactId>
      <scope>provided</scope>
    </dependency>
 </dependencies>

Specify the version of the Bom to be used as a Property. For example, if you were to use WildFly 12:

<properties>
	<version.server.bom>20.0.0.Final</version.server.bom>
</properties>

In the first example, we will recall a RESTful Web service which returns a String when a certain path is request with an HTTP GET:

package com.sample;

import javax.ws.rs.*;

@Path("tutorial")
public class HelloWorld
{

    @GET
    @Path("helloworld")
    public String helloworld() {
        return "Hello World!";
    }
}

The @Path annotation at class level is used to specify the base URL of the Web service. Then you can assign a @Path annotation at method level to specify the single action you want to invoke.

Before deploying your application you need a JAX-RS class activator, which is a class extending javax.ws.rs.core.Application and declaring the Path where JAX-RS Services will be availble:

package com.sample.activator;

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

@ApplicationPath("/rest")
public class JaxRsActivator extends Application {

}

In this example, if you need to invoke the helloworld service, you have to use the following URL: http://localhost:8080/rest/rest-demo/tutorial/helloworld (we suppose that the web application is named rest-demo.war)

resteasy restful web services tutorial

This would produce the classic “Hello World” message on your browser. Now let’s add a parameter to our service:

@GET
@Path("helloname/{name}")
public String hello(@PathParam("name") final String name) {
  return "Hello " +name;
}

Now, we have defined the “helloname” service which accepts the {name} parameter. Now the service returns the value which is appended in the URL. Example:
http://localhost:8080/rest/rest-demo/tutorial/helloname/francesco

would return:
Hello Francesco

Returning XML from your RESTEasy services

As required by the specification, RESTEasy JAX-RS includes support for (un)marshalling JAXB annotated classes. RESTEasy provides multiple JAXB Providers.
RESTEasy will select a different provider based on the return type or parameter type used in the resource. A JAXB Provider is selected by RESTEasy when a parameter or return type is an object that is annotated with JAXB annotations (such as @XmlRootEntity or @XmlType).
For example, supposing you were to return an XML containing the Item class:

package com.sample;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Item {
	public Item() { 	}

	public Item(String description, int price) { 
            this.description = description;
            this.price = price;
	}
 
	private String description;
	private int price;

        // Getter- Setter methods

}

Now add this method to your HelloWorld service:

@GET
@Path("item")
@Produces({"application/xml"})
public Item  getItem() {
  Item item = new Item("computer",2500);
 return item;
}

When invoked, the service (http://localhost:8080/rest-demo/rest/tutorial/item)  will return the following XML:

<item>
   <description>computer</description>
   <price>2500</price>
</item>

If you need to return an array of Item, you can simply use:

@GET
@Path("itemArray")
@Produces({"application/xml"})
public Item[]  getItem() {
  Item item[] = new Item[2];
  item[0] = new Item("computer",2500);
  item[1] = new Item("chair",100);

  return item;
}  

using curl to test the above method:

curl -s http://localhost:8080/rest-demo/rest/tutorial/itemArray | xmllint --format -

The following XML will be returned:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<collection>
  <item>
    <description>computer</description>
    <price>2500</price>
  </item>
  <item>
    <description>chair</description>
    <price>100</price>
  </item>
</collection>

If, on the othen hand, you need to use standard Java collections, you can use a java.util.List to return a set of Item objects:

@GET
@Path("itemList")
@Produces(MediaType.APPLICATION_XML)
public List<Item> getCollItems() {
	List list = new ArrayList();
	Item item1 = new Item("computer",2500);
	Item item2 = new Item("chair",100);
	Item item3 = new Item("table",200);

	list.add(item1);
	list.add(item2);
	list.add(item3);

	return list;
}

using curl to return the List of Item objects:

curl -s http://localhost:8080/rest-demo/rest/tutorial/itemList | xmllint --format -

The following XML will be returned:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<collection>
  <item>
    <description>computer</description>
    <price>2500</price>
  </item>
  <item>
    <description>chair</description>
    <price>100</price>
  </item>
  <item>
    <description>table</description>
    <price>200</price>
  </item>
</collection>

Using JSON providers

According to the documentation (http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html/Built_in_JAXB_providers.html)
Resteasy supports different providers to create XML. JSON is particularly useful to return collections. It encloses lists, sets, or arrays of returned JAXB objects within a simple JSON array. For example:

For example, the following method is identical to getCollItems, except that it returns data using JSON provider:

@GET
@Path("itemListJson")
@Produces("application/json")
public List<Item>  getJSONItems() {
        ArrayList list = new ArrayList();
        Item item1 = new Item("computer",2500);
        Item item2 = new Item("chair",100);
        Item item3 = new Item("table",200);

        list.add(item1);
        list.add(item2);
        list.add(item3);

        return list;
}

You can use curl to request the above method:

curl -s http://localhost:8080/rest-demo/rest/tutorial/itemListJson | jq

Here is the expected outcome:

[
  {
    "description": "computer",
    "price": 2500
  },
  {
    "description": "chair",
    "price": 100
  },
  {
    "description": "table",
    "price": 200
  }
]

Source code for this tutorial: https://github.com/fmarchioni/mastertheboss/tree/master/jax-rs/basic

Read the second part of this tutorial concerning RESTEasy web parameters handling

Running an older version of JBoss ?

Some installation steps might be required if you are running an older version of the application server, let’s see them in detail.

JBoss 6/7

If you are going to run RESTEasy with JBoss 6/7 you don’t have to download/install anything. The RESTEasy libraries are already bundled in the application server. Also the application server detects automatically the resources which are exported as Restful services.

All you have to do is inserting the correct web.xml namespaces:

<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

">

</web-app>

Older JBoss releases

If you have got any other JBoss AS release you have to perform a few basic steps for installing RESTEasy:

Step 1# Download Resteasy from the Repository

The first step is to download the latest Resteasy stable release from:
http://sourceforge.net/projects/resteasy/files/Resteasy%20JAX-RS/

Step 2# Add the following libraries to your Web application:

resteasy-libs

Step 3# Define listeners and bootstrap classes:

Add the following web.xml configuration:

<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"

http://java.sun.com/dtd/web-app_2_3.dtd

">
<web-app>
    <display-name>RestEasy sample Web Application</display-name>

    <listener>
        <listener-class>
            org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>Resteasy</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>sample.HelloWorldApplication</param-value>
        </init-param>

    </servlet>

    <servlet-mapping>
        <servlet-name>Resteasy</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

The org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap class is a ServletContextListener that configures an instance of an ResteasyProviderFactory and Registry.

Then, you need to set the parameter javax.ws.rs.core.Application with the singleton class which is used by your application to enlist all JAX-RS root resources and providers. Using JBoss 6-M4 and Higher this is not necessary as it’s performed automatically by the application server when you deploy the .war

Finally you need to specify which url patterns need to be filtered by Resteasy. With the /* url-pattern all resources will be passed to resteasy servlet.

Step 4# Create the Singleton class

Now we need to add a special Singleton class to enlist all JAX-RS resources, as indicated by the javax.ws.rs.Application parameter.

package sample;

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

import sample.HelloWorld;

public class HelloWorldApplication extends Application
{
    private Set<Object> singletons = new HashSet();
    private Set<Class<?>> empty = new HashSet();

    public HelloWorldApplication() {
        // ADD YOUR RESTFUL RESOURCES HERE
        this.singletons.add(new HelloWorld());
    }

    public Set<Class<?>> getClasses()
    {
        return this.empty;
    }

    public Set<Object> getSingletons()
    {
        return this.singletons;
    }
}

This is your Application class which will enlist your RESTful services in the constructor. In our example, we will add the HelloWorld service.

Autoscanning of resources

If you prefer, you can let RESTeasy scan for your resources instead of adding the SingletonBean which installs your JAX-WS resources.  Just add the following configuration in your web.xml:

   <context-param>
      <param-name>resteasy.scan</param-name>
      <param-value>true</param-value>
   </context-param>
   <context-param>
      <param-name>resteasy.servlet.mapping.prefix</param-name>
      <param-value>/</param-value>
   </context-param>