For more information:
Archives
Posts filed under "Resource Oriented"
ActiveResource can take RESTful resources and map them to client-side classes with almost no configuration or code required by the application developer. Lets take a look at the classic “Person” service example:
class Person < ActiveResource::Base
self.site = “http://www.bti360.com/person-service”
end
In these few lines of code we’ve created a Person model class that can be used throughout our application much like our ActiveRecord based model classes that interact with our database. What can we do with this class? Well, out of the box you can do all the standard CRUD operations.
Lets take a look at how some of these operations might look.
So say we want to create a new person. Here is some sample code to do just that:
jp = Person.new(:first_name => 'Jon’, :last_name => ‘Pierce’)
jp.save # sends POST /people/ (create)
The save method above will send the following XML to the service in the POST request body:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<first-name>Jon</first-name>
<last-name>Pierce</last-name>
</person>
And any response body from the request will be parsed and assumed to be the saved representation of the new person. Once the person has been saved we can easily make updates:
jp.new? # => false
jp.last_name = ‘Awesome’
jp.save # sends PUT /people/1 (update)
So we’re following standard convention here to get us moving very quickly. Similarly we could delete our new person:
jp.destroy # sends DELETE /people/1 (delete)
And now JP is gone.
The final piece to the CRUD puzzle is the ‘find’ method. As with the others, this method behaves similarly to the ActiveRecord find method. Here are some examples:
Person.find(1)
# => GET /people/1.xml
Person.find(:all)
# => GET /people.xml
Person.find(:all, :params => { :last_name => "Smith" })
# => GET /people.xml?last_name=Smith
As you can see ActiveResource provides a lot of power into very little code for the application developer, and this blog has only scratched the surface. ActiveResource has many more options and features to allow you to taylor it to your specific needs and purposes, including validation, error handling and many others.
I would recommend diving into the ActiveResource API documentation on the RoR homepage if you’re interested in learning more about it. Or feel free to shoot me an email, I’d love to discuss it with you.
Happy coding!!!
The subject of media types has been glossed over in some of our recent blogs and screencasts. In this blog I'd like to focus on what media types are and give some basic guidelines for using them in your RESTful web services.
A media type is a two-part identifier for file formats on the Internet. Some examples of very common media types are:
- text/xml
- text/html
- audio/mpeg
- video/mp4
- image/jpeg
A list of registered media types is made available on the web by the Internet Assigned Numbers Authority (IANA). So how does this relate to RESTful web services? As you already know RESTful web services are focused around resources, and service clients interact with those resources through representations. Every representation of a resource is a media type.
Here are a few guidelines regarding how you should represent the resources in your web services using media types:
- Whenever possible you should use existing media types to represent your resources. This will open your web service up to many more clients, and allow for much easier integration. It makes perfect sense. If you had a resource that was a person and you wanted one representation of the resource to be a picture of the person, would you send back that picture using the "image/jpeg" media type or would you make up your own image format and use that? I think the answer is pretty obvious.
One commonly used media type in RESTful web services is the ATOM Syndication Format (application/atom+xml). ATOM was essentially designed as an improved format for web feeds. But its flexibility has made it a great media type for representing resource collections. By using the ATOM media type to represent your collection resources, you immediately open your service up to a huge range of clients that already know how to parse ATOM XML.
- Ensure that your media types accurately represent your resources. So I'm going to pick on one of our own previous blog postings. In the last blog on HATEOAS we used the following request / response example:
Client Request:
GET /dictionary/happy HTTP/1.1 Accept: application/xml
Service Response:
So here our client has asked for a resource represented using the 'application/xml' media type. And our service has responded with the representation in XML format. You may wonder: "What's the problem? 'application/xml' is a valid and common media type." That it is, but unfortunately, if I go and read the specification for the 'application/xml' media type I will be able to parse the response above, but I won't have any idea what it means.Content-type: application/xml <?xml version="1.0" encoding="UTF-8"?> <entry> <word>happy</word> <part-of-speech>adjective</part-of-speech> <definition>delighted, pleased, or glad, as over a particular thing</definition> </entry>
The same would apply if I had sent back 'application/json'. So what is the best thing to do? First, check the registered media types to see if there is a public and widely used representation for dictionary entries that meets your needs. If you find one that nearly meets your needs, hopefully you can extend it. If you don't find one, then you'll have to create your own media type. Here's how the previous request might look if I had used a custom media type for a dictionary entry:
Client Request:GET /dictionary/happy HTTP/1.1 Accept: application/dict-entry+xml
Service Response:Content-type: application/dict-entry+xml <?xml version="1.0" encoding="UTF-8"?> <entry> <word>happy</word> <part-of-speech>adjective</part-of-speech> <definition>delighted, pleased, or glad, as over a particular thing</definition> </entry>
As you can see, the data returned here is the same. The key difference is in the 'Content-type' header. The 'application/dict-entry+xml' media type would be well-defined and clearly inform the client of how to interpret the response.
- Ensure all your media types are well documented and publicly available. This is not much of an issue if you use a registered media type to represent a resource. However, if you are using custom media types or extending a registered media type, it is imperative that you very clearly document the media type and make that documentation publicly available to any potential service clients.
This is one of the things that we mentioned when we discussed HATEOAS. The two pieces of information that a client needs to know to use a RESTful web service are the starting point and how to interpret the information displayed. So this is where nearly all of our service documentation will come from: documenting our media types. This can't be stressed enough. DOCUMENT YOUR MEDIA TYPES!!!
That's about it for media types at this point. There may be more to come in the future, but I'll let you chew on all of this for now. Keep on learning, and pass your new knowledge on.
Now that Topher figured out how to make an HTTP request to a RESTful Web Service, he needs to know all about resources and representations. Resources are the objects that a web services exposes to the world. The resources are maintained and controlled by the service. A resource could be data in a database, a physical object such as a person, or a conceptual object like "the most recent blog posting."
Clients interact with resources through representations. And a resource can have many different types of representations. Examples of common representations are "text/html", "application/xhtml+xml", "application/xml", "application/json", "image/jpeg", "image/gif", and "audio/mpeg". RESTful web services can send and accept representations of resources in any of these content-types that the service chooses.
One of the reasons RESTful web services are popular is because they can easily provide many representations for a resource. Many RESTful web services provide the ability to return the results of a request in multiple formats by specify the format as part of the request. RESTful services provide a default format if none is specified on the request. Some web service implementations like SOAP only allow one response format. Lets look at some common response formats for an example GET request:
GET http://www.bti360.com/dictonary?synonym=happy
From a previous post we know that this request will return synonyms for the word 'happy'. Now lets see a few possible representations for this request. In the following examples note that the response format is specified on the HTTP request.
XML
GET http://www.bti360.com/dictionary/happy/synonyms.xml
The XML representation in the response looks like
<?xml version="1.0" encoding="UTF-8"?>
<synonyms>
<synonym>chipper</synonym>
<synonym>glad</synonym>
<synonym>pleased</synonym>
<synonym>tickled</synonym>
</synonyms>
JSON
GET http://www.bti360.com/dictionary/happy/synonyms.json
The JSON representation in the response looks like
[{"synonym": "chipper"}, {"synonym": "glad"}, {"synonym": "pleased"}, {"synonym": "tickled"}]}
HTML
GET http://www.bti360.com/dictionary/happy/synonyms.html
The HTML representation in the response looks like
<ul>
<li>chipper</li>
<li>glad</li>
<li>pleased</li>
<li>tickled</li>
</ul>
CSV
GET http://www.bti360.com/dictionary/happy/synonyms.csv
The CSV representation in the response looks like
chipper,glad,pleased,tickled
As you can see RESTful Web Services allow for many possible representations of the same resource. They can be standard or you can create your own. This flexibility allows many types of clients to access RESTful services. However, flexibility can also be dangerous. Whenever possible it is recommended that a RESTful web service use standard representations for their resources. This allows clients to quickly and easily integrate with your service.
http://www.bti360.com/dictionary/set
"Wait a second, that looks just like a website address?" they exclaimed, wanting to know what it all meant. Resources and verbs, my friends, think resources and verbs.
Resources are the actual "things" that are being exposed in a web service. In the example above, "/dictionary" is the resource and "/set" is a sub-resource. What can we do with these resources? Well, that's where the verbs come in.
RESTful web services take advantage of common HTTP methods in order to perform operations on a resource; these HTTP methods are referred to as REST verbs. The most commonly used verbs include:
|
REST(HTTP)
|
Operation |
| POST | Create |
| GET | Retrieve |
| PUT | Update |
| DELETE | Delete |
One nice characteristic of REST verbs is that the URI does not change when different operations are performed. For example, the same URI given at the top can be used to:
- Create the word set in the dictionary we use the HTTP POST
- Retrieve the definition of the word set in the dictionary we use the HTTP GET
- Update the definition of the word set in the dictionary we use the HTTP PUT
- Delete the word set from the dictionary we use the HTTP DELETE
So Snook and Topher, what did you learn today? The "web address"
that you saw is actually a REST URI that can be used to perform
interesting actions (create, read, update, delete) on a particular
resource. How about that? You both now know some basics for interacting
with a RESTful web service.
Please note: REST URI's should not be pre-constructed by client code. In fact, they should be treated as opaque identifiers that are meant to be discovered by following hyperlinks (the HATEOAS REST constraint will be discussed later... so stay tuned)
*A URI is the name and web address of a resource (an identifier)



ShareThis