Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC, REST, and HATEOAS

Tags:

I'm struggling with the correct way to implement Spring MVC 3.x RESTful services with HATEOAS. Consider the following constraints:

  • I don't want my domain entities polluted with web/rest constructs.
  • I don't want my controllers polluted with view constructs.
  • I want to support multiple views.

Currently I have a nicely put together MVC app without HATEOAS. Domain entities are pure POJOs without any view or web/rest concepts embedded. For example:

class User {    public String getName() {...}    public String setName(String name) {...}    ... } 

My controllers are also simple. They provide routing and status, and delegate to Spring's view resolution framework. Note my application supports JSON, XML, and HTML, yet no domain entities or controllers have embedded view information:

@Controller @RequestMapping("/users") class UserController {    @RequestMapping   public ModelAndView getAllUsers() {     List<User> users = userRepository.findAll();     return new ModelAndView("users/index", "users", users);   }    @RequestMapping("/{id}")   public ModelAndView getUser(@PathVariable Long id) {     User user = userRepository.findById(id);     return new ModelAndView("users/show", "user", user);   } } 

So, now my issue - I'm not sure of a clean way to support HATEOAS. Here's an example. Let's say when the client asks for a User in JSON format, it comes out like this:

{   firstName: "John",   lastName: "Smith" } 

Let's also say that when I support HATEOAS, I want the JSON to contain a simple "self" link that the client can then use to refresh the object, delete it, or something else. It might also have a "friends" link indicating how to get the user's list of friends:

{   firstName: "John",   lastName: "Smith",   links: [     {       rel: "self",       ref: "http://myserver/users/1"     },     {       rel: "friends",       ref: "http://myserver/users/1/friends"     }   ] } 

Somehow I want to attach links to my object. I feel the right place to do this is in the controller layer as the controllers all know the correct URLs. Additionally, since I support multiple views, I feel like the right thing to do is somehow decorate my domain entities in the controller before they are converted to JSON/XML/whatever in Spring's view resolution framework. One way to do this might be to wrap the POJO in question with a generic Resource class that contains a list of links. Some view tweaking would be required to crunch it into the format I want, but its doable. Unfortunately nested resources could not be wrapped in this way. Other things that come to mind include adding links to the ModelAndView, and then customizing each of Spring's out-of-the-box view resolvers to stuff links into the generated JSON/XML/etc. What I don't want is to be constantly hand-crafting JSON/XML/etc. to accommodate various links as they come and go during the course of development.

Thoughts?

like image 214
SingleShot Avatar asked Aug 23 '11 20:08

SingleShot


People also ask

What is the use of Spring HATEOAS?

Spring HATEOAS provides some APIs to ease creating REST representations that follow the HATEOAS principle when working with Spring and especially Spring MVC. The core problem it tries to address is link creation and representation assembly.

How do you implement HATEOAS in REST spring boot?

To implement HATEOAS, we would need to include related resources in the response. Instead of Student we use a return type of EntityModel<Student> . EntityModel is a simple class wrapping a domain object and allows adding links to it. We create a new resource.

Should I use Spring HATEOAS?

Spring HATEOAS provides common abstractions (representational models, a Link class, API to build links pointing to Spring MVC controllers, etc.) to ease building hypermedia driven REST APIs with Spring MVC in general. Thus, you can use it alongside Spring MVC to manually build those services.


1 Answers

There is a useful project called Spring HATEOAS on GitHub which has the following description:

"This project provides some APIs to ease creating REST representations that follow the HATEOAS principle when working with Spring and especially Spring MVC"

If the resource class you are returning extends 'ResourceSupport' you can easily add links to it, and you can build links using 'ControllerLinkBuilder', for example to add a self link:

import static org.sfw.hateoas.mvc.ControllerLinkBuilder.*;  Link link = linkTo(YourController.class).slash(resource.getName()).withSelfRel(); resource.add(link); 

It is quite a new project but it is available from the public Maven repo if required:

<dependency>     <groupId>org.springframework.hateoas</groupId>     <artifactId>spring-hateoas</artifactId>     <version>0.3.0.RELEASE</version> </dependency> 

If you use the maven artifact:

org.sfw.hateoas.mvc.ControllerLinkBuilder 

becomes:

org.springframework.hateoas.mvc.ControllerLinkBuilder 
like image 65
smithleej Avatar answered Nov 27 '22 01:11

smithleej