Building Jersey 2.x RESTful Web services in Servlet 3 container with Maven

Monday June 20, 2016 ()
Building Jersey 2.x RESTful Web services in Servlet 3 container with Maven

This is our implementation of Jersey 2.23.1 RESTful web services running on Tomcat 8's Servlet 3.1. It is our practice to write a blog as way to document a new feature available in our servers. We use NetBeans 8.1 for our IDE.

In NetBeans 8.x enabling Maven to build a project is simply selecting Maven as the project Type which generates automatically the POM.xml containing build configuration details. You just need to update them with your dependencies. Here is our POM.xml updated with our artifacts. Shown here contains artifacts that may not all be used in this demonstration, they are used in our actual project.

<dependencies>        
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>         
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>     
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.23.1</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>2.23.1</version>
    </dependency> 
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.14</version>
    </dependency>
    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.9.2</version>
    </dependency>      
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jdbc</artifactId>
        <version>8.0.27</version>
	<scope>provided</scope>
    </dependency>
</dependencies>

In servlet 3.x we have an option to register Jersey 2 application using @ApplicationPath annotation (or use web.xml). We used below ResourceConfig to register Jersey and components, no entry into the web.xml is required. ResourceConfig is Jersey's own implementaton of its Application class used mainly for declaring resources. Note that this implementation is GET only.

package com.kahimyang.rest;

import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.jackson.JacksonFeature;

@ApplicationPath ("/ws")
public class WebService extends ResourceConfig {
    public WebService() {
        // register(JacksonFeature.class);
        packages(this.getClass().getPackage().getName());
    }
}

The resources we return to clients are HTML and XML documents. A description of the resources provided by the web services can be accessed through Jersey's WADL (Web Application Description Language). Use the following URL to describe your web services.

{domain-name}/{app-name}@ApplicationPath/application.wadl

Note that "app-name" is also your application "Context". In our example, the URL would be:

localhost:8080/rest/ws/application.wadl

Here is a sample Jersey's WADL output.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02">
    <doc xmlns:jersey="http://jersey.java.net/" jersey:generatedBy="Jersey: 2.23.1 2016-06-09 18:05:47"/>
    <doc xmlns:jersey="http://jersey.java.net/" jersey:hint="This is simplified WADL with user and core resources only. To get full WADL with extended resources use the query parameter detail. Link: http://localhost:8080/rest/ws/application.wadl?detail=true"/>
    <grammars/>
    <resources base="http://localhost:8080/rest/ws/">
        <resource path="/article">
            <resource path="/html/{id}">
                <param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="id" style="template" type="xs:string"/>
                <method id="getHtml" name="GET">
                    <response>
                        <representation mediaType="text/html"/>
                    </response>
                </method>
            </resource>
            <resource path="/xml/{id}">
                <param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="id" style="template" type="xs:string"/>
                <method id="getXml" name="GET">
                    <response>
                        <representation mediaType="text/xml"/>
                    </response>
                </method>
            </resource>
        </resource>
    </resources>
</application>

The HTML service endpoint. This contains the resources actually available to your users and is described in the WADL mentioned earlier.

package com.kahimyang.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.PathParam;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;


@Path ("/article")
public class ArticleService {
    
    @GET
    @Path("/html/{id}")
    @Produces(MediaType.TEXT_HTML)
    public Response getArticle(@PathParam("id") String id) {
        return HtmlArticle.response(id);
    }

    @GET
    @Path("/xml/{id}")
    @Produces(MediaType.TEXT_XML)
    public Response getXml(@PathParam("id") String id) {
        return XmlArticle.response(id);
    }
}

We access the resource above using the following URL:

{domain-name}/{app-name}@ApplicationPath@Path@GET@Path

For our HTML service, this is:

localhost:8080/rest/ws/article/html/{id}

{id} - any value of an id.

Here is the content of the resource returned by our article HTML resource using Jsoup to build the HTML document from our MySQL database.

package com.kahimyang.rest;

import javax.ws.rs.core.Response;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

public class HtmlArticle {  
    private String id; int id;
    String html;

    private HtmlArticle (String id) {this.id=id;}
  
    public void getRecord () {      
        KahimyangArticle record = new KahimyangArticle (id); 
        status=record.getStatus();                   
        Document doc = Jsoup.parseBodyFragment(record.getBody());   
        Element head = doc.head();
        head.append("<title>").append(record.getBody()).append("</title>");         
        head.append (css.toString());
        html=doc.html();
    }

    public String article() {
        return html;
    }

    public int status() {
        return status;
    }
    
    public static Response response (String id) {
        HtmlArticle article = new HtmlArticle (id);  
        article.getRecord ();    
        return Response.status(article.status()).entity(article.article()).build();
    }
    
}

For the XML service, we use the same mechanism but instead of Jsoup, we used Java's JAXB to build the document.

That's it good luck.


1,073

Comments (Building Jersey 2.x RESTful Web services in Servlet 3 container with Maven)