Posted by
bleonard on August 16, 2007 at 3:37 PM PDT
Since I've been studying the Rails framework, I've had an interest in integration with Java. Yes, JRuby is one possible solution, but if you have some large Java system that you want to integrate with, it' unlikely that you're just going to get the jar files to access that system's APIs. More likely is that system will expose itself as a service, and the service type du jour is REST.
So, in this entry I'm going to expose an entity class as a RESTful web service and then create a Rails client for that entity.
Setting Things Up
- Download and install NetBeans 6.0 M10. Grab the Full distribution so you can get the Java IDE, Ruby and GlassFish.
- Download and install the SWDP to GlassFish. This is required to create the RESTful web service.
Creating the RESTful Web Service
Here we'll expose the manufacturer table as a RESTful web service.
Create the Manufacturer Entity Class
- Start NetBeans 6.0 and create a new Web Application named Manufacturers.
- Right-click the project and select Entity Classes from Database.
- Select jdbc/sample as the Data Source and MANUFACTURER as the Table (your list of available tables will be different then mine, but you should have MANUFACTURER):
- Click Next and set the package to model.
- Click the Create Persistence Unit button and then Create on the Create Persistence Unit dialog:

- Click Finish to generate the Manufacturer entity class.
Create the REST Web Service from the Entity Class
- Right-click the project and select REST Web Services from Entity Classes
- Select the Manufacturer Entity Class and click Next.
- Set the package to rest and click Finish.
Test the REST Services
- Right-click the project and choose Test REST Services.
- This will deploy the Manufacturers application to GlassFish and launch a Test REST Services tool:
This tool is very handy for working with the RESTful interface.
The Completed Project
Manufacturers.zip
Creating the Rails REST Client
If you know REST then you know that its operations are basically the HTTP methods: POST, GET, UPDATE and DELETE, which correspond nicely to SQL's Create, Read, Update and Delete. I will implement each one in turn.
GET the Manufacturers
Create the Project
Create a new Ruby on Rails Application named manufacturer_client.
Create a Model to Represent the Manufacturer
The Manufacturer entity contains a bunch of fields. For the purposes of this tutorial, we're only going to work with a handful of them: name, email and phone.
- Since we're not using ActiveRecord, we're not going to run the model generator. Instead, right-click the Models folder and select New > Ruby Class.
- Name the class Manufacturer.
- Add the following code:
require 'open-uri'
class Manufacturer
BASE_URI = 'http://localhost:8080/Manufacturers/restbean/manufacturers/'
attr_accessor :manufacturerId, :name, :email, :phone
def initialize(id, name=nil, email=nil, phone=nil)
@manufacturerId, @name, @email, @phone = id, name, email, phone
end
def uri
BASE_URI + manufacturerId
end
def get
doc = REXML::Document.new(open(uri).read)
@name = REXML::XPath.first(doc, "//name").text
@email = REXML::XPath.first(doc, "//email").text
@phone = REXML::XPath.first(doc, "//phone").text
end
end
Generate a Controller and View to Display the Manufacturers
- Right-click the project and choose Generate. Select Controller and set the Name to Manufacturer and the Views to index list.
- Redirect the index to the list:
def index
list
render :action => 'list'
end
- Define list as follows:
def list
@manufacturers = []
doc = REXML::Document.new(open(Manufacturer::BASE_URI).read)
REXML::XPath.each(doc, "//manufacturerId/") do |entry|
id = entry.text
@manufacturers << Manufacturer.new(id)
end
@manufacturers.each do | manufacturer |
manufacturer.get
end
return @manufacturers
end
Code the View the Display the Manufacturers
- Open list.rhtml and replace its contents with the following:
<h1>Manufacturer List</h1>
<table>
<tr>
<th>Manufacturer Name</th>
<th>Phone</th>
</tr>
<% for manufacturer in @manufacturers %>
<tr>
<td><a href="mailto:<%= manufacturer.email%>"><%= manufacturer.name %></a></td>
<td><%= manufacturer.phone %></td>
</tr>
<% end %>
</table>
Test
- Test F6 to run the project and hit: http://localhost:3000/manufacturer:

Getting the rest-open-uri Gem
Before we can continue, the open-uri library we're using above only supports HTTP GET. Fortunately for us, Leonard Richardson has extended the library (rest-open-uri) to accept the additional HTTP methods.
- Open the Gem Manager: Tools > Ruby Gems
- Select the New Gems tab and enter rest-open-uri in the Search field:
- Install the rest-open-uri gem:
- Restart your server. This is necessary for the new library to be picked up.
POST new Manufacturers
- Add the following link to the bottom of list.rhtml:
<p>
<%= link_to 'New Manufacturer', :action => 'new' %>
- Right-click the Views > manufacturer folder and create a new rhtml file named _form. We'll use this partial for both the new and edit pages. Populate it with the following:
<p>Name<br/>
<%= text_field 'manufacturer', 'name' %></p>
<p>E-Mail<br/>
<%= text_field 'manufacturer', 'email' %></p>
<p>Phone<br/>
<%= text_field 'manufacturer', 'phone' %></p>
- Right-click the Views > manufacturer folder and create a new rhtml file named new. Populate it with the following:
<h1>New Manufacturer</h1>
<% form_tag :action => :create do %>
<p>Manufacturer ID<br/>
<%= text_field 'manufacturer', 'manufacturerId' %></p>
<%= render :partial => 'form' %>
<%= submit_tag "Create" %>
<% end %>
<%= link_to 'Back', :action => 'list' %>
- Switch to the ManufacturerController and add the following create action:
def create
values = params[:manufacturer]
@manufacturer = Manufacturer.new(values[:manufacturerId], values[:name], values[:email], values[:phone])
if @manufacturer.post
redirect_to :action => 'list'
else
render :action => 'new'
end
end
- Switch to the Manufacturer model and add the post method and and a couple of helper methods:
def post
value = get_as_xml
args = prepare_args(:post, value)
result = open(BASE_URI, args)
puts 'HTTP Status: '
puts result.status
return true if result.status[0] = 201
end
private
def get_as_xml
result = "<manufacturer>"
instance_variables.each do | var| var.sub!('@', '')
puts send(var)
result += "<#{var}>" + send(var) + "</#{var}>"
end
result += "</manufacturer>"
end
def prepare_args(http_method, body)
args = {:method => http_method}
args["Content-Type"] = "application/xml"
args["Content-Length"] = body.size.to_s
args[:body] = body
return args
end
- Test:: http://localhost:3000/manufacturer/new
PUT Updates Back
- Open list.rhtml and add the following column to the end of the table:
<td><%= link_to 'Edit', :action => 'edit', :id => manufacturer.manufacturerId %></td>
- Right-click the Views > manufacturer folder and create a new rhtml file named edit. Populate it with the following:
<h1>Editing Manufacturer</h1>
<% form_tag :action => "update", :id => @manufacturer.manufacturerId do %>
<%= hidden_field 'manufacturer', 'manufacturerId' %></p>
<%= render :partial => 'form' %>
<%= submit_tag 'Edit' %>
<% end %>
<%= link_to 'Back', :action => 'list' %>
- Switch to the ManufacturerController and add the following edit and update actions:
def edit
@manufacturer = Manufacturer.new(params[:id])
@manufacturer.get
end
def update
values = params[:manufacturer]
@manufacturer = Manufacturer.new(values[:manufacturerId], values[:name], values[:email], values[:phone])
@manufacturer.update
redirect_to :action => 'list'
end
- Switch to the Manufacturer and add the update method:
def update
doc = REXML::Document.new(open(uri).read)
manufacturer = REXML::XPath.first(doc, "//manufacturer/")
manufacturer.elements.each do |element|
case element.name
when 'name'
element.text = @name
when 'email'
element.text = @email
when 'phone'
element.text = @phone
end
end
value = manufacturer.to_s
args = prepare_args(:put, value)
result = open(uri, args)
puts 'HTTP Status: '
puts result.status
end
- Test http://localhost:3000/manufacturer/edit/19985678
DELETE Manufacturers
This is the easiest one :-).
- Open list.rhtml and add the following column to the end of the table:
<td><%= link_to 'Delete', :action => 'delete', :id => manufacturer.manufacturerId %></td>
- Press Ctrl+Shift+A to switch to the ManufacturerController and add the following delete action:
def delete
uri = Manufacturer::BASE_URI + params[:manufacturerId]
result = open(uri, :method => :delete)
puts result.status
redirect_to :action => 'list'
end
- Test: http://localhost:3000/manufacturer/list. Now you can delete all those entries you added above :-).
Summary
And there you have it, full CRUD operations against a RESTful Web Service. Now this application can use a lot of improvements, like basic error handling and validatation. Pagination on the list page would also be nice. All potential topics for a future blog :-).
The Completed Project
Resources