Activitats

HATEOAS per a un servei web RESTful

L’objectiu d’aquesta activitat és veure el suport que proporciona Spring per construir serveis web RESTful que segueixin el principi HATEOAS (de l’anglès Hypermedia as the Engine of Application State ). Veurem què és HATEOAS i com ho podem implementar amb Spring.

A partir d’un servei web RESTful fet amb Spring que permeti fer operacions sobre equips de futbol i els jugadors que els integren, cal que redissenyeu la funcionalitat que permeti consultar la informació d’un equip per tal que segueixi el principi de disseny HATEOAS. El projecte inicial ja té el servei web completament desenvolupat, però no segueix el principi de disseny HATEOAS.

Descarregueu el codi del projecte “Springresthateoasioc” en l’estat inicial d’aquest apartat en el següent enllaç i importeu-lo a NetBeans:

El primer que farem serà desplegar el servei web que us proporcionem com a punt de partida i provar que funciona correctament. Desplegueu el projecte fent Run a NetBeans.

Projecte en estat final

En el següent enllaç teniu disponible el projecte en l’estat final:

Tot i que podeu descarregar-vos el projecte en l’estat final, sempre és millor que aneu fent vosaltres tots els passos partint del projecte en l’estat inicial de l’apartat. Recordeu que podeu utilitzar la funció d’importar per carregar els projectes a NetBeans.

El servei web RESTful que conté el projecte permet fer operacions sobre equips de futbol i els jugadors que els integren. Té implementades les operacions típiques CRUD amb els jugadors, una operació que mostra el llistat d’equips, una que ensenya els jugadors d’un equip i una altra que mostra les dades d’un equip.

Per fer l’exercici ens ficarem en la funcionalitat que permet consultar les dades d’un equip i la funcionalitat que permet llistar tots els jugadors.

Per consultar les dades d’un equip (per exemple, les dades del FC Barcelona), accediu amb un navegador a l’URL localhost:8080/springresthateoasioc/teams/1 i, si tot ha anat bé, veureu la representació JSON de l’equip consultat al navegador:

[{ 
  "teamId":1,
  "name":"F.C. Barcelona",
  "foundationYear":"1899"
}]

Si ara voleu llistar els jugadors que formen part del FC Barcelona no ens queda més remei que consultar l’API del servei RESTful per veure que ho podem fer amb una petició GET a /teams/{teamId}/players. Si ho feu accedint amb un navegador a l’URL localhost:8080/springresthateoasioc/teams/1/players veureu la llista de jugadors del FC Barcelona:

[
{"id":1,"name":"LionelMessi","goals":472,"age":29,"teamId":1},
{"id":2,"name":"Luis Suarez","goals":100,"age":29,"teamId":1}}
]

Amb aquesta aproximació apareixen dos problemes principals:

  • No tenim cap manera de saber com obtenir els jugadors d’un equip sense haver de consultar la seva API.
  • Si la forma d’accedir (API) als jugadors d’un equip canvia caldrà canviar tots els clients que la utilitzaven.

Per solucionar aquestes dues problemàtiques apareix el concepte de HATEOAS.

De forma molt simplificada, podríem veure HATEOAS com un principi de disseny que obliga que, donat un punt d’entrada al servei, els clients han de ser capaços de descobrir tots els seus recursos basant-se únicament en respostes donades pel servidor.

A l’exemple que ens aplica, això vol dir que quan consultem la informació d’un equip el servidor ens ha de tornar també l’enllaç per consultar els seus jugadors; és a dir, la resposta JSON a la consulta de les dades d’un equip ha de ser similar a aquesta:

[{ 
  "teamId":1,
  "name":"F.C. Barcelona",
  "foundationYear":"1899",
  “players”: “http://localhost:8080/springresthateoasioc/teams/1/players”
}]

D’aquesta forma ja sabrem on i com anar a buscar els recursos relacionats (jugadors) amb el nostre recurs (equip) gràcies a la resposta del servidor en forma d’enllaç. Molts puristes diuen que una API no és realment RESTful si no segueix aquest principi de disseny.

Ara ja sabem què és HATEOAS i també que el nostre servei web no el segueix, però com ho podem fer dissenyar-lo seguint el principi HATEOAS? Aquí és on apareix un petit mòdul Spring anomenat Spring HATEOAS, que ens ajudarà a fer que el nostre servei respecti el principi HATEOAS.

Modifiqueu el pom.xml per afegir les dependències cap a Spring HATEOAS, afegint les següent línies al fitxer pom.xml:

  1. <dependency>
  2. <groupId>org.springframework.hateoas</groupId>
  3. <artifactId>spring-hateoas</artifactId>
  4. <version>0.8.0.RELEASE</version>
  5. </dependency>

Recarregueu el pom.xml fent clic amb el botó dret damunt el nom del projecte i prement l’opció Reload POM.

Spring HATEOAS tan sols imposa una restricció: els recursos que tornem a la resposta han d’estendre de la classe org.springframework.hateoas.ResourceSupport. Simplement fent això ja podrem afegir al recurs els enllaços que permetran als clients fer la navegació.

El recurs que volem que torni l’enllaç amb la consulta dels jugadors de l’equip és l’objecte del domini Team, que és el que torna la consulta de la informació d’un equip. Obriu la classe Team del paquet cat.xtec.ioc.domain i feu que estengui de ResourceSupport:

  1. public class Team extends ResourceSupport

Ara el que hem de fer és modificar el mètode del servei web que torna les dades d’un equip per incloure l’enllaç a la resposta que permetrà consultar els jugadors de l’equip. Per fer-ho obriu la classe TeamsController del paquet cat.xtec.ioc.controller i canvieu el codi del mètode getById pel següent:

  1. @RequestMapping(value = "/teams/{id}", method = RequestMethod.GET)
  2. public @ResponseBody
  3. Team getById(@PathVariable int id) {
  4. Team team = this.teamRepository.get(id);
  5. final Link link = linkTo(methodOn(PlayerController.class).getTeamPlayers(team.getTeamId())).withRel("players");
  6. team.add(link);
  7. return team;
  8. }

El que fem és crear un enllaç que apunta al recurs que donaria com a resultat la invocació al mètode getTeamPlayers del controlador PlayerController.

Fixeu-vos que tant methodOn com linkToCodi són mètodes estàtics de la classe org.springframework.hateoas.mvc.ControllerLinkBuilder; per poder-los utilitzar cal que afegim a la classe TeamsController els import corresponents:

  1. import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
  2. import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

Ara ja tan sols ens queda tornar a desplegar el servei web per veure si es comporta com volem. Desplegueu-lo fent Run a NetBeans i comproveu que la representació JSON de l’equip ara incorpora un enllaç per consultar els seus jugadors.

Per fer-ho accediu a l’URL localhost:8080/springresthateoasioc/teams/1 amb un navegador i, si tot ha anat bé, veureu que la resposta JSON incorpora l’enllaç que volíem:

[{
  "teamId":1,
  "name":"F.C.Barcelona",
  "foundationYear":"1899",
  "links":[{"rel":"players","href":"http://localhost:8080/springresthateoasioc/teams/1/players"}]
}]

Amb HATEOAS hem aconseguit solucionar els dos problemes principals que tenia el nostre servei web quan no seguia els principis HATEOAS:

  • Ara ja sabem com obtenir els jugadors d’un equip sense haver de consultar la seva API.
  • Si la forma d’accedir (API) als jugadors d’un equip canvia, l’enllaç que tornem canviarà i no caldrà modificar els clients que la utilitzaven.

Anar a la pàgina següent:
Exercicis d'autoavaluació