Building java projects on runcoderun.com

26 01 2010

RunCodeRun is a hosted Continuous integration environment developed by Relevance. Thanks to the Relevance team and their effort to provide this service free for opensource projects.

I wanted to build rapa on RunCodeRun. I was trying to setup my project on RunCodeRun using instructions in a blog post. It is a very useful blog and easy to follow. But I was having trouble getting code to compile on runcoderun box. Here are the problems and their solutions.

I guess there is no real jdk on runcoderun, so my compile task on ant would not work.

I checked in tools.jar as a part of my project libraries. Then I added it as part of the classpath when invoking ant from rake.

classpath = [File.join(".","lib","ant.jar"), File.join(".","lib","tools.jar"), File.join(".","lib","junit.jar"), File.join(".","lib","ant-junit.jar"), File.join(".","lib","ant-launcher.jar")].join(File::PATH_SEPARATOR)
system "java -cp #{classpath} org.apache.tools.ant.Main -emacs dist"

Even after I fixed that the build would always go green even if there was failure from ant

I guess the exit status returned by rake was always zero irrespective of what ant returned. I changed the rakefile as shown below.

system "java -cp #{classpath} org.apache.tools.ant.Main -emacs dist"
exit $?.exitstatus

This seemed to fix all the issues with the build.

Along with these issues I was also facing an issue with ant-junit task with junit 4. Basically standard distribution of ant does not understand the annotations of junit4 and requires the test class to extend TestCase. I had to checkout the latest source from ant subversion trunk and build it. I am currently using these jars.

Have a look at the project in github.

http://github.com/harikrishnan83/rapa

Continuous integration on.

http://runcoderun.com/harikrishnan83/rapa





Testability Explorer and rapa

5 09 2009

After a hard day at work my mind was in no state to churn out quality code on open source. But really wanted to get something done about rapa. So thought it might be a good idea to integrate some metrics into the build and see what they had to say.

Misko has created this really cool tool called Testability Explorer. It tells you how testable your classes are. But why do we need such a tool?

Rapa was mainly designed and developed the TDD way. There is always more to learn and improve in the code. Certain parts of Rapa became increasingly difficult to develop the TDD way. We also need a tool that can Flag some basic testability issues.

Background

Lets start with some basic testability issues that we all may have faced at some point in time.

A very common issue most people new to TDD and mocks face is the mocks returning mocks. Below is an example.

when(mockMethodProvider.getMethod()).thenReturn(mockMethod);
MethodExecutor executor = new MethodExecutor(mockMethodProvider);
executor.execute();
verify(mockMethod).execute();

In the first line we are setting an expectation on mockMethodProvider to return a mockMethod. The mockMethodProvider is injected into the methodExecutor. Then we call execute on executor. In the last line we are verifying that execute was called on the mockMethod by the executor.

If we look at this code closely we can observe that MethodExecutor is being injected with mockMethodProvider when all it needs is the mockMethod.

It is a simple design issue. You can find this and many more examples of such common issues with testability in Misko’s blog.

Rapa and Testability Explorer

Integrating testability explorer itself into the build is an easy process. I used the instructions in this link.

Below is the report.

Testability Explorer Report for Rapa release 0.8
Testability Explorer Report for Rapa release 0.8

Looks like the code is not too bad. :)





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.








Follow

Get every new post delivered to your Inbox.

Join 239 other followers