Calling JAX-RS Service Using AJAX Client

At the time of this writing, there is no standard way to generate AJAX client proxy for a JAX-RS RESTful service. You will find yourself writing a lot of code in the client side just to invoke these services. Several JAX-RS implementations provide their own proprietary client code generation solution. In this article, I will discuss how to generate a client if you are using RESTeasy. JBoss AS 7.1 uses RESTeasy by default which is what I used to test my work.

Let’s say that we have a very simple service resource class.

@Path("/svc")
public class MyBean {
  @Path("/value")
  @Produces("text/plain")
  @GET
  public String getValue() {
    return "Some value";
  }
}

First, register the code generation servlet in web.xml.

<listener>
<listener-class>
  org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>RESTEasy JSAPI</servlet-name>
  <servlet-class>org.jboss.resteasy.jsapi.JSAPIServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RESTEasy JSAPI</servlet-name>
  <url-pattern>/rest-api.js</url-pattern>
</servlet-mapping>

This binds the “/rest-api.js” path to the generated JavaScript. You can use any other path if you like.

In your HTML file, import the client side script.

<script type="text/javascript" src="rest-api.js"></script>

Note, “res-api.js” is the path to the JSAPIServlet as registered in web.xml.

The script defines a JavaScript object for every JAX-RS resource class by the same name. In our case, we will get a variable called MyBean. This JavaScript object has a method for each exposed method of the JAX-RS resource class. In our case, the name of the method will be getValue().

Let’s go ahead and code the rest of the HTML file.

<head>
  <script type="text/javascript" src="rest-api.js"></script>
  <script type="text/javascript">
  function doTest() {
    MyBean.getValue({$callback: onResult});
  }
  function onResult(status, xhr, data) {
    console.log("Status is: " + status);
    if (status == 200)
        alert(data);
    else
        console.log("Do error handling");
  }
</script>
</head>
<body>
<button onclick="doTest();">Test</button>
</body>

Basically, MyBean.getValue() method takes a parameter object. At minimum, we need to supply the callback method which is set using the $callback property. The callback method receives three input parameters:

  • The HTTP reply status. Use this to do error handling.
  • The XmlHttpRequest object used to make the AJAX call.
  • The actual reply data. If the response is a JSON document, then system parses it and gives you the JavaScript object. If the response is XML, then you get the Document object. Otherwise, you get the raw response data as is.

For more information, see the official doc on RESTeasy AJAX client programming.

Developing JAX-RS Services With JBoss AS 7

This morning, I tried to write a RESTful service using JBoss AS 7 and JBoss plugins for Eclipse Indigo. The process to setup a dynamic web project for JAX-RS is a little tricky.

First of all, do’t just go ahead and try to add the JAX-RS facet to the dynamic web project. Instead, right click the project and select Add JAX-RS 1.1 Support.

Then, open web.xml, and add these lines:

<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>

<servlet-mapping>
   <servlet-name>javax.ws.rs.core.Application</servlet-name>
   <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

You can use anything else in place of “/rest/*”. Any URI starting with this will be routed to the JAX-RS servlet.

Let’s say that we have a class:

@Path("/mybean")
public class MyBean {
  @Path("/value")
  @Produces("text/plain")
  @GET
  public String getValue() {
     return "Some value";
  }
}

Let’s say that the context root of the web project is “MyWeb”. Now, you can access the getValue() method of the MyBean resource using the URI: /MyWeb/rest/mybean/value.

A Documentation Model for a RESTful API

In this article, I propose a documentation structure for RESTful Web Services.

RESTful Web Services lack any standard for modeling. By that I mean, the URI syntax, HTTP method, response code etc. are all left up to the API designer. Without a clear documentation, developers can be left guessing about exactly how to invoke a service. There is a reason good documentation is considered a key best practice in a RESTful API design.

I have seen pretty messy documentation, some from fairly well known companies. Don’t let that happen to you.

What Needs to be Documented?

There are some factors that are common to all entry points or operations of the service. They need to be documented in one place:

  1. The base URL consisting of the protocol and host name only.
  2. Any details about the authentication scheme.

For each entry point (or operation) supported by the API, document these items.

General:

  1. What does the operation do?
  2. What are the security requirements? Is SSL or authentication required?

For the request:

  1. The HTTP method.
  2. URI syntax. This may contain the base URL for ease of use.
  3. URL parameters if any.
  4. Request body parameters if any.
  5. Supported MIME types (Content-type request header).

For the response:

  1. Meaning of various HTTP reply codes.
  2. Schema of the response body in success situation.
  3. Schema of the response body in error situations.

The URI Syntax

URI is used to uniquely identify a resource or a specific collection of resources. It should be documented using place holder parameters. Example:

/api/v2/products/{productId}

Or,

http://www.example.com/api/v2/products/productId

Name Type Description
productId Integer The ID of the product

URL Parameters

URL parameters are normally used with GET requests only. They provide filtering and sorting criteria. They should be documented using place holder parameters.

/api/v2/products/categories/{categoryId}?sortBy={sortBy}&maxSize={maxSize}

Name Type Description
sortBy String How to sort the results. Possible values: PRICE, ALPHABATIC. Optional. Default is PRICE.
maxSize Integer Maximum number of products returned. Optional. Default is 100.

Request Body Parameters

Request Body Parameters

Request body is normally used with PUT and POST requests. They are listed in a table similar to the URL parameters.

Describing the Response Body Schema

Most APIs use examples to describe the schema. This is not a bad way. For XML response, it may be useful to also attach a schema document.

Example Case Study

Get a Product

URI

http://www.example.com/api/v2/products/productId?lang=lang&currency=currency

Name Type Description
productId Integer The ID of the product

HTTP Method: GET

URL Parameters

Name Type Description
lang String The language code in which the description of the product will be returned. Possible values en, fr and es. Optional. Defaults to browser’s language setting.
currency String Currency in which prices are returned. Possible values USD, CAD and EUR. Optional. Default is USD.

MIME Types

text/xml, application/xml and application/json

HTTP Reply Codes

Code Meaning
200 Success
404 Product not found. Check the ID.
500 Invalid language or currency setting.

Response Body on Success

XML:

<product>
  <id>1001</id>
  <price>172.00<price>
  <currency>USD</currency>
  <image>http://images.example.com/small/1001.png</image&gt;
  <name>Baseball gloves</name>
  <description>…</description>
</product>

JSON:

{
  “id”: 1001,
  “price”: 172.00,
  “currency”: “USD”,
  “image”: “http://images.example.com/small/1001.png&#8221;,
  “description”:”…”
}