Spring Hateoas Example
In the following snippets of code you can see an example of Rest Endpoint using the Spring Hateoas
framework.
This post aims to only show a runnable example giving to readers the possibility to be introduced quickly to a new argument.
BookController.java
package com.simonefolinojavablog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
private BookRepository bookRepository;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public @ResponseBody BookResource show(@PathVariable String id) {
Book book = bookRepository.getBook(id);
BookResourceAssembler bookResourceMapper=new BookResourceAssembler(getClass(), BookResource.class);
BookResource resource = bookResourceMapper.toResource(book);
return resource;
}
}
BookResource.java
package com.simonefolinojavablog;
import org.springframework.hateoas.ResourceSupport;
/**
* The Class BookResource.
*/
public class BookResource extends ResourceSupport {
/** The name. */
private String name;
/**
* Sets the name.
*
* @param name
* the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName() {
return name;
}
}
BookResourceAssembler.java
package com.simonefolinojavablog;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import java.util.List;
import org.springframework.hateoas.mvc.ResourceAssemblerSupport;
/**
* The Class BookResourceMapper.
*/
public class BookResourceAssembler extends ResourceAssemblerSupport<Book, BookResource> {
public BookResourceAssembler(Class<?> controllerClass, Class<BookResource> resourceType) {
super(controllerClass, resourceType);
}
public BookResource toResource(Book entity) {
BookResource resource = createResourceWithId(entity.getId(), entity);
resource.add(linkTo(methodOn(AuthorController.class).show(entity.getAuthor().getId())).withRel("author"));
resource.setName(entity.getName());
return resource;
}
/* (non-Javadoc)
* @see org.springframework.hateoas.mvc.ResourceAssemblerSupport#toResources(java.lang.Iterable)
*/
@Override
public List<BookResource> toResources(Iterable<? extends Book> entities) {
return super.toResources(entities);
}
}
AuthorController.java
package com.simonefolinojavablog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* The Class AuthorController.
*/
@Controller
@RequestMapping("/author")
public class AuthorController {
/** The author repository. */
@Autowired
private BookRepository bookRepository;
/**
* Show.
*
* @param authorId the author id
* @return the http entity
*/
@RequestMapping(value = "/{authorId}", method = RequestMethod.GET)
public HttpEntity show(@PathVariable String authorId) {
Author author = bookRepository.getAuthor(authorId);
AuthorAssembler authorAssembler = new AuthorAssembler(AuthorController.class, AuthorResource.class);
AuthorResource resource = authorAssembler.toResource(author);
return new HttpEntity(resource);
}
}
mvc-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<context:component-scan base-package="com.simonefolinojavablog" />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
<bean id="jacksonSerializationConfig" class="org.codehaus.jackson.map.SerializationConfig"
factory-bean="jacksonObjectMapper" factory-method="getSerializationConfig" />
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonSerializationConfig" />
<property name="targetMethod" value="setSerializationInclusion" />
<property name="arguments">
<list>
<value type="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion">NON_NULL</value>
</list>
</property>
</bean>
</beans>
Invoke Rest Endpoint
If you invoke on localhost your endpoint using the following uri http://localhost:8080/hateoas-example/book/1 you get the book resource that has identifier "1".
{"links":[{"rel":"self","href":"http://localhost:8080/hateoas-example/book/1","variables":[],"templated":false,"variableNames":[]},{"rel":"author","href":"http://localhost:8080/hateoas-example/author/1","variables":[],"templated":false,"variableNames":[]}],"name":"Never Ending Story","id":{"rel":"self","href":"http://localhost:8080/hateoas-example/book/1","variables":[],"templated":false,"variableNames":[]}}
If you analyze the following json result, you can see that the resource "Book" has two attributes ( id, name) and a collection of links. In the links sections there is a reference to another resource "Author" that is available at the address http://localhost:8080/hateoas-example/author/1