Activitats

Habilitant sol·licituds Cross-Origin per a un servei web RESTful

L’objectiu d’aquesta activitat és veure les capacitats que proporciona Spring per habilitar sol·licituds CORS (de l’anglès Cross-Origin Resource Sharing) en les peticions AJAX que es facin als serveis web RESTful des d’un altre domini.

A partir d’un servei web RESTful fet amb Spring que respon a peticions GET a l’URI /hello amb “Hello, World!!!”, cal que habiliteu el servei web per tal que sigui capaç de servir peticions AJAX que provinguin d’un domini diferent del domini en el qual teniu desplegat el servei web (Cross-Origin). El projecte inicial ja té el servei web desenvolupat i està preparat per ser executat a un servidor Tomcat que porta Spring.

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

Feu a un altre projecte un client AJAX amb jQuery que consulti el servei web des d’un domini diferent per certificar que la solució funciona correctament. Desplegueu aquesta aplicació al servidor Glassfish.

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

Estat final del projecte

Al 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.

Farem el desplegament creant una aplicació executable que s’executarà amb un contenidor de servlets Tomcat que Spring porta incorporat per tal que el servei web s’executi en un servidor d’aplicacions diferent del servidor d’on farem les peticions AJAX i així comprovar que l’habilitació Cross-Origin funciona correctament.

El projecte que us proporcionem com a punt de partida ja té una classe Java anotada amb @SpringBootApplication amb un mètode main que crida el mètode run de SpringApplication. Farem el desplegament al port 9000 per tal que després puguem arrancar l’aplicació client al port 8080 de Glassfish.

Per fer-ho cal que tingueu la finestra Navigator visible (ho podeu fer amb Ctrl + 7) i el projecte “Springresthellocorsioc” seleccionat. Un cop tingueu la finestra Navigator visible executeu el goal de maven spring-boot:run afegint-hi el paràmetre -Dserver.port=9000 tal com es mostra en la figura.

Figura Execució del servei web al port 9000

I veureu que apareix una finestra a NetBeans amb l’execució de l’aplicació al port 9000 (vegeu la figura).

Figura Servei web arrancat en Tomcat al port 9000

Comproveu que el servei web està desplegat correctament accedint a l’URL http://localhost:9000/hello amb un navegador. El servei web us ha de tornar la salutació “Hello, World!!!” en format JSON:

{"id":1,"content":"Hello, World!!!"}

Si tot ha anat bé, ja teniu el servei web desplegat i a punt per rebre peticions. El següent que cal fer és que el client AJAX consumeixi el servei web des d’un domini diferent.

Això ho podeu fer de diverses maneres: una d’aquestes pot ser creant un nou projecte Maven a NetBeans de tipus Web Application. Per fer-ho, feu File / New Project i us apareixerà l’assistent de creació de projectes. A l’assistent seleccioneu Maven i Web Application, tal com es veu en la figura.

Figura Creació de projectes a NetBeans

En la següent pantalla (vegeu figura) triareu el nom del projecte; el podeu anomenar “Resthellocorsioc”, i en el paquet per defecte on anirà el codi font.

Figura Nom del nou projecte

En la següent pantalla de l’assistent deixeu els valors per defecte i polseu Finish.

Ara hem de crear l’aplicació web que consumeixi el servei web amb peticions AJAX realitzades amb jQuery.

Aprofundir en jQuery

L’objectiu d’aquest exemple no és aprofundir en el coneixement de jQuery, sinó que només pretén mostrar com es pot habilitar el Cross-Origin als serveis web Spring per permetre peticions AJAX que vinguin de diferents dominis. Si voleu aprofundir en el coneixement de jQuery ho podeu fer a jquery.com.

El primer que necessitem és crear un mòdul controlador jQuery que consumeixi el servei web. Per fer-ho creeu un fitxer anomenat hellojquery.js a Web Pages amb el següent contingut:

  1. $(document).ready(function() {
  2. $.ajax({
  3. url: "http://localhost:9000/hello"
  4. }).then(function(data) {
  5. $('.greeting-id').append(data.id);
  6. $('.greeting-content').append(data.content);
  7. });
  8. });

Aquest mòdul controlador es representa com una funció JavaScript que fa servir la funció ajax per fer la petició al servei web REST. Si la crida té èxit, s’assignarà el JSON retornat des del servei web a les variables id i content que s’afegiran als elements del DOM greeting-id i greeting-content, respectivament.

Un cop tenim el controlador ens cal crear la pàgina HTML que carregarà el controlador al navegador de l’usuari. Per fer-ho, creeu un fitxer anomenat hellojquery.html a Web Pages amb el següent contingut:

  1. <!DOCTYPE html>
  2. <head>
  3. <title>Hello jQuery</title>
  4. <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  5. <script src="hellojquery.js"></script>
  6. </head>
  7.  
  8. <body>
  9. <div>
  10. <p class="greeting-id">The ID is </p>
  11. <p class="greeting-content">The content is </p>
  12. </div>
  13. </body>
  14. </html>

A la secció head de la pàgina hi posem aquestes dues etiquetes:

  1. <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  2. <script src="hellojquery.js"></script>

La primera descarrega la llibreria jQuery del CDN (de l’anglès Content Delivery Network) per tal que no l’haguem d’incorporar al projecte, i el segon carrega el codi JavaScript del controlador que hem creat (hellojquery.js).

Fixeu-vos també que les etiquetes <p> tenen atributs class per tal que jQuery les pugui localitzar fàcilment al DOM i actualitzar-ne el valor amb el resultat de la crida AJAX al servei web.

Ara ja sols ens queda desplegar el client per veure si es comporta com volem.

Desplegueu el client fent Run a NetBeans i comproveu que el client està desplegat correctament accedint a l’URL localhost:8080/resthellocorsioc/hellojquery.html amb un navegador.

Si tot ha anat bé veureu la pàgina HTML, però no veureu la salutació del servei web RESTFul. Si torneu a fer la petició i inspeccioneu la resposta amb qualsevol eina de debug del navegador que feu servir, veureu que el que passa és que el servei web que esteu cridant no té el Cross-Origin habilitat, i per això us respon amb un error (vegeu la figura).

Figura Error Cross-Origin

CORS és una tecnologia que cada vegada necessitem més a l’hora de desenvolupar aplicacions web i també aplicacions mòbils. En una aplicació clàssica podem carregar una pàgina web i sol·licitar dades dinàmiques al servidor mitjançant AJAX, però aquestes dades dinàmiques han de pertànyer al mateix domini. Si les dades no pertanyen al mateix domini, l’aplicació no les podrà carregar per limitacions de seguretat.

Per solucionar això cal configurar el servidor per tal que els serveis suportin peticions CORS habilitant les capçaleres CORS a la resposta enviada pel servei web.

Per fer-ho, simplement cal que afegim l’anotació @CrossOrigin al mètode del controlador que té el servei web RESTful. Per fer-ho, obriu la classe GreetingController del projecte “Springresthellocorsioc” i afegiu la següent línia al mètode greeting:

  1. @CrossOrigin(origins = "http://localhost:8080")

El codi del controlador quedarà així:

  1. package cat.xtec.ioc.springresthelloioc.controller;
  2.  
  3. import cat.xtec.ioc.springresthelloioc.domain.Greeting;
  4. import java.util.concurrent.atomic.AtomicLong;
  5. import org.springframework.web.bind.annotation.CrossOrigin;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestMethod;
  8. import org.springframework.web.bind.annotation.RequestParam;
  9. import org.springframework.web.bind.annotation.RestController;
  10.  
  11. @RestController
  12. public class GreetingController {
  13.  
  14. private static final String template = "Hello, %s";
  15. private final AtomicLong counter = new AtomicLong();
  16.  
  17. @CrossOrigin(origins = "http://localhost:8080")
  18. @RequestMapping(method = RequestMethod.GET, value = "/hello")
  19. public Greeting greeting(@RequestParam(value="name", defaultValue="World!!!") String name) {
  20. return new Greeting(counter.incrementAndGet(),
  21. String.format(template, name));
  22. }
  23. }

Aquesta anotació habilita CORS solament per al mètode greeting i per a les peticions que vénen de localhost:9000. El comportament es pot personalitzar amb els atributs següents:

  • origins
  • methods
  • allowedHeaders
  • exposedHeaders
  • allowCredentials
  • maxAge

També es pot habilitar CORS de forma global per a tots els mètodes del controlador posant l’anotació a nivell de classe, enlloc de fer-ho a nivell de mètode i de forma més global afegint l’habilitació a nivell d’aplicació.

Per provar-ho, primer pareu l’aplicació que tenia corrent el servei web (vegeu la figura).

Figura Parada de l’aplicació que té el servei web

I torneu-la a executar, tal com es mostra en la figura.

Figura Execució del servei web al port 9000 amb CORS

Si tot és correcte ja podem tornar a provar el client AJAX accedint a l’URL localhost:8080/resthellocorsioc/hellojquery.html amb un navegador, i ara sí que veureu la salutació ”Hello, World!!!” tornada pel servei web (vegeu la figura).

Figura Parada de l’aplicació que té el servei web

Noteu que afegir suport per a CORS a un servei web RESTful desenvolupat amb Spring és tan senzill com afegir l’anotació @CrossOrigin al servei.

El codi de la solució de la part client d’aquesta activitat el podeu descarregar del següent enllaç:

resthellocorsioc ( 3.6 KB )
.

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