Java RESTful Web Services Tutorial for Beginners

1- Introduction

This document is based on:
  • Eclipse 4.6 (NEON). (ok for 4.5 MARS)

  • Jersey

If you are a beginner of RESTful Web Service, you need to spend 10 minutes on finding out what RESTful Web service is before starting a Java RESTful serivce application.

You can see "What are RESTful web services?" here:

2- What is Jersey?

Jersey is a open-source Java platform supporting you in developing the RESTful Web service application and the Client applications involved. Jersey implements the specifications of JSR 311.
The Jersey implementation provides a library to implement Restful webservices in a Java servlet container.

On the server side Jersey provides a servlet implementation which scans predefined classes to identify RESTful resources. In your web.xml configuration file your register this servlet for your web application.

The Jersey implementation also provides a client library to communicate with a RESTful webservice.
Here is the path structure of resources proposed by Jersey.
In which, com.sun.jersey.spi.container.servlet.ServletContainer is a servlet provided by JERSEY and needs to be declared on web.xml.

3- Create a Maven webapp

In Eclipse select:
  • File/New/Other..
Enter:
  • Group Id: org.o7planning
  • Artifact Id: HelloRESTful

4- Declare maven & web.xml

You need to declare JERSEY, and Servlet libraries in pom.xml:
pom.xml
<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>org.o7planning</groupId>
    <artifactId>HelloRESTful</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>HelloRESTful Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>


        <!-- 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>

        <!-- https://mvnrepository.com/artifact/asm/asm -->
        <dependency>
            <groupId>asm</groupId>
            <artifactId>asm</artifactId>
            <version>3.3.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-bundle -->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-bundle</artifactId>
            <version>1.19.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.json/json -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20160810</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-server -->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.19.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-core -->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
            <version>1.19.2</version>
        </dependency>

    </dependencies>

    <build>
        <finalName>HelloRESTful</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <path>/HelloRESTful</path>
                    <port>8080</port>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>
Declaring RESTful Servlet - com.sun.jersey.spi.container.servlet.ServletContainer - A Servlet provided by Jersey REST API.

You need to declare the package containing your RESTfuls classes to the servlet via the com.sun.jersey.config.property.packages parameter .

(Note need servlet >= 3.0)
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <display-name>Hello RESTful Service</display-name>

    <servlet>
        <servlet-name>jerseyServlet</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>org.o7planning.hellorestful</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>  
    </servlet>
    <servlet-mapping>
        <servlet-name>jerseyServlet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>


</web-app>

5- RESTful Service class

In the next step, you must create your RESTful service class. For example, the  class WeatherRESTfulService below is a web service providing weather forecast information.
WeatherRESTfulService.java
package org.o7planning.hellorestful;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("/weather")
public class WeatherRESTfulService {

   private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

   //
   // http://localhost:8080/contextPath/rest/weather/{location}/{date}
   // Example:
   // http://localhost:8080/contextPath/rest/weather/chicago/2016-09-27
   // http://localhost:8080/contextPath/rest/weather/hanoi/2016-09-27
   //
   @Path("{location}/{date}")
   @GET
   @Produces("application/xml")
   public String getWeather_XML(@PathParam("location") String location,//
            @PathParam("date") String dateStr) {
       Date date = null;
       if (dateStr == null || dateStr.length() == 0) {
           date = new Date();
       } else {
           try {
               date = df.parse(dateStr);
           } catch (ParseException e) {
               date = new Date();
           }
       }
       dateStr = df.format(date);

       String[] weathers = new String[] { "Hot", "Rain", "Cold" };
       int i = new Random().nextInt(3);
       String weather = weathers[i];

       return "<weather>"//
               + "<date>" + dateStr + "</date>"//
               + "<location>" + location + "</location>"//
               + "<info>" + weather + "</info>"//
               + "</weather>";
   }

   //
   // http://localhost:8080/contextPath/rest/weather/{location}
   // Example:
   // http://localhost:8080/contextPath/rest/weather/chicago
   // http://localhost:8080/contextPath/rest/weather/hanoi
   //
   @Path("{location}")
   @GET
   @Produces("application/xml")
   public String getWeather_XML(@PathParam("location") String location) {
       return getWeather_XML(location, null);
   }

   //
   // http://localhost:8080/contextPath/rest/weather/{location}/{date}
   // Example:
   // http://localhost:8080/contextPath/rest/weather/chicago/2016-09-27
   // http://localhost:8080/contextPath/rest/weather/hanoi/2016-09-27
   //
   @Path("{location}/{date}")
   @GET
   @Produces("application/json")
   public String getWeather_JSON(@PathParam("location") String location,//
           @PathParam("date") String dateStr) {
     
       Date date = null;
       if (dateStr == null || dateStr.length() == 0) {
           date = new Date();
       } else {
           try {
               date = df.parse(dateStr);
           } catch (ParseException e) {
               date = new Date();
           }
       }
       dateStr = df.format(date);

       String[] weathers = new String[] { "Hot", "Rain", "Cold" };
       int i = new Random().nextInt(3);
       String weather = weathers[i];

       return "{" //
               + "'date': '" + dateStr + "'," //
               + "'location': '" + location + "'," //
               + "'info': '" + weather + "'" //
               + "}";
   }

   //
   // http://localhost:8080/contextPath/rest/weather/{location}
   // Example:
   // http://localhost:8080/contextPath/rest/weather/chicago
   // http://localhost:8080/contextPath/rest/weather/hanoi
   //
   @Path("{location}")
   @GET
   @Produces("application/json")
   public String getWeather_JSON(@PathParam("location") String location) {
       return getWeather_JSON(location, null);
   }

}

6- Run application

Configure to run the application:

7- Explain RESTful

Let's Copy the URL below and running it on the browser:
When you run URL above, it is the same that you send a request to server:
GET /HelloRESTful/rest/weather/chicago/2016-08-27 HTTP/1.1
Host: localhost:8080
If the Request doesn't specify the type of return data (MINE type), the default data type will be returned by web service.
The requests can specify the type of return data.
GET /HelloRESTful/rest/weather/chicago/2016-08-27 HTTP/1.1
Host: localhost:8080
Accept: application/xml
Or:
GET /HelloRESTful/rest/weather/chicago/2016-08-27 HTTP/1.1
Host: localhost:8080
Accept: application/json
In the above-mentioned example, if Rquest specifies the return type as application/json, you will get a result as below:
To specify the type of data returned, you need to write a Client application to form customized Requests and to send it to Web service. However you can also use AddOns for browser to adjust the Requests before sending to RESTful service.

RESTClient AddOns is such a plugin, you can set up it on Firefox or Chrome. It supports you in testing the RESTful web services in the process of application development.

How does Jersey RESTful work?

contextPath:
REST Path: