Search This Blog

Tuesday, 28 May 2013

Rest Example with Spring - 2

Continuing from the previous post, I decided to take up the next method
@RequestMapping(value = "{id}", method = RequestMethod.GET)
public @ResponseBodyUser getUser(@PathVariable final int id) {"getUser with id " + id);
   return this.allUsers.get(id);
The method will return an User instance when the id is passed to it. So the URL for the same would be
The documentation for the PathVariable annotation
Annotation which indicates that a method parameter should be bound to a URI template variable.
When the controller receives a request with the above URL and the GET method, it sets the value of id variable with the value following /user/<id>
On executing the call, the server logs indicate how the method was detected:
2013-05-05 20:18:33 DEBUG DispatcherServlet:819 - DispatcherServlet with name 'd
ispatcher' processing GET request for [/SampleRest/api/user/1]
2013-05-05 20:18:33 DEBUG RequestMappingHandlerMapping:209 - Looking up handler 
method for path /user/1
2013-05-05 20:18:33 DEBUG RequestMappingHandlerMapping:253 - Found 1 matching ma
pping(s) for [/user/1] : [{[/user/{id}],methods=[GET],params=[],headers=[],consu
2013-05-05 20:18:33 DEBUG ServletInvocableHandlerMethod:123 - Invoking [getUser]
 method with arguments [1]
The next is the create method:
@RequestMapping(method = RequestMethod.POST)
   public @ResponseBody
   User addUser(@RequestBody final User user) {
      final int newId = this.keyIndex++;
      this.allUsers.put(newId, user);"addUser : new User added with id " + newId);
      return user;
The method is a POST method to the same resource. I tried to execute the same with the RestClient plugin and got the below exception:
2013-05-05 20:24:30 DEBUG RequestMappingHandlerMapping:216 - Returning handler m
ethod [public com.test.controller.User com.test.controller.RestServiceController
2013-05-05 20:24:30 DEBUG ServletInvocableHandlerMethod:160 - Error resolving ar
gument [0] [type=com.test.controller.User]
HandlerMethod details: 
Controller [com.test.controller.RestServiceController]
Method [public com.test.controller.User com.test.controller.RestServiceControlle
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/p
lain;charset=UTF-8' not supported
A little web hunting indicated that the root cause was Spring not having any clear idea on how to deal with my request body. So I added appropriate headers and made the call again:
 As seen the response returned the record with id set to a new value. The logs indicate the method being called after the request body has been processed.
2013-05-05 20:30:04 DEBUG RequestResponseBodyMethodProcessor:117 - Reading [com.
test.controller.User] as "application/json;charset=UTF-8" using [org.springframe
2013-05-05 20:30:04 DEBUG ServletInvocableHandlerMethod:123 - Invoking [addUser]
 method with arguments [com.test.controller.User@1ff66bd]
2013-05-05 20:30:04 INFO  RestServiceController:72 - addUser : new User added wi
th id 4
The next method is for Update.
@RequestMapping(value = "{id}", method = RequestMethod.PUT)
   public @ResponseBody
   User updateUser(@PathVariable final int id, @RequestBody final User user) {
      if ((user.getId() == User.INVALID_ID) || (id == User.INVALID_ID)) {
         throw new RuntimeException("Invalid Id receieved - ");
      this.allUsers.put(id, user);"updateUser : user with id " + user.getId()
            + " has been updated");
      return user;
Here a PUT method was used for the same resource.Similarly we can use the DELETE method to delete a resource from the server.
@RequestMapping(value = "{id}", method = RequestMethod.DELETE)
   @ResponseStatus(value = HttpStatus.OK)
   public void deleteUser(@PathVariable final int id) {
      this.allUsers.remove(id);"deleteUser : user with id " + id + " has been deleted");
Both these methods use the id extracted from the URL itself. I tested both of the above using RestClient Plugin and they worked fine. The Delete method is a bit different in that it has a void return type. If the method succeeds, than the Servlet will  return a 200 value or OK.
This completes basic CRUD operations.
The last method is not exactly a resource method in that it uses a slightly different URL.
@RequestMapping(value = "search/{name}", method = RequestMethod.GET)
   public @ResponseBody
   User findUserByName(@PathVariable final String name) {"findUserByName : for name " + name);
      User target = null;
      for (final User user : this.allUsers.values()) {
         if (name.equals(user.getName())) {
            target = user;
      return target;
The method is actually a search method. The URL for the same would be
The value after "/search" goes into the method variable marked by PathVariable annotation. This method returns a user with the specified name.
This completes my REST API for user resource. With Spring implementing the service was easier than expected.