Rails to Java via REST
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
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/' # These accessor names match their corresponding element names. This is # important because I use these names to construct the xml to post back # to the service. attr_accessor :manufacturerId, :name, :email, :phone def initialize(id, name=nil, email=nil, phone=nil) @manufacturerId, @name, @email, @phone = id, name, email, phone end # A utility method getting this object's URI. def uri BASE_URI + manufacturerId end # Retrieves the Manufacturer data 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 # Build a list of Manufacturers @manufacturers = [] # Get the manufacturer list URI and read the XML document from it. doc = REXML::Document.new(open(Manufacturer::BASE_URI).read) #For every manufacturer... REXML::XPath.each(doc, "//manufacturerId/") do |entry| id = entry.text # Append to the manufactures list @manufacturers << Manufacturer.new(id) end # Now that the manufacturer objects all have ids, populate them... @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:
# Creates a new Manufacturer def post # Get an XML representation of this model value = get_as_xml # Gather the arguments required for the post args = prepare_args(:post, value) # Do the POST result = open(BASE_URI, args) puts 'HTTP Status: ' puts result.status return true if result.status[0] = 201 end private #Return an XML representation of this model 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) # Set the arguments for the POST 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 # Populate the object 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 # Get the entire existing record. With this web service, if we only # pass in the new values, the other fields will be set to nil doc = REXML::Document.new(open(uri).read) manufacturer = REXML::XPath.first(doc, "//manufacturer/") # Interate through the document, updating the fields this application # exposes 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 # Revert back to an XML string value = manufacturer.to_s # Gather the arguments required for the post args = prepare_args(:put, value) # Do the PUT 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 # Make a DELETE request 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
- Login or register to post comments
- Printer-friendly version
- bleonard's blog
- 4936 reads





