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.

Advertisements

Pushing Existing Repository to GitHub

Let’s say that you have a local Git repo that you have been using to manage your code for a while. Now, you wish to publish it to  GitHub so others can look at it and participate in development. How will you do that?

Well, the key to pushing to any remote repo for the first time is to make sure that the remote repo is completely empty. Normally, you will use “git init –bare” to create a bare/empty repo on the remote server. In GitHub, you use the web GUI to create a repo. There, make sure that you do not choose Initialize this repository with a README checkbox. This will create a bare repo in GitHub.

After the repo is created in GitHub, run these commands from your local Git repository. Let’s say that the URL for the newly created GitHub repo is “https://github.com/bobby/MyRepo.git&#8221;.

git remote add MyGitHub https://github.com/bobby/MyRepo.git
git push MyGitHub master

Then, enter your GitHub user ID and password.

So, the trick is not to create the README file when you create the repository in GitHub. Otherwise, the repository will not be bare and when you try to do a push, you will get an error message “Updates were rejected because the tip of your current branch is behind”.