Channels ▼

Eric Bruno

Dr. Dobb's Bloggers

JAX-RS: Easily Bridge Platforms with Services and JSON

February 03, 2014

JAX-RS is part of Java EE, which makes creating web services in Java a cinch. You can also create Java applications that call web services easily thanks to the javax.ws.rs.client.Client class, also part of JAX-RS. Even better, you can easily handle and convert JSON data as parameters to your web service calls so that you can call Java web services from JavaScript or other platform languages. Let's take a look.

The Library Web Service

Let's say you're implementing the database and related services for your local library. You might want to build the lookup service (where books are searched by title or other criteria) as a web service so that you can build multiple applications in different languages to access them. For instance, your web service can be called by a web application for people using their browser at home, from Objective-C for people using an iOS application, or from Java for people using an Android application, and so on.

With JAX-RS, you can build this service — and others in your library application — in Java with plain-old-Java-objects (POJOs) and some annotations. First, we define a Book object like so:


public class Book {
    String title;
    String author;
    String publisher;
    String revision;
    String description;

    // getters and setters here…
}

Next, we have a basic lookup service that lets you pre-populate the book library with book information, and then search for them:


public class LookupResource {
    static HashMap<String,Book> books = new HashMap<>();

    public Book getBook(String title) {
        // Lookup a book by given title
        System.out.println("Looking up title: " + title);
        return books.get(title);
    }
    
    public void storeBook(Book book) {
        // Make sure we have a valid book
        if ( book == null || book.getTitle() == null ) {
            return;
        }

        System.out.println( "Storing book: " + book.getTitle() );
        books.put(book.getTitle(), book);
    }
}

To web service-enable this class you add the proper annotations and import the javax.ws.rs.* package classes as shown here:


import java.util.HashMap;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@Path("/lookup")
public class LookupResource {
    static HashMap<String,Book> books = new HashMap<>();

    // Process HTTP GET requests to lookup books
    @GET 
    @Produces(MediaType.APPLICATION_JSON)
    public Book getBook(@QueryParam("title") String title) {
        // Lookup a book by given title
        System.out.println("Looking up title: " + title);
        return books.get(title);
    }
    
    // Process HTTP POST requests to store books
    @POST 
    @Consumes(MediaType.APPLICATION_JSON)
    public void storeBook(Book book) {
        // Make sure we have a valid book
        if ( book == null || book.getTitle() == null ) {
            return;
        }

        System.out.println( "Storing book: " + book.getTitle() );
        books.put(book.getTitle(), book);
    }
}

We'll look at these annotations in detail in a moment. For now, we need to create a Java EE application to deploy this service. To do this, create a Java EE project in your favorite IDE, and add the code above as well as an Application class like this:

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

@ApplicationPath("libraryapp")
public class LibraryApp extends Application {
}

Since I created a Java EE project named MyJAXRSProject, the full URL to access my library web service deployed locally is available here.

Annotations

Before we go any further, let's take a step back and look at the annotations in the LookupResource class one at a time. First, the @Path annotation indicates that this service will be accessible through the URL: http://<server>:<port>/<context>/<application>/lookup".

The @GET and @POST annotations are pretty obvious, and the @Produces and @Consumes annotations are used to indicate that only JSON data will be accepted and returned. So far so good, but JSON can be a little messy to deal with in Java. Again, JAX-RS makes this easy as well. Let's explore that now.

JAX-RS Client Application

Using the javax.ws.rs.client.Client and javax.ws.rs.client.ClientBuilder classes, we can gain access to a javax.ws.rs.client.WebTarget — our web service in this case — that we can make calls to and from a Java application. For instance, to access the web service we built above, we would need the following code:


  Client webclient = ClientBuilder.newClient();
  WebTarget target = webclient.target("http://localhost:8080/MyJAXRSProject/libraryapp/lookup");

To store a book in the library database using this service, you need to send JSON data via an HTTP POST. The javax.ws.rs.client.Entity class is used to take a Book object and encode it as JSON data transparently:

  Book book = new Book();
  book.setTitle("...");
  ...
  Entity.entity(book, MediaType.APPLICATION_JSON)

You pass the result of this call as a POST request to the service with this line of code:


  target.request().post( Entity.entity(book, MediaType.APPLICATION_JSON), Book.class);

As a result, JSON will be passed to the web service, where it will be reassembled into a Java object for you, thanks to JAX-RS, and then stored in the HashMap of library books. To look up the book later, you need to make a GET request where the book search criteria (i.e., the title) is passed as a parameter:


  Book book = target.queryParam("title", title)
                      .request(MediaType.APPLICATION_JSON)
                        .get(Book.class);

Although you specified JSON as the data format for your service, JAX-RS allows you to write Java code that deals with POJOs instead. To prove that JSON is indeed used to pass data around, just call the GET method from a browser. In this example, assume I added my book, Java Messaging, to the library previously. Typing the following URL in a browser:

will yield the following JSON result:

{"author":"Eric J. Bruno","description":"As software becomes more
complex, and the Web is leveraged further, the need for messaging
software continues to grow. Virtually all software written today 
requires at least one form of internal, and even external, 
communication. Java Messaging explores the various methods of
intra-process and inter-process messaging for Java software, such 
as JavaBean events, JMS, JAX-RPC, JAXM, SOAP, and Web 
Services. Programmers will learn the basics of these APIs, as well as
how, when, and why to use each one, including how to use them in 
combination, such as combining SOAP with JMS over a WAN. The 
book begins by walking the reader through simple intra-process
communication using JavaBean events. A set of classes is 
constructed that extend JavaBean events beyond one JVM, 
transparently using JMS. The messaging paradigms of JMS are 
explained thoroughly, including in-depth discussions on the theory 
and mechanics of message queues. Design patterns and helper 
classes are also explored, which ultimately combine to form a generic
messaging framework that helps programmers avoid common 
pitfalls. This framework, explained throughout the book, provides for 
the seamless integration of JMS with SOAP Web Services that is 
required to build distributed applications. Starting from the first 
chapter, a comprehensive sample application (an online stock trading
system) is built using the framework and messaging paradigms 
discussed in the book. By the end of the book, programmers will not 
only understand the various messaging paradigms, but they will also 
understand how to architect complex distributed applications that use 
them together — with a framework that provides a running 
start.","publisher":"Cengage Learning","revision":"1","title":"Java 
Messaging"}

JAX-RS not only allowed us to easily turn a set of POJOs into a web service, it also helped us bridge the worlds of JavaScript and mobile technology by transparently handling the JSON details for us.

Happy coding!
-EJB

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video