Wednesday, 14 January 2015

Building a HATEOAS Hypermedia RESTful Record Store Web Service with Spring

Introduction

  • This is a very simple example of developing a hypermedia-driven RESTful web service, using Spring HATEOAS
  • A companion project is available to download on github (using Java, Maven and Spring Boot)

HATEOAS? What is it?

  • HATEOAS ("Hypermedia as the Engine of Application State") is an approach to building RESTful web services, where the client can dynamically discover the actions available to it at runtime from the server. All the client should require to get started is an initial URI, and set of standardised media types. Once it has loaded the initial URI, all future application state transitions will be driven by the client selecting from choices provided by the server. 
  • The choices of available actions may be driven by state in time (e.g. different actions available to the user based on access control or stateful data through workflow or previous actions), or by available functionality (e.g. as new functionality becomes available - the client can hook into them with no design changes on its part)

Where did it come from?

  • HATEOAS constraint is an essential part of the "uniform interface" feature of REST, as defined in Roy Fielding's doctoral dissertation (Ray was one of the principal authors of the HTTP specification, and co-founder of the Apache HTTP server project)
  • In his view if an API is not being driven by hypertext, then it cannot be RESTful

The Record Store Spring Example




  • The entry point to our API is :
    • http://localhost:8080/albums/
    • This will basically list all the albums available at our store, along with Stock Levels


  • It provides links to any client of our api telling it the URLs it can use to:
  • View and Albums details:
    • http://localhost:8080/album/{id}



  • View details of the Artist:
    • http://localhost:8080/artist/{id}


  • Purchase a copy of the Album:
    • http://localhost:8080/album/purchase/{id}
    • Note: this action is only displayed next to an album when the stock level is > 0 (an example of how the server will control the transitions available to the client based on current application state)
    • Look at the example below - first call to view album '3' shows it is available to purchase:
      • http://localhost:8080/album/3


      • If you then purchase it, using http://localhost:8080/album/purchase/3, next time you view it you can see there is no longer a purchase option available



The Code


Application.java


Album.java

Artist.java

MusicService.java


  • This is just a mock service that simulates a service/data access layer
  • It provides some methods to retrieve Album and Artist data, and also to purchase an Album (which for now will just reduce the stock level by 1)


ArtistController.java

  • Spring web controller for Artist operations


AlbumController.java

  • Spring web controller for Album operations
  • Note how in here a check is made on stock Levels in determining whether to allow the client to make a purchase



pom.xml


Building and running the example

Building

  • You will require Maven installed and configured (see .... for more details on this)
  • The example project uses Spring Boot to run the example. This basically builds a JAR file and spins up an embedded Tomcat container using a very simple command (so no WAR file is built, and no deployment to an external server is needed). This is great for getting up and running quickly - all you need is Maven and a JDK.

Running

Running with Eclipse STS

  • If you use Eclipse STS - you can just run the project as a Spring Boot App (just right-click the project in the package explorer and click 'Run As .. Spring Boot App'

Running with Maven

  • On the command line, navigate to the project folder root (containing pom.xml), and use 'mvn clean install spring-boot:run'

Either of these will start the Spring Boot deployment, and you should see a screen similar to this:



Changing the Embedded Tomcat Port

  • Just change the 'server.port' setting in application.properties

Further Reading

 - http://en.wikipedia.org/wiki/HATEOAS
 - http://en.wikipedia.org/wiki/Roy_Fielding
 - http://projects.spring.io/spring-hateoas/
 - http://roy.gbiv.com/