Consume REST webservices in java using rapa

24 01 2009

I have been reading about REST webservices for quite a while now. But rails still seems to have the best support for consuming REST webservices (ActiveResource). It is magical the way active resource works. Even if the magical and dynamic behavior may not be completely possible in java, it would be helpful if we have basic support for accessing REST webservices.

A few options which immediately pop up on a search would be restlet, apache cxf and jersey (reference implementation of jsr 311). But they are not as easy to use as ActiveResource and not very object oriented. The motivation behind rapa is to fill this gap. In this blog I will take you through creating a simple REST webservice with rails and then use rapa to consume it in an object oriented approach.

Rapa uses the tried and tested Jakarta Commons HttpClient and JAXB. It helps you in consuming REST webservice easily by taking care of the grunt work (making connection to the webservice, transporting data etc). All that said, its time for some code.

Prerequisites for this example:

If you are in a hurry, you can download the sample application code here.

If you want to get your hands dirty building the rails rest webservice and the rapa client yourself, below are the steps.
Firstly create the REST webservice in rails (which we will later consume in java).

rail rest --database=mysqlcd rest

ruby script/generate model customer id:number name:string

ruby script scaffold customer

then edit the database.yml file according to your database settings.

rake db:create
rake db:migrate

gentlemen start your server

ruby script/server

now access your rest webservice by pasting the below url in a browser
http://localhost:3000/customers.xml

<customers type="array">
</customers>

Since there is no data yet you will see only so much.
Now let us consume this webservice with rapa.
Download rapa. You will also need the below supporting jars.

Create a project with your favourite ide. Create a POJO class called Customer (or any name your think appropriate). This class has to implement the org.rest.rapa.resource.Resource interface.

/**
 * Purpose: Value object that represents the RestAPI
 */

import org.rest.rapa.resource.Resource;

public class Customer implements Resource {
	private String name;
	private int id;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

}

Instanciate the org.rest.rapa.RestClientWrapper class as shown below.

RestClientWrapper restClientWrapper = new RestClientWrapper(
"http://localhost:3000/customers", "", "", "localhost", 9000);

The first parameter is the base url of the REST webservice. The second and third parameters are the username and password (In this case they are emty because our sample rails application does not require authentication). The fourth parameter is host name and fifth parameter is the port number.

Now we are ready use the webservice to create, read, update and delete with rapa.

Create

Customer customer = new Customer();
customer.setName("Hari");
restClientWrapper.save(customer);

Read

customer = (Customer) restClientWrapper.getById(1, Customer.class);
System.out.println(customer.getName());

Update

customer = new Customer();
customer.setName("rapa");
customer.setId(1);
restClientWrapper.update(customer);

Delete

customer = new Customer();
customer.setId(1);
restClientWrapper.delete(customer);

Rapa throws a checked exception called org.rest.rapa.RestClientException if an operation was not successful.

All the above operations in the example can be verified by looking at the rails log. For example the create method would result in the below log generated by the rails server.

Processing CustomersController#create (for 127.0.0.1 at 2009-01-24 23:20:16) [POST]
Session ID: fda551698b0faca8bed707f7148fe3de
Parameters: {"format"=>"xml", "action"=>"create", "controller"=>"customers", "customer"=>{"name"=>"Hari", "id"=>"0"}}
←[4;36;1mSQL (0.000000)←[0m   ←[0;1mSET NAMES 'utf8'←[0m
←[4;35;1mSQL (0.000000)←[0m   ←[0mSET SQL_AUTO_IS_NULL=0←[0m
←[4;36;1mCustomer Columns (0.031000)←[0m   ←[0;1mSHOW FIELDS FROM `customers`←[0m
←[4;35;1mSQL (0.000000)←[0m   ←[0mBEGIN←[0m
←[4;36;1mCustomer Create (0.000000)←[0m   ←[0;1mINSERT INTO `customers` (`name`, `updated_at`, `created_at`) VALUES('Hari', '2009-01-24 17:50:16', '2009-01-24 17:50:16
')
←[0m
←[4;35;1mSQL (0.031000)←[0m   ←[0mCOMMIT←[0m
Completed in 0.20300 (4 reqs/sec) | Rendering: 0.14100 (69%) | DB: 0.06200 (30%) | 201 Created [http://localhost/customers.xml]

Enjoy consuming REST webservice in java.

This project is still in very initial stages. Please send me your feedback.

Update: Please take a look at the latest improvements at github. The documentation has been updated as well.