Getting started with RESTEasy

The Java API for RESTful web services (JAX-RS) is a Java language specification that simplifies the development and deployment of RESTful web services. RESTEasy is JBoss's implementation of the JAX-RS specification.

In this post, I will walk you through the steps I followed when getting started with the RESTEasy framework.

Prerequisites

  • OpenJDK for Java 1.8
  • Git
  • Maven (I'm using 3.3.9)
  • The Eclipse IDE for Java EE Developers (I'm using Neon)

Note: This post will walk you through the steps required to install the OpenJDK. And, this post will walk you through the steps required to install Git, Maven and the Eclipse IDE.

What is an Archetype?

An archetype is "an original pattern or model from which all other things of the same kind are made". We can use Maven's quickstart archetype to create a template for our project:

mvn archetype:generate \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DarchetypeVersion=1.1 \
  -DgroupId=org.robferguson.resteasy.examples.helloworld \
  -DartifactId=helloworld \
  -DarchetypeRepository=local \
  -DinteractiveMode=false

Note: For line continuation to work the backslash ('\') must be the very last character before the end of line character, if there is a space after the '\', the line continuation will not work.

You should see output like:

[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------
[INFO] Parameter: packageName, Value: helloworld
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] ----------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ----------------------------------------------------------------
[INFO] Total time: 7.316 s
[INFO] Finished at: 2016-11-26T09:49:24+11:00
[INFO] Final Memory: 18M/121M
[INFO] ----------------------------------------------------------------

The Eclispe IDE

Now we can import the template into the Eclispe IDE, select 'File -> Import...':

Select 'Existing Maven Projects', then click the Next button:

Select the project's root directory, click the Finish button, then take a look at the project's structure in the Project Explorer:

Creating a Resource

Now we're ready to create our first resource, lets take a look at a simple example:

...

@Path("/hello")
@Produces(MediaType.TEXT_PLAIN)
public class MessageResource {

  @GET
  @Path("/{param}")
  public Response printMessage(@PathParam("param") String msg) {
    String result = "Hello " + msg + "!";
    return Response.status(200).entity(result).build();
  }
}

JAX-RS relies heavily on annotations to simplify the development of RESTful web services. The @Path annotation specifies the relative path (i.e., "/hello") for a resource class or method. The @GET annotation specifies the HTTP request type and the @PathParam annotation binds the method parameter to a path segment (e.g., "World").

Registering a Resource

We can extend the javax.ws.rs.core.Application class in order to tell RESTEasy which resources we want deployed.

Let’s take a look at a simple example:

...

@ApplicationPath("")
public class HelloWorldApplication extends Application {

  public HelloWorldApplication() {}

  @Override
  public Set<Object> getSingletons() {
	HashSet<Object> set = new HashSet<Object>();
	set.add(new MessageResource());
    return set;
  }
}

The Application class is very straightforward, it lists the classes and objects that JAX-RS is supposed to deploy. It also includes the @ApplicationPath(“”) annotation which defines the relative base URL path (e.g., @ApplicationPath("") -> http://localhost:8080 or @ApplicationPath("api") -> http://localhost:8080/api) for all our JAX-RS services.

The getSingletons() method returns a list of preallocated (i.e., objects that you have created) JAX-RS web services and providers. The RESTEasy runtime will iterate through the list of objects and register them internally. When the objects are registered, RESTEasy will also inject values for @Context annotated fields and setter methods.

Deployment

RESTEasy applications can be deployed to a servlet container like Jetty or Tomcat or to a JEE application server like JBoss Wildfly or IBM Websphere. They can be packaged in a WAR or as a fat JAR.

To deploy a RESTEasy application to a JAX-RS-aware servlet container we only need a very minimal web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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 
             version="3.0">
</web-app>

If you have at least one Application class implementation annotated with @ApplicationPath, a JAX-RS–aware servlet container will deploy your application by using the Servlet 3.0 ServletContainerInitializer Service Provider Interface (SPI).

The POM.XML

The Project Object Model contains everything we need to know about a project (the "who", "what", and "where") including the plugin configurations used during the build process (the "when" and "how").

Note: Maven favours convention over configuration which means it will look for code to compile in the src/main/java directory, for the web.xml file in the src/main/webapp directory, and for tests in the src/test/java directory.

Let’s take a look at the Hello World example's pom.xml:

<groupId>org.robferguson.resteasy.examples.helloworld</groupId>
<artifactId>helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

The first few elements — the groupId, artifactId, version and packaging — are known as the Maven coordinates, and they uniquely identify a project.

<properties>
  ...
  <resteasy.version>3.0.19.Final</resteasy.version>
  <junit.version>4.11</junit.version>
  ...
</properties>

Maven properties are value placeholders, their values are accessible anywhere within a POM using the following notation: ${X} (e.g., ${resteasy.version}).

<dependencies>

  <!-- Runtime dependencies -->
  <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>
    
  <!-- Test scope dependencies -->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
  </dependency>
    
</dependencies>

The dependencies element lists all the library dependencies the project needs to compile and run.

The Hello World example is dependent on RESTEasy (the core library and the ServletContainerInitializer integration library) as this is the JAX-RS implementation we are using. The junit dependency has a scope of test. This means that this library is only used to run tests and is not included in the WAR.

The build element contains configuration information that defines how Maven should build the project:

<build>
    <finalName>helloworld-${project.version}</finalName>

The first item is the finalName element, which is used to name the project's WAR file.

Next we have the plugins element:

    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven-compiler-plugin.version}</version>
            <configuration>
                <source>${source.version}</source>
                <target>${target.version}</target>
            </configuration>
        </plugin>

This section contains information about the Maven plugins that will be used to build the project. The compiler plugin, is configured to compile the project's source code into the Java 8 bytecode format.

The next plugin we need to configure is the surefire-it plugin:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven-surefire-plugin.version}</version>
            <configuration>
                <skip>true</skip>
            </configuration>
            <executions>
                <execution>
                    <id>surefire-it</id>
                    <phase>integration-test</phase>
                    <goals>
                        <goal>test</goal>
                    </goals>
                    <configuration>
                        <skip>false</skip>
                    </configuration>
                </execution>
            </executions>
        </plugin>

The surefire-it plugin controls test execution, here you can see that we have configured the plugin to not run any tests until the WAR file has been built and deployed to Jetty.

The final plug-in is the Jetty plugin:

        <plugin>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>${jetty-maven-plugin.version}</version>
            <configuration>
                <webApp>
                    <contextPath>/</contextPath>
                </webApp>
                <scanIntervalSeconds>10</scanIntervalSeconds>
                <stopKey>alpha</stopKey>
                <stopPort>9099</stopPort>
                <stopWait>2</stopWait>
            </configuration>
            <executions>
                <execution>
                    <id>start-jetty</id>
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <scanIntervalSeconds>0</scanIntervalSeconds>
                        <daemon>true</daemon>
                    </configuration>
                </execution>
                <execution>
                    <id>stop-jetty</id>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>stop</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

The Jetty plugin is responsible for running (and stopping) the embedded Jetty servlet container.

Build and run the example program

The best way to learn about the RESTEasy framework is to build and run example programs. Lets start by cloning my RESTEasy examples repository:

git clone https://github.com/Robinyo/resteasy.git

Then we can build the 'Hello World' example (in the examples/helloworld directory) and run some tests:

mvn clean install

To run Jetty:

mvn jetty:run

You should see output like:

[INFO] --- jetty-maven-plugin:9.0.6.v20130930:run
[INFO] Configuring Jetty for project: helloworld
...
INFO: RESTEASY002225: Deploying javax.ws.rs.core.Application: class
  org.robferguson.resteasy.examples.helloworld.HelloWorldApplication
INFO: RESTEASY002220: Adding singleton resource
  org.robferguson.resteasy.examples.helloworld.resource.MessageResource
 ...
[INFO] Started Jetty Server
[INFO] Starting scanner at interval of 10 seconds.

In your browser navigate to:

http://localhost:8080/hello/World

You should see output like:

To stop Jetty:

mvn jetty:stop
References:
Source Code: