martes, octubre 04, 2011

Can't you see, It all makes perfect sense, Express in dollars and cents, Pounds shillings and pents, Can't you see, It all makes perfect sense (Perfect Sense Part II - Roger Waters)



REST INTRODUCTION

From Wikipedia: REST-style architectures consist of clients and servers. Clients initiate requests to servers; servers process requests and return appropriate responses. Requests and responses are built around the transfer of representations of resources. A resource can be essentially any coherent and meaningful concept that may be addressed.

As you have read the most important thing in Rest architecture is the existance of a resource. This resource  can be anything (typically required information requested by client) that can be identified with a global identifier (URI in case of HTTP). In order to manipulate these resources, client communicates using standard interfaces (like HTTP) and exchange representations of these resources (using HTML, XML, ...).

Note that Rest does not force you to use any specific network protocol nor how resources are identified.

For those who have never read about Rest this description of Rest architecture could seem something strange and bit complicated. 

A RESTful web service is a simple web service implemented using HTTP and the principles of REST. URI is defined as global identified, communication interface is HTTP and resource representation can be any valid Internet media type like JSON, XML or YAML. The set of operations that can be executed to resources depend on HTTP Methods and are (GET - retrieving/listing, PUT - replacing/updating, POST - creating and DELETE - deleting).

HANDS ON WORK

Let's create our first Rest application with help of Spring MVC. Imagine an application that has a database of manga characters, and you want to provide a Rest interface so clients can retrieve characters following a RESTful strategy.

First thing to do is identify the resource. In this case it is easy, "a character". Next step is finding a URI that determines unequivocally a character. Easy too de facto rule can be applied here. This rule suggests that a unique URI can be <host>/<applicationname>/<resourceName>s/<id> in our case to return (GET) character with id 1 the URI would be "http://localhost:8080/RestServer/characters/1". If no identifier is present all characters should be retrieved. If instead of GET, POST is used, a character with id "1" would be inserted. And finally decide which Internet media type is required, in this case doesn't matter because we are implementing both client and server so initially XML will be used.

CODING

Let's start with a simple Spring MVC application created with Spring MVC template. Not much secret here, you will have a servlet-context.xml where component-scan, annotation-driven and InternalResourceViewResolver are registered.

Next step is defining Character class. A simple POJO with four attributes. Class is converted to its XML representation using Jaxb annotation.  Jaxb allows developers to map Java classes to XML representations and viceversa.

And finally the most important class in Spring MVC, "The Controller". Controller will be the responsible of implementing required operations of Character resource. In current case only GET is implemented, the other operations would be similar. Let's see the code:


First part is a map where all characters are stored. I have used this approach to not focus in data access. Then findCharacter method that is called when URI is /characters/{characterId}. This is a URI template and is a URI-like string, containing one or more variable names, which can be accessed using @PathVariable annotation. So when you are accessing to /characters/1 parameter characterId is bound to 1.

Last important part is @ResponseBody annotation. This annotation can be put on a method and indicates that the return type should be written straight to the HTTP response body, and not placed in a Model, or interpreted as a view name as standard behaviour of Spring MVC. So findCharacter method returns a Character object.

And that's all if you execute this code, and for example you enter URI http://localhost:8080/RestServer/characters/1 the output (using RestClient UI) will be:


And now is when you are wondering, ¿If I am returning a Character object and output is a XML, where is conversion between object and XML? So easy, let me introduce a new concept: HttpMessageConverters. HttpMessageConverter is responsible for converting from HTTP request message to an object and converting from an object to HTTP response body. Next HttpMessageConverters are registered by default:

- ByteArrayHttpMessageConverter
- StringHttpMessageConverter
- ResourceHttpMessageConverter
- SourceHttpMessageConverter
- XmlAwareHttpMessageConverter
- Jaxb2RootElementHttpMessageConverter
- MappingJacksonHttpMessageConverter

So now you understand why works perfectly. When you are returning Character instance, Jaxb2RootElementHttpMessageConverter using canWrite method checks if class contains XmlRootElement annotation. If class is annotated, write method is called. In this case Jaxb marshaller is called, and XML is returned. Same from XML to object but using Jaxb unmarshaller class.

So easy, no complicated configurations, no complicated mappings, no unclear code, and you only need to worry about your model objects, not in conversion. But let me introduce one change. Now instead of returning XML we want to return JSON.

Change could not be easier, add Jackson library to pom.xml and change @XmlRootElement to @JsonAutoDetect. And now MappingJacksonHttpMessageConverter will handle this object and will transform Character instance to JSON protocol using Jackson library. Only changing one line of code!!!

And now output will be:



CONCLUSIONS

Of course this is a very simple application with only one operation, but it gives you an idea of how to develop Restful web services using Spring MVC. It is a matter of time of writing all your required operations using same approach that I have used with GET.

Arriving at this point I think that all of us have arrived to same conclusion. Annotations are really really powerful, and Spring MVC fits perfectly for developing RESTful web services.

See you next time.

8 comentarios:

Anónimo dijo...

Nice article, thank you!

Rossen Stoyanchev dijo...

Hi, nice article. For the purpose of your example you don't need a InternalResourceViewResolver in your configuration. The @ResponseBody annotation indicates the return value should be written to the response and no further work (e.g. view resolution for JSP-based rendering) is required.

knalli dijo...

Hey, what eclipse plugin do you use for testing/working against the REST api?

Thanks.

Alex dijo...

Thank you very much for your comments. Rossen I agree with you, because I have used the template generated by STS I didn't remove InternalResourceViewResolver, but should be removed.
Knalli I use Rest Client but you can find many more in eclipse market like http4e http://www.ywebb.com/ or restclient-tool like http://code.google.com/a/eclipselabs.org/p/restclient-tool/

Anónimo dijo...

I suggest to use JAX-RS for restful applications. It has a really nice and clean API.

Alex dijo...

Dxxvi ask me next question that I think that can be shared with you:

"Now instead of returning XML we want to return JSON.
Change could not be easier, add Jackson library to pom.xml and change @XmlRootElement to @JsonAutoDetect.": if I have a client asking for xml and another requiring json, what should you do? Have you ever heard of ContentNegotiatingViewResolver?"

And my response was:

"Hi it is easier than this, in fact it is so easy, you should only tell to client that requires XML to send you Accept header parameter with application/xml and json with application/json. And magic, Spring knows what converter to use. In fact it is not magic AnnotationMethodHandler retrieves media type from this field, and is passed to canWrite/canRead method of message converter.

Thanks for reading my post."

Hope that this can help more people.

Rickard Öberg dijo...

This article has nothing to do with REST. In particular, there is no use of hypermedia (i.e. linnks), which is required in REST. Have you read the thesis?

Anónimo dijo...

I'm glad that i see www.blogger.com again
[url=http://www.youtube.com/watch?v=beX72Js-mdQ]eye makeup tutorial[/url]
[url=http://www.youtube.com/watch?v=CTwrXW6B2JA]school makeup tutorial[/url]
[url=http://www.youtube.com/watch?v=Y-YKJF87SCQ]zombie makeup[/url]