As part of the “MySpyder” project I am currently working on we want a Flex front-end to access a RESTFul Ruby on Rails service. You can read more on RESTFul and ActiveResource on
David’s blog, on the
“release notes” of Rails 1.2, PeepCode as an excellent
screencast (not free) on the subject, and many other places.
In short using the RESTFul approach allows to expose and manipulate a Rails model via a predefined set of standard Http requests. For example we have an ActiveRecord named Watch which can be manipulated via the following requests:
| command |
url |
| index |
# GET /watches.xml |
| show |
# GET /watches/1.xml |
| new |
# GET /watches/new |
| create |
# POST /watches.xml |
| update |
# PUT /watches/1.xml |
| delete |
# DELETE /watches/1.xml |
This allows for standard
CRUD operations. Note rest supports also custom operations and
CRUD operations on nested resources (such as a has_many relationship). We won’t address them in the article, but I will certainly need them later in the project.
The Rails application can determined what format to return based on the content type or the extension of the url. We are only interested in xml for the moment.
Some of the advantages of a RESTFul Rails application are that it provides a standard way to organize your controllers, as you will see just in a moment because the controllers are standard most of the code can easily be generated, and because the
URL to access the application are standard we can now provide some standard utility class to access a RESTFul server. Rails provides an ActiveResource client class, and I haven’t found one yet for Flex. So I started to write one which I will show here after. Now please contact me or add some comments to this blog if you find anything similar or if you want to help me out writing this class. Another cool feature of writing RESTFul Rails controllers is that you get an
API for your application nearly for free. This is the main reason we went down that direction.
Assuming we have an ActiveRecord named Watch we can now generate a RESTFul Ruby on Rails controller issuing the following command
./script/generate scaffold_resource watch
Our server now supports RESTFul http requests.
Now wouldn’t it be nice if we could access the server data from Flex in the following manner:
import mx.rpc.AsyncToken;
import org.onrails.ActiveResourceClient;
var watches:ActiveResourceClient = new ActiveResourceClient();
watches.defineResource("http://localhost:3000", "watches", resultHandler, faultHandler);
// Note that all the calls are performed in parallel and asynchronously.
watches.list()
watches.show(8)
// create
var data:XML = <watch>
<url>www.picnik.com</url>
<xpath></xpath>
<frequency>10080</frequency>
</watch>
watches.create(data)
// update
data = <watch>
<id>8</id>
<frequency>10080</frequency>
</watch>
data.frequency = 1440;
watches.update(data)
// delete
watches.deleteItem(8)
Now we can. I started to write the ActiveResourceClient actionscript class to allow this. It’s attached at the end of the article. Now, this is a first try I’ve created this morning. So please be critical and let’s improve it together, or even better if you have one or know one that’s way better please point me where I can get it.
To use the ActiveResourceClient just put the ActiveResourceClient.mxml file into the org.onrails folder in your Flex project. Note that you can provide a default result handler and fault handler or set one handler for each specific call, i.e. the watches.create returns an AsyncToken where a dedicated handler can be specified just to handle the result of the creation.
Download:
ActiveResourceClient.mxml (renamed file to ActiveResourceClient.mxml)
Enjoy,
Daniel Wanja.
I had a shot at this: http://www.eribium.org/?p=74 Is it possible we could collaborate – I think using inheritance would be a better idea.
Also, just noticed, ‘deleteItem’ should have ’?_method=delete’ attached on to the url.
Thanks for the feedback, I’ll will look at your website once I am back from the mountains. But we should definitively work together on it. deleteItem already sets the _method attribute via the mx:request in the HttpService definition.
I just stumbled upon this nice introduction article about RESTful nested CRUD resource http://earthcode.com/blog/2007/01/nested_crud_resources_in_rails_1.html
Good stuff, i’ve been chatting with Alex about this for a while. It also gets around the problem that the Flex HTTPService doesn’t support PUT,DELETE without the Flex proxy (http://www.liverail.net/articles/2006/12/13/flex-no-rest-for-the-wicked)
Daniel, are you still using this? I’ve been thinking of building my own RESTful service along the lines of what you’ve done here.
I’ve been wondering about how well this works if you’re trying to do say 2 different shows at the same time with the same service. Since this changes the url of the service, what happens if something like this happens:
So basically, what happens if you have one request pending on show, and another one happens before that first returns? Does the HTTPService not like messing with the url in this case? Do the onResult handlers get confused?
I’m going to look into these things myself, but if you have looked into this I’d appreciate hearing what you’ve come across.
The mx:HTTPService supports different level of concurrency that can be set using the concurrency attribute (“multiple|single|last”). By default it supports multiple call and you responders won’t get confused. However “my” code doesn’t support concurrency.
ActiveResourceClient.show methodSo if you have one instance of ActiveResourceClient that issues two show calls at the same time there is a potential race condition between setting the url on the showOperation (HTTPService) and the call to the send method. If you need to do concurrent calls with the ActiveResourceClient you need multiple instance of the ActiveResourceClient that each issue the call in parallel. Currently it’s not an issue for the application I am working on.
I’ve done a bit more testing of this and I’m not so worried about the specific example I gave here. It seems like this won’t be a problem (although one will probably want some mechanism to identify what show goes with what in their result handler, assuming 1 result handler for all shows).
One thing I am still worried about is a race condition on the http service’s url. So this happens:
1 Event handler 1 does watches.show(1)
1.1 update’s the service’s url
2 Event handler 2 does watches.show(2)
2.1 update’s the service’s url
2.2 does a .send on the service -> hitting /blahs/2
Now after that has happended event handler 1 executes again:
1.2, event handler 1’s show does service.send -> hitting /blahs/2 instead of /blahs/1
In Java for instance, I would alleviate this concern with a synchronized block, but I’m not sure if this is even a problem in Flex (I’m not totally up to speed on how flex’s event handling uses threading).
Hi Jerry,
Your concern and the example you give is exactly the race condition I was describing. It’s a problem you can solve by creating two instances of ActiveResourceClient, i.e:
Then your point 1. would be watches1.show(1) and your point 2. watches2.show(2). This solves the potential race issue.Note in Flex you don’t control threads nor can use a synchronization block. You just have to be aware that as the UI is event driven and any remote calls asynchronous you can have code that runs parallel. Also you can not garantee in which order the result will come back. 2 can come back before 1.
This said your raised an excellent point. I need to do more reading on how the AVM3 is implemented and manages threading.
Not sure this helps you.
Daniel, thanks for the reply. I missed that comment where you talk about that race condition (exactly what I was trying to warn about)... D’oh.
Is there an example flex app that uses this?