hfwr )lq gh &duuhud ,qjhqlhutd gh...

81
Proyecto Fin de Carrera Ingeniería de Telecomunicación Aplicación web y servicio RESTful basado en JPA/Hibernate para ofrecer un servicio de fisioterapia a distancia Autor: Policarpo Caballero Peña Tutor: María Teresa Ariza Gómez Dep. Ingeniería Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2018

Upload: others

Post on 27-Jan-2021

6 views

Category:

Documents


0 download

TRANSCRIPT

  • Proyecto Fin de CarreraIngeniería de Telecomunicación

    Formato de Publicación de la Escuela TécnicaSuperior de Ingeniería

    Autor: F. Javier Payán Somet

    Tutor: Juan José Murillo Fuentes

    Dep. Teoría de la Señal y ComunicacionesEscuela Técnica Superior de Ingeniería

    Universidad de Sevilla

    Sevilla, 2013

    Proyecto Fin de CarreraIngeniería de Telecomunicación

    Aplicación web y servicio RESTful basadoen JPA/Hibernate para ofrecer un servicio defisioterapia a distancia

    Autor: Policarpo Caballero PeñaTutor: María Teresa Ariza Gómez

    Dep. Ingeniería TelemáticaEscuela Técnica Superior de Ingeniería

    Universidad de Sevilla

    Sevilla, 2018

  • Proyecto Fin de CarreraIngeniería de Telecomunicación

    Aplicación web y servicio RESTful basado enJPA/Hibernate para ofrecer un servicio de

    fisioterapia a distancia

    Autor:

    Policarpo Caballero Peña

    Tutor:

    María Teresa Ariza GómezProfesor Titular

    Dep. Ingeniería TelemáticaEscuela Técnica Superior de Ingeniería

    Universidad de SevillaSevilla, 2018

  • Proyecto Fin de Carrera: Aplicación web y servicio RESTful basado en JPA/Hibernate para ofrecerun servicio de fisioterapia a distancia

    Autor: Policarpo Caballero PeñaTutor: María Teresa Ariza Gómez

    El tribunal nombrado para juzgar el trabajo arriba indicado, compuesto por los siguientes profesores:

    Presidente:

    Vocal/es:

    Secretario:

    acuerdan otorgarle la calificación de:

    El Secretario del Tribunal

    Fecha:

  • A mi amigo Paco

  • Resumen

    Este proyecto describe el diseño e implementación de una aplicación web RESTful que proporcionaun servicio en línea de fisioterapia. Esta aplicación le permite a los pacientes leer instrucciones, verimágenes y ver vídeos sobre el tratamiento fisioterapéutico adecuado para su caso. También permite que losfisioterapeutas preparen y organicen estos materiales, y se los asignen a sus pacientes. Esta aplicación puedeser útil para proporcionar atención médica a personas que no pueden desplazarse a un centro médico, ya seapor su discapacidad o porque viven en lugares remotos.

    III

  • Abstract

    This project describes the design and implementation of a RESTful web application that provides anonline service of physiotherapy. This application allows patients to read instructions, see images andwatch videos about the physical therapy treatment recommended for their illnesses or injuries by a clinician.It also allows physical therapists to prepare and organize these materials, and to assign them to their patients.This application can be useful to provide assistance to people who cannot travel to a clinic, because of theirdisability or because they live in remote areas.

    V

  • Índice Abreviado

    Resumen IIIAbstract VÍndice Abreviado VII

    1 Introducción 11.1 Objetivos y justificaciones 11.2 Arquitectura de la solución 11.3 Contexto 21.4 Antecedentes 31.5 Estructura de la memoria 3

    2 Tecnologías empleadas 52.1 Tecnologías de la implementación 5

    2.2 Herramientas de desarrollo 11

    3 Aplicación en el servidor y API REST 153.1 La base de datos 153.2 La aplicación Java del servidor 16

    3.3 La API REST 253.4 Seguridad y control del acceso 28

    4 La aplicación HTML/Javascript del cliente 334.1 Funcionamiento de la interfaz 334.2 Organización del código Javascript 38

    5 Conclusiones y líneas de exploración para el futuro 45

    Apéndice A Apache Maven 47

    Apéndice B Obtención de un certificado HTTPS y configuración de HTTPS en Tomcat 51

    Apéndice C Instalación de la base de datos y configuración del acceso 53C.1 Configuración de la conexión desde Tomcat 53

    Índice de Figuras 55Índice de Tablas 57Índice de Códigos 59Bibliografía 61Índice alfabético 63Glosario 65

    VII

  • Índice

    Resumen IIIAbstract VÍndice Abreviado VII

    1 Introducción 11.1 Objetivos y justificaciones 11.2 Arquitectura de la solución 11.3 Contexto 21.4 Antecedentes 31.5 Estructura de la memoria 3

    2 Tecnologías empleadas 52.1 Tecnologías de la implementación 5

    2.1.1 Tecnologías en el servidor 5El servidor de aplicaciones Tomcat 6Java Api for RESTful Services (JAX-RS) 7Representational State Transfer (REST) 7Java Persistence API (JPA) 7La base de datos MariaDB 8

    2.1.2 Tecnologías empleadas en el cliente 8HTML 5 9Javascript 10Bootstrap 10JQuery 11

    2.2 Herramientas de desarrollo 112.2.1 Edición del código: Emacs 112.2.2 Compilación y empaquetado: Apache Maven 122.2.3 Depuración del código 132.2.4 Gestión de versiones: git 13

    3 Aplicación en el servidor y API REST 153.1 La base de datos 153.2 La aplicación Java del servidor 16

    3.2.1 Estructura de la aplicación web 16web.xml 17persistence.xml 18

    3.2.2 Funcionamiento de JAX-RS 183.2.3 Funcionamiento de JPA 20

    Mapeo ORM 20Manejo de entidades 22

    3.2.4 Estructura del código fuente 23

    IX

  • X Índice

    3.3 La API REST 253.3.1 Relación entre los recursos 27

    3.4 Seguridad y control del acceso 283.4.1 Método de autenticación 293.4.2 Restricciones de seguridad 293.4.3 Implementación de las restricciones 30

    4 La aplicación HTML/Javascript del cliente 334.1 Funcionamiento de la interfaz 33

    4.1.1 Elementos de la interfaz 334.1.2 Paseo por la interfaz 35

    4.2 Organización del código Javascript 384.2.1 El estado de la aplicación y el historial de navegación 394.2.2 Ejecución de las peticiones 404.2.3 Presentación de resultados 424.2.4 Manipulación del DOM 42

    5 Conclusiones y líneas de exploración para el futuro 45

    Apéndice A Apache Maven 47Estructura del fichero pom.xml 47

    Apéndice B Obtención de un certificado HTTPS y configuración de HTTPS en Tomcat 51

    Apéndice C Instalación de la base de datos y configuración del acceso 53C.1 Configuración de la conexión desde Tomcat 53

    Índice de Figuras 55Índice de Tablas 57Índice de Códigos 59Bibliografía 61Índice alfabético 63Glosario 65

  • 1 Introducción

    1.1 Objetivos y justificaciones

    El presente proyecto de fin de carrera tiene como objetivo realizar el diseño e implementación de unaaplicación web para ofrecer un servicio de asistencia fisioterapéutica a distancia. Esta aplicación estábasada en una arquitectura cliente-servidor, en la que un servidor Apache Tomcat ofrecerá una API Web detipo REST, que será consumida por una aplicación que se ejecutará en el navegador web del dispositivo delcliente. La aplicación web que se ejecuta en Apache Tomcat accederá a una base de datos MariaDB usandoJPA/Hibernate.

    El hecho de haber optado por crear una API RESTful hace que el servidor no tenga que guardar el estadode las sesiones (statelessness), lo cuál simplifica su implementación. Además, la interfaz resultante es muyuniforme y fácil de usar, especialmente por parte de una aplicación basada en Javascript.El hecho de usar JPA para acceder a la base de datos relacional automatiza las conversiones de datos

    necesarias para realizar transacciones, y demuestra ser una tecnología que se escala bien conforme una basede datos crece y se vuelve más compleja.

    El hecho de haber optado por una interfaz de cliente basada en HTML y Javascript le otorga a la aplicacióndel cliente de un alto grado de portabilidad, siendo posible usarla en distintos entornos tales como ordenadorespersonales, tabletas y teléfonos móviles; y no se requiere la instalación de ningún software adicional en eldispositivo desde el que se quiera usar. El uso del framework Bootstrap ayuda considerablemente a lograr quela aplicación web adapte su interfaz a las características de cada dispositivo, especialmente en lo concernientea los distintos tamaños de pantalla que pueden presentarse.

    1.2 Arquitectura de la solución

    La solución propuesta sigue un modelo cliente-servidor como se muestra en la figura 1.1.La aplicación que presta el servicio reside en un servidor Apache Tomcat. Dicho servidor Tomcat ha sido

    configurado para establecer una conexión con una base de datos MariaDB y la expone como una fuentede datos a las aplicaciones web que se encuentran desplegadas en él. La aplicación web hace uso de esafuente de datos mediante la librería Hibernate. La librería Hibernate ofrece a la aplicación web el servicio depersistencia a través de la API JPA.Por otra parte, la aplicación web ha creado una serie de recursos web disponibles para los usuarios a

    través del protocolo HTTP, y se encuentra recibiendo peticiones de los usuarios, procesándolas, y enviandolas respuestas. La librería a través de la cuál se ofrecen dichos recursos web y se canalizan las peticionesy respuestas se denomina Jersey. Jersey expone dicha funcionalidad a través de una API conocida comoJAX-RS.

    El cliente está constituido por una serie de ficheros HTML y Javascript que también están disponibles enel servidor Tomcat. Cuando el navegador web del usuario carga dichos documentos, el código Javascriptcrea una interfaz de usuario y cuando el usuario interactúa con dicha interfaz, el código Javascript envía laspeticiones necesarias al servidor a través del protocolo HTTP, y realiza la visualización de los resultadosobtenidos.

    1

  • 2 Capítulo 1. Introducción

    Figura 1.1 Diagrama de la aplicación.

    1.3 Contexto

    A finales del siglo XX y principios del XXI se ha producido en el mundo un desarrollo espectacular delas tecnologías de la información. Hoy en día la mayoría de las personas tienen en su bolsillo un teléfonointeligente con una capacidad computacional notable, capaz de conectarse a Internet y proporcionar acceso acontenidos multimedia, y los recientes avances en campos tales como la inteligencia artificial o la realidadvirtual indican que la revolución de la llamada sociedad de la información está lejos de acabar.

    En el contexto de una sociedad en la que la mayoría de las actividades económicas están relacionadas conla prestación de servicios, el empleo de medios telemáticos para la prestación de algunos de estos servicios adistancia es un campo que está en plena exploración. En particular, la prestación de servicios de fisioterapia adistancia puede beneficiarse del empleo de tecnologías telemáticas por las siguientes razones:

    • Las personas que necesitan esta clase de servicios frecuentemente tienen problemas de movilidad porlo que la realización de los ejercicios desde el hogar puede ser atractiva.

    • Aprender a realizar ejercicios fisioterapéuticos es una actividad que puede realizarse perfectamente através de medios audiovisuales, ya que es el sentido de la vista el que permite que el paciente identifiquey aprenda los movimientos que debe realizar.

    • El empleo de las tecnologías de la información abarata la prestación de los servicios, debido a losahorros en personal, instalaciones y transportes. Los pacientes pueden aprender por sí mismos muchasde las pautas del tratamiento que deben seguir, lo cuál conlleva una reducción en la cantidad deprofesionales necesarios.

    • El acceso a las tecnologías necesarias para la prestación de este servicio de manera telemática está hoyen día al alcance de todo el mundo gracias a la difusión de los teléfonos móviles inteligentes. Estosdispositivos permiten que el acceso al servicio sea fácil para el usuario y de bajo coste.

  • 1.4 Antecedentes 3

    1.4 Antecedentes

    En el departamento de Ingeniería Telemática de la Escuela Técnica Superior de Ingeniería de Sevilla variosalumnos ya han desarrollado proyectos de fin de carrera relacionados con la prestación de servicios defisioterapia a distancia.

    En nuestro caso el proyecto que guarda una mayor relación es el presentado por Jose María Valverde Baena[5].

    En dicho proyecto se desarrolla una aplicación RESTful para proporcionar acceso a la base de datos, y unaaplicación Android que hace uso de dicha API. La API REST permite leer la información requerida pararealizar los entrenamientos, crear usuarios y modificar sus datos personales.

    La diferencia con nuestro proyecto radica en que la API aquí creada permite la edición de toda la informaciónexistente en la base de datos, incluyendo los ejercicios y rutinas; y dicha API no es consumida por unaaplicación Android, sino por una aplicación web basada en HTML y Javascript, lo cuál la dota de mayorportabilidad. La aplicación Javascript se adapta al tipo de cuenta de usuario, de tal manera que un usuarioadministrador del sistema podrá hacer todos los cambios que considere oportunos, mientras que un usuariode tipo cliente, tendrá una capacidad muy limitada para hacer cambios.

    1.5 Estructura de la memoria

    A continuación, explicaremos brevemente la estructura del presente documento.En el primer capítulo de tipo introductorio se expone la aplicación desarrollada, el objetivo de la aplicación,

    su estructura y el contexto en el que se ha llevado a cabo.Pasamos entonces, a un segundo capítulo donde se enumeran de las distintas tecnologías sobre las que

    se fundamenta la solución propuesta, así como, las tecnologías usadas para su desarrollo. Debido a lagran cantidad de tecnologías involucradas, solamente haremos una breve mención de ellas, indicando susprincipales características o funcionalidades.En el tercer capítulo explicaremos en profundidad el funcionamiento de la parte de la aplicación que se

    ejecuta en el servidor y documentaremos la API REST implementada a través de la cuál se presta el servicio.Veremos también cómo se hace uso de JAX-RS para definir la API REST, y cómo se realizan las operacionessobre la base de datos mediante JPA/Hibernate. Comentaremos también algunos aspectos sobre la seguridaddel sistema del sistema.

    En el cuarto capítulo se expondrá como se consume la API REST por parte del cliente, y el funcionamientode la interfaz gráfica que ven los usuarios de la aplicación.

    El capítulo quinto será breve y estará dedicado a llevar a cabo algunas reflexiones sobre el trabajo realizado,y presentar cuáles podrían ser algunas líneas de trabajo interesantes para explorar en el futuro.

    Finalmente, cerraremos la presente memoria con varios apéndices, donde el lector podrá encontrar infor-mación más detallada sobre algunos aspectos del desarrollo de menor importancia.

  • 2 Tecnologías empleadas

    En este capítulo expondremos las tecnologías sobre las que se apoya la aplicación desarrollada, tanto en laparte del servidor como en la parte del cliente; y aquellas que han sido empleadas para llevar a cabo eldesarrollo de la misma.

    2.1 Tecnologías de la implementación

    A continuación explicaremos cuáles han sido las tecnologías sobre las que se ha basado la implementaciónpropuesta.

    2.1.1 Tecnologías en el servidor

    Como ya hemos explicado la arquitectura de la aplicación web está basada en el paradigma cliente-servidor,donde la interfaz de comunicación entre el cliente y el servidor será una Application Programming Interface(API) RESTful. El servidor está constituido por una aplicación Java que se ejecuta dentro de un servidor deaplicaciones Apache Tomcat, y por una base de datos MariaDB. El cliente está constituido por un conjuntode documentos HTML, código Javascript y hojas de estilo CSS, que son servidos por el servidor y que sevisualizan o ejecutan en el navegador web del usuario.

    El componente fundamental del servidor es el servidor de aplicaciones Apache Tomcat. Esta aplicación esel único elemento del servidor al que el cliente tiene acceso y es el que interconecta los demás elementos delservidor.Dentro del servidor Tomcat se encuentra desplegada nuestra aplicación Java, que fue enviada al servidor

    por el desarrollador o el administrador del sistema en el formato WAR, el cuál es en realidad el formato JARcon una extensión diferente y una cierta jerarquía en el sistema de ficheros. La aplicación web está compuestapor una serie de clases Java donde está contenida toda la lógica de negocio del servidor y por tanto el controldel flujo de mensajes tanto con los clientes como con la base de datos. La interfaz con la base de datos selleva a cabo mediante la API de persistencia JPA, mientras que la interacción con los clientes se realiza através de la API para servicios web RESTful JAX-RS.El otro gran pilar del entorno de ejecución en el servidor lo constituye la base de datos MariaDB. La

    misión de este elemento es la de proporcionar persistencia de la información de la lógica de negocio.Por tanto, las tecnologías claves sobre las que se basa el servidor son:

    • Máquina virtual de Java

    • Servidor de aplicaciones

    • JAX-RS

    • JPA

    • Base de datos relacional

    En la figura 2.1 se muestra un esquemático que ilustra las relaciones entre las tecnologías involucradas.Obsérvese que estos elementos son interfaces o grupos funcionales, y que en ningún caso estamos restrin-

    gidos a una determinada implementación o a un determinado proveedor. Gracias al uso de unas interfaces

    5

  • 6 Capítulo 2. Tecnologías empleadas

    Figura 2.1 Tecnologías del servidor.

    bien definidas mantenemos la capacidad para reemplazar una implementación por otra, según pudiera serventajoso de acuerdo a criterios de eficiencia, rendimiento, facilidad de uso, etc.

    En nuestro caso, la selección de implementaciones ha venido dada por la familiaridad con las herramientas,y la conveniencia en cuanto a documentación y disponibilidad del producto.

    El sistema operativo donde se ejecutará la aplicación web será Debian GNU/Linux 9 Stretch, un sistemaoperativo estable y seguro, y bien conocido por parte del autor. El sistema Debian proporciona unos ampliosrepositorios de software que facilitan la instalación de librerías y programas.

    La selección de máquina virtual de Java ha sido OpenJDK 8, que es la implementación de Java usada pordefecto en el sistema Debian.La selección de servidor de aplicaciones ha sido Apache Tomcat 8. Es un servidor web con buena

    documentación, disponible en los repositorios de Debian y bien integrado con el sistema de organización dedemonios del sistema Systemd.

    La selección de proveedor de JAX-RS ha sido Jersey. Jersey es la implementación de referencia de JAX-RSy cuenta con una gran documentación.

    La selección de proveedor de JPA ha sido Hibernate. Hibernate fue creado antes de que existiera JPA, y portanto proporciona su propia API específica. Nosotros, sin embargo, hemos preferido usar la implementaciónque Hibernate proporciona de la API JPA, la cual no difiere excesivamente de la API propietaria de Hibernate,y de esa manera conseguimos una mayor libertad.

    La implementación de base de datos relacional ha sido MariaDB, que es un fork de MySQL. MariaDB esuna base de datos bien integrada en el sistema Debian, y con conectores JDBC disponibles para Tomcat.

    El servidor de aplicaciones Tomcat

    Apache Tomcat fue desarrollado inicialmente por Sun Microsystems como la referencia de implementaciónde las tecnologías Java Servlet y Java Server Pages. Fue donado en 1999 a la fundación Apache y hoy en díaes mantenido y desarrollado por multiples voluntarios y organizaciones de todo el mundo.La aplicación que se ejecuta en el servidor es una aplicación web desarrollada en el lenguaje de progra-

    mación Java. Esta aplicación está compuesta por una serie de componentes web que son desplegados enun servidor de aplicaciones. El servidor de aplicaciones proporciona a los componentes web un entorno deejecución que les permite acceder a las distintas facilidades del servidor. A este entorno de ejecución se le

  • 2.1 Tecnologías de la implementación 7

    Figura 2.2 Logotipo de Apache Tomcat.

    denomina contenedor web. Los componentes web desplegados en el servidor realizan la prestación de losservicios web que tienen asignados a través de una API conocida como la tecnología de Servlets de Java.JAX-RS

    La tecnología de Servlets constituye, por tanto, la interfaz básica para crear un servicio web en el mundo Java.No obstante, para la creación de servicios web de tipo REST existe otra API de más alto nivel, construidasobre la base proporcionada por los Servlets, que se denomina . Es sobre esta API, sobre la que se construyenlos componentes web que conforman la aplicación web en el servidor.La API Java Api for RESTful Services (JAX-RS) se fundamenta en un conjunto de anotaciones que

    permiten a la aplicación, por una parte indicar qué métodos de qué clases van a procesar las invocaciones, ypor otra parte establecer la correspondencia entre los parámetros de entrada y salida de la función con lasentradas y salidas de la API REST. Cuando se explique en detalle el funcionamiento de la aplicación web severán detalle estas anotaciones.

    Como ya se comentó en el capítulo introductorio, la implementación de JAX-RS empleada es Jersey, porser la implementación de referencia y contar con buena documentación.REST

    REST no es realmente en sí mismo una tecnología sino un paradigma de programación web. REST fuedefinido por Roy Thomas Fielding, uno de los padres del protocolo HTTP, en su tesis doctoral tituladaArchitectural Styles and the Design of Network-based Software Architectures [1].

    La idea fundamental de un servicio web REST es la de permitir el acceso y manipulación de unos recursosweb identificados por URIs (Uniform Resource Identifier), mediante un conjunto reducido de operacionesdefinidas en el protocolo HTTP, tales como GET (obtener), POST (crear), PUT (editar) y DELETE (eliminar).Una característica fundamental de REST es que estas operaciones no tienen estado (statelessness). Con

    esto se quiere decir que cada petición del cliente contiene toda la información necesaria para la prestacióndel servicio, y que el estado de la sesión es guardado en el cliente, el cuál deberá usarlo para generar suspeticiones. Las respuestas a estas peticiones serán representaciones textuales de los recursos web en formatostales como JSON, XML, u otros.Otra idea asociada con el paradigma REST es que los recursos web deben estar enlazados entre sí de tal

    manera el usuario de la API REST pueda en cierta manera “navegar” por la API. A este principio se le conocecomo Hypermedia as the Engine of Application State (HATEOAS).JPA

    La prestación del servicio web requiere que la aplicación web en el servidor almacene información que seráofrecida a través de los recursos web. Esta información será almacenada en una base de datos relacional,que la guardará en una serie de tablas. Sin embargo, la representación más cómoda de esta informaciónpara los componentes web es en forma de objetos. Para realizar de una forma cómoda el paso de datos deuna base de datos relacional a objetos Java y viceversa, usaremos una API denominada . Java PersistenceAPI (JPA) fue definida por el Java Community Process en la JSR 338, con el objetivo de unificar diversassoluciones existentes tales como EJB 2 CMP, JDO, Hibernate, y TopLink. Esta especificación ha tenidobastante éxito, y hoy en día es considerada el estándar a la hora de establecer la correspondencia entre objetosy datos relacionales (ORM, Object to Relational Mapping).

    JPA es tan solo una especificación de una API. Para poder hacer uso de ella necesitamos una implementación.La implementación usada es Hibernate, que también cuenta con otra API alternativa específica que ofrecealgo más de funcionalidad a costa de perder portabilidad. Esa funcionalidad adicional como pueden ser losgeneradores de identificadores extendidos, las entidades inmutables, o la API para fechas y tiempos, no es lo

  • 8 Capítulo 2. Tecnologías empleadas

    suficientemente importante como para justificar la pérdida de portabilidad consiguiente y por tanto hemosoptado por usar su API JPA.

    La base de datos MariaDB

    La base de datos es el elemento que le proporciona a la aplicación web la capacidad de persistir la información.La aplicación web hará uso de esta capacidad a través de la capa JPA que ya ha sido discutida.Debido al aislamiento que JPA proporciona con respecto a la base de datos, la elección de la base datos

    está en realidad muy abierta, y no condicionará el código resultante dentro de la aplicación web, siendoposible el migrar de una base de datos a otra si fuera necesario. La elección de la base de datos puede, portanto, estar basada en factores tales como la experiencia anterior con bases de datos, o la disponibilidad deherramientas y documentación. En nuestro caso la base de datos usada ha sido MariaDB, que es un “fork” deMySQL. Este “fork” fue creado algo después de que MySQL fuera comprada por Oracle, y su propósito fueel de asegurar que el software permanecería bajo la licencia GNU GPL.

    Figura 2.3 Logotipo de MariaDB.

    2.1.2 Tecnologías empleadas en el cliente

    La parte de la aplicación que se ejecuta en el dispositivo del cliente, ya sea este un paciente, un entrenador,o un administrador del servicio, es fundamentalmente la misma. Se trata de una aplicación en el lenguajeECMAScript, también conocido como Javascript, que se ejecuta en el navegador web del usuario. El navegadorweb proporciona APIs, tales como Asynchronous Javascript and XML (AJAX) o el Document Object Model(DOM) API, que permiten que la aplicación pueda invocar operaciones REST sobre el servidor, y permite lacreación de una interfaz gráfica de usuario capaz de soportar contenidos multimedia. Estas APIs facilitan eldesarrollo de una aplicación portable capaz de dar soporte a una enorme diversidad de sistemas operativoscon un mismo código de base.Las APIs y frameworks usados por la aplicación cliente son:

    DOM API Permite la manipulación del HTML DOM (Document Object Model), de tal manera que la páginaweb deja de ser un documento estático, y se convierte en la interfaz gráfica de la aplicación.

    AJAX Permite que la aplicación pueda invocar operaciones REST, sin forzar la recarga de toda la páginaweb.

    Bootstrap Es un framework que ayuda a crear interfaces de usuario gracias a una serie de componentes,estilos y layouts que incorpora.

    JQuery Es un framework para Javascript que proporciona una interfaz alternativa para acceder a la fun-cionalidad de otras APIs web, tales como DOM o AJAX, con las ventajas de que facilita el soportea navegadores webs antiguos o incompatibles, y proporciona una interfaz más ergonómica para elprogramador. En nuestra aplicación ha sido usado principalmente por ser un prerrequisito de Bootstrap.

  • 2.1 Tecnologías de la implementación 9

    History API Permite que la aplicación interactúe correctamente con la funcionalidad de manejo del historialde navegación que ofrecen los navegadores web (Botones de ir hacia delante y hacia atrás en el historial).

    HTML 5 La versión del estándar HTML publicada por el W3C en 2014 añade algunos tags HTML nuevos,como por ejemplo que permiten ofrecer contenido multimedia sin necesidad de recurrir aplugins o extensiones externas.

    Una tecnología que no tiene la consideración de API o framework, pero que desempeña un papel importantees JavaScript Object Notation (JSON). Es un formato para la transmisión de estructuras de datos basado en lasintaxis del lenguaje Javascript. Las invocaciones AJAX solían usar XML como lenguaje para dar formato alos datos, pero hoy en día lo más usual en todas las APIs RESTful es emplear JSON. JSON tiene una sintaxismás fácil de procesar, está soportado por los navegadores web y es más compacto que XML.La aplicación del cliente es la parte de la aplicación web que se ejecuta en el navegador web del cliente

    y permite que el cliente pueda acceder a la funcionalidad proporcionada por el servidor a través de la APIREST. Esta funcionalidad incluye la creación, lectura, modificación y borrado de la información contenidaen la base de datos sobre ejercicios fisioterapéuticos.

    Cuando hablamos del “cliente” nos estamos refiriendo tanto a los administradores del sistema, como a losentrenadores o profesionales fisioterapeutas, como a los pacientes o personas que desean realizar un entrena-miento. La API REST distingue entre estos tres tipos de usuarios y proporciona distintas funcionalidadessegún el tipo de usuario.La aplicación que se ejecuta en el navegador web de los usuarios, ya sean estos clientes, entrenadores,

    o administradores, se trata de una aplicación programada en Javascript. Cuando los usuarios abran en sunavegador web una cierta URL, el navegador web se descargará un conjunto de documentos HTML, Javascript,CSS e imágenes, que son los elementos que componen la aplicación.

    Aunque nosotros hemos optado por usar la misma instancia de Apache Tomcat para ofrecer estos recursoswebs, es perfectamente posible desplegar dichos recursos en cualquier otro tipo de servidor web en otramáquina distinta. Desde el punto de vista del servidor, la aplicación del cliente no es más que un conjuntode recursos estáticos disponibles en algunas URLs. Las URLs que aparecen dentro los documentos HTMLy Javascript siempre son relativas, de tal manera que únicamente es necesario que el servidor preserve laposición relativa de los recursos.En este capítulo explicaremos las principales tecnologías usadas para implementar la aplicación cliente.

    HTML 5

    HTML es el lenguaje de marcado para la creación de páginas web. Fue creado en los años ochenta en elCERN, y posteriormente estandarizado inicialmente por el IETF, y posteriormente por el W3C. En 2014 sepublicó la versión 5 de HTML con importantes novedades.

    Figura 2.4 Logotipo de HTML 5.

    La principal característica de HTML 5 requerida por la aplicación web el tag que permite lareproducción de videos en el navegador web sin necesidad de complementos externos. Otro tag usado pornuestra aplicación, aunque menos importante, es que está pensado para contener enlaces de navegación.

    En la aplicación web se usa HTML de dos maneras diferentes. Por un lado tenemos dos documentos HTMLestáticos: welcome.html y main.html. El primero sirve como lugar de llegada para los usuarios no registradosen el sistema, el segundo es el punto de entrada para los usuarios registrados. Por otro lado tenemos el HTMLcreado de forma dinámica desde Javascript. Este es el que constituye el grueso de la interfaz de la aplicación.

    La necesidad de crear el HTML de forma dinámica se debe al hecho de que los datos que son visualizadosmediante dicho HTML, solamente están disponibles después de ser obtenidos mediante la API RESTful.

  • 10 Capítulo 2. Tecnologías empleadas

    Sería posible generar en el servidor el HTML con los datos ya insertados, pero en tal caso no podríamosdemostrar el funcionamiento de API RESTful creada.

    Javascript

    El lenguaje de programación Javascript fue creado en 1995 por Brendan Eich para servir como lenguaje descripting dentro del navegador web Netscape Navigator, con el propósito de permitir la creación de páginasweb dinámicas e interactivas. Posteriormente, el organismo de estandarización Ecma ha aprobado variasnormas que definen el lenguaje de programación ECMAScript, que es el nombre que fue elegido entre losparticipantes en el proceso de estandarización como una solución de compromiso. No obstante, es lo másfrecuente es usar el nombre Javascript para referirse al lenguaje ECMAScript, y nosotros así lo haremos.

    Existen un total de ocho ediciones del estándar ECMAScript, siendo la quinta de 2009, la sexta de 2015, laséptima de 2016 y la octava de 2017. A día de hoy, el grado de compatibilidad de los principales navegadoresweb con los estándares de 2009 y 2015 es altísimo e implementan casi todas las nuevas característicasintroducidas en dichas normas, mientras que los estándares de 2016 y 2017 aún no han sido adoptados engran medida. Nosotros hemos optado por usar las APIs y características del lenguaje definidas en la quintaversión de ECMAScript, usando en algunas ocasiones características de la sexta versión si dicha característicaestá implementada en los siguientes navegadores web: Firefox, Chrome, Safari y Edge.Las principales características de ECMAScript 5 de las que hemos hecho uso han sido:

    • Modo estricto, que se activa colocando la cadena de caracteres “use strict” al principio de cada archivo,para que el lenguaje sea menos laxo y lance excepciones en más casos.

    • La función Array.prototype.forEach para iterar sobre objectos Array.

    • Las funciones JSON.parse y JSON.stringify para realizar las conversiones de objetos de Javascript aJSON y viceversa.

    La única característica de ECMAScript 6 de las que hemos hecho uso han sido los nuevos objetos tipo Set.En su lugar, podríamos haber usado las claves de un objeto Javascript a modo de set, pero de esta manera elcódigo es más elegante y todos los navegadores web relevantes implementan esta parte de la API.Al margen de estas características relativamente recientes de Javascript, las APIs fundamentales sobre

    las que se apoya la aplicación son de dos naturalezas: APIs definidas por el estándar ECMAScript y APIsproporcionadas por librerías o frameworks de terceros. Entre las primeras destacan la API para la manipulacióndel DOM, la API AJAX y la History API. Entre las segundas, encontramos JQuery.

    Bootstrap

    Bootstrap es un framework HTML/CSS/Javascript que facilita la creación de interfaces de usuario másconsistentes, proporcionando una serie de componentes tales como barras de navegación, diálogos modales,menús, etc.

    Figura 2.5 Logotipo de Bootstrap.

    Para usar bootstrap es necesario que añadamos a nuestros documentos la hoja de estilo de bootstrap, eincluyamos un elemento script apuntando a una copia del fichero Javascript de bootstrap. La forma de haceruso de los componentes generalmente consiste en asignar determinados classNames a los elementos HTML.

  • 2.2 Herramientas de desarrollo 11

    JQuery

    JQuery es una librería Javascript que proporciona una interfaz más fácil de usar para realizar las tareasmás convencionales de Javascript, tales como manipulación del DOM o AJAX. En la aplicación web, hasido usado a la hora de realizar invocaciones AJAX de una manera ligeramente más concisa. Es además unprerrequisito del framework Bootstrap.

    Figura 2.6 Logotipo de JQuery.

    Para incluir JQuery en la aplicación es necesario que añadamos un elemento script apuntando al ficheroJavascript de JQuery. Toda la funcionalidad de JQuery estará accesible a través del objecto global con nombreJQuery. Un nombre alternativo para este objeto es “$” que es un carácter que no tiene ningún significadoespecial para Javascript y permite que el uso de la librería sea mucho más conciso.

    2.2 Herramientas de desarrollo

    El entorno de desarrollo está formado por el conjunto de herramientas usadas en la creación del códigofuente, y en la compilación, depuración y organización de dicho código.

    2.2.1 Edición del código: Emacs

    La herramienta elegida para coordinar las herramientas que componen el entorno de desarrollo y queproporciona una interfaz conveniente para interactuar con cada una de ellas ha sido el editor de texto GNUEmacs1, debido a ser una herramienta personalizable y extensible con la que el autor está familiarizado.

    Figura 2.7 Logotipo de Emacs.

    Emacs es un editor de texto desarrollado por el Richard Stallman, fundador del proyecto GNU, que ademásde ser un buen editor para muchos lenguajes de programación, es programable en el lenguaje Emacs Lisp,lo que le permite ser usado como una herramienta versátil de procesamiento de la información capaz deadaptarse a otras herramientas de desarrollo.Efectivamente, las otras herramientas fundamentales involucradas en el desarrollo de la aplicación han

    sido Apache Maven para compilar el código, empaquetarlo y desplegarlo; el depurador jdb; y la herramientade control de versiones git. Para todas y cada una de estas herramientas hemos encontrado complementospara Emacs que facilitan el uso de dichas herramientas.

    Emacs es un programa complejo, con un gran número de funcionalidades, cuyo funcionamiento no podemosexplicar en este documento, así que tan solo mencionaremos algunas características que fueron especialmenteútiles.1 https://www.gnu.org/ software/ emacs/

    https://www.gnu.org/software/emacs/

  • 12 Capítulo 2. Tecnologías empleadas

    Emacs posee soporte para una gran cantidad de lenguajes de programación. Los dos principales tipos decódigos fuente con los que se ha trabajado en el proyecto han sido Java y Javascript. El primero ha sido ellenguaje de programación usado para implementar la aplicación en el servidor que ofrece el servicio REST,mientras que Javascript ha sido el lenguaje de programación de la aplicación del cliente, que consume laAPI REST. Aunque estos lenguajes de programación suponen la mayor parte del código, también ha sidonecesario utilizar otros lenguajes de marcado, como XML y HTML, de estilo, como CSS, o de propósitoespecífico, SQL. Para todos estos lenguajes, emacs ofrece edición de código que tiene en cuenta la sintaxisdel lenguaje. En el caso particular de Java, herramientas como Eclipse poseen potentes capacidades paracompletación y refactorización del código que pueden ser aprovechadas desde emacs mediante el plugin paraemacs llamado Eclim. La principal característica de Eclim que fue aprovechada en el desarrollo del proyectofue la de mover clases de unos paquetes a otros.

    Una dificultad que podía presentarse en cuanto a los lenguajes de programación es la edición de código deun lenguaje de programación dentro de un fichero de otro lenguaje de programación. Esto puede suceder, porejemplo, cuando insertamos un elemento con código Javascript dentro de un documento HTML, ocuando escribimos sentencias SQL en un literal de tipo cadena de caracteres en el código Java. Este problemafue evitado simplemente manteniendo el código Javascript en sus propios ficheros, pero podemos mencionarque emacs ofrece una solución para estas situaciones mediante el modo MMM que permite que múltiplesmodos mayores puedan coexistir en un mismo buffer.Otro problema que surge al editar código es el de localizar los archivos y moverse de unos a otros,

    especialmente cuando las rutas en el sistema de ficheros son muy largas. En particular, un proyecto gestionadocon Apache Maven debe seguir una determinada jerarquía de directorios a la hora de ubicar los ficheros decódigo fuente y el compilador de Java, javac, también requiere que las clases que forman parte de un paquetede java se encuentren en unos determinados directorios. Estos factores terminan provocando que las rutasde los archivos de código fuente puedan ser bastante largas, dificultando el acceso a los mismos. Emacscuenta con los plugins projectile y helm que facilitan enormemente la localización de los ficheros. El pluginprojectile crea una lista de los ficheros que componen el proyecto a partir de la información proporcionadapor git. El plugin helm ofrece una funcionalidad de búsqueda “fuzzy” sobre los resultados proporcionadospor projectile, de tal manera que podemos saltar a cualquier archivo del proyecto con muy pocas pulsacionesdel teclado.

    2.2.2 Compilación y empaquetado: Apache Maven

    La herramienta de desarrollo básica de Java es el JDK, que incluye el compilador de Java javac. Estaherramienta solamente proporciona la capacidad de generar bytecode para la máquina virtual de Java (JVM),a partir del código fuente de una clase. No es por tanto capaz de determinar las dependencias que puedenexistir entre unas partes del código y otras, o cuando una determinada clase necesita ser recompilada.Por tanto es necesario una herramienta que se encargue de organizar la compilación del código. Existen

    diversas herramientas populares para este fin como por ejemplo Make, Ant y Maven. Esta última ofrece unaenorme ventaja con respecto a las otras dos, que es la de poseer un sistema de repositorios para la instalaciónde dependencias y por tanto poder funcionar como un sistema de paquetes.Apache Maven surgió dentro del proyecto Jakarta Alexandria a principios de la década 2000, y sus

    principales innovaciones con respecto a Ant son el uso de una jerarquía estándar de directorios y la gestiónde dependencias. La filosofía de Maven es la de primar las convenciones frente a la configurabilidad, de talmanera que todos los proyectos Maven sean más homogéneos y fáciles de gestionar.

    Figura 2.8 Logotipo de Maven.

    Las funciones fundamentales que Maven ha desempeñado en el desarrollo de la aplicación han sido la deinvocar al compilador de Java, empaquetar la aplicación en el format WAR, y desplegar la aplicación en elservidor Tomcat. Para invocar con mayor comodidad a Maven, se creó además un pequeño Makefile, con elpropósito de guardar allí el comando bajo el cual hay que invocar a Maven.

    Otra característica notable de Maven que también fue aprovechada durante el desarrollo de la aplicación esla capacidad para crear los ficheros de proyecto para Eclipse de tal manera que sea posible realizar algunas

  • 2.2 Herramientas de desarrollo 13

    tareas de refactorización del código con Eclipse, mientras que el proyecto sigue estando gestionado porMaven y no por Eclipse, con la flexibilidad que esto aporta.

    2.2.3 Depuración del código

    Otra necesidad habitual en el desarrollo de una aplicación es la de depurar los errores que existan en lamisma. Para ello, el OpenJDK proporciona el depurador jdb, herramienta muy capaz pero con una interfazinadecuada. Emacs corrige este defecto mediante el modo GUD (Grand Unified Debugger) que permite ponerbreakpoints sobre el propio código fuente, y la inspección de los contenidos de las variables haciendo clickcon el ratón.

    El código Javascript no necesita de ninguna fase de compilación, pero también requiere de herramientas dedepuración. En este caso, los navegadores web Firefox y Chrome incluyen herramientas para desarrolladoresweb que permiten realizar la depuración de la aplicación mediante una interfaz muy cómoda y práctica.

    2.2.4 Gestión de versiones: git

    En el desarrollo de una aplicación de cierto volumen es normal que surja cierto temor a realizar grandescambios o experimentos por el temor a no poder deshacer dichos cambios. Poseer una herramienta de gestiónde versiones del código como git, da una mayor libertad de creación ya que permite ir guardando todo elhistorial de cambios del proyecto. Estas herramientas son también útiles para realizar copias de seguridad delcódigo de una forma rápida y simple. Emacs posee la capacidad de interactuar con git mediante el excelentepaquete Magit.

    Figura 2.9 Logotipo de Git.

  • 3 Aplicación en el servidor y API REST

    En este capítulo explicaremos las distintas partes de la aplicación que se ejecutan en los servidores y hacenposible la prestación del servicio: la base de datos MariaDB y la aplicación Java dentro de Tomcat.La interfaz de comunicación entre la aplicación Java del servidor y la aplicación Javascript del cliente es laAPI RESTful, a la que también se dedicará una sección dentro de este capítulo. Finalizaremos el capítuloanalizando el funcionamiento de la aplicación en cuanto a seguridad y el control del acceso a la API.

    3.1 La base de datos

    Puesto que se pretende ofrecer un servicio de fisioterapia, la información fundamental que debemos almacenaren la base de datos es la relativa a los ejercicios o entrenamientos que los usuarios deben llevar a cabopara mejorar su condición. La información básica relativa a estos ejercicios residirá en una tabla quedenominaremos ejercicios.

    Debido a que frecuentemente habrá múltiples ejercicios que sirvan para un mismo propósito, es deseableque los ejercicios puedan ser agrupados en forma de rutinas. Por lo tanto tendremos también una tablallamada rutinas que guardará una relación “muchos a muchos” con la tabla ejercicios, ya que una rutinapuede contener múltiples ejercicios, y es posible que un mismo ejercicio aparezca en distintas rutinas.La realización de un ejercicio puede requerir en algunas ocasiones algún instrumento o utensilio, como

    puede ser una pelota o una cuerda. La información sobre estas herramientas residirá en la tabla utiles queguardará una relación “muchos a muchos” con ejercicios puesto que un ejercicio puede involucrar múltiplesutensilios y un mismo utensilio puede servir para llevar a cabo distintos ejercicios.

    Al realizar un ejercicio fisioterapéutico intervendrán distintos músculos del cuerpo; y un mismo músculopuede ser entrenado mediante distintos ejercicios. Por tanto, tendremos otra tabla llamada musculos quetambién guardará una relación “muchos a muchos” con ejercicios.Para ayudar a la realización del ejercicio se pueden proporcionar diversos materiales audiovisuales que

    faciliten la comprensión del entrenamiento. Esta información estará guardada en la tabla recursos. Nuevamentetenemos una relación “muchos a muchos”, ya que un mismo material audiovisual puede ser adecuado paramúltiples ejercicios, y para un mismo ejercicio puede haber varios materiales recomendables.

    La tabla recursos tan solo guardará la URL del recurso y una descripción del mismo. Para que sea posibleque materiales audiovisuales puedan estar guardados íntegramente en el servidor local, proporcionaremosuna tabla llamada multimedia donde pueden estar guardados. Obsérvese que no existe una relación directaentre la tabla recursos y la tabla multimedia a través de la URL, ya que deseamos que también sea posibleusar URLs externas.Finalmente, debemos guardar información acerca de los usuarios del servicio, los entrenadores y los

    administradores. Para ello crearemos las tablas usuarios y rolesdeusuarios. La primera contiene informaciónpersonal sobre cada usuario y guarda una relación “muchos a muchos” con la tabla rutinas, ya que a un mismousuario le pueden corresponder varias rutinas, y una misma rutina puede ser usada por varios usuarios. Latabla rolesdeusuarios indica los distintos roles que un usuario puede poseer, y por tanto existe una relación“uno a muchos” entre usuarios y rolesdeusuarios.

    En la figura 3.1 se presenta un diagrama de la base de datos, con los nombres de las tablas, sus columnas ylas relaciones entre ellas.

    15

  • 16 Capítulo 3. Aplicación en el servidor y API REST

    Figura 3.1 Diagrama de la base de datos.

    En cuanto al contenido de cada una de las tablas, no parece que sean necesarias demasiadas explicaciones.En casi todos los casos tenemos un campo “nombre” o “título” pensado para identificar el elemento de caraal usuario. También, suele existir un campo descripción que proporciona información detallada en formatotexto acerca del elemento en cuestión. Otro campo que suele estar presente es “url” o “urlfoto” que contienela URL de la imagen asociada al recurso.

    El diseño de esta base de datos ha sido ha realizado de forma que sea similar al empleado en otros ProyectosFin de Carrera que han sido desarrollados en los años pasados en el departamento de Ingeniería Telemáticade la ETSI de la Universidad de Sevilla, de forma que los materiales audiovisuales empleados en la base dedatos, para los cuáles pueden existir restricciones sobre su uso y distribución, puedan ser reutilizados.

    3.2 La aplicación Java del servidor

    En esta sección veremos el funcionamiento de la aplicación web en el servidor. Para ello, primero examinare-mos la estructura de una aplicación web y cuáles son sus componentes. A continuación, veremos los paquetesJava que componen la aplicación, las interacciones existentes entre los mismos, y como la aplicación haceuso de las dos grandes APIs sobre las que se basa: JPA y JAX-RS.

    3.2.1 Estructura de la aplicación web

    Una aplicación web es básicamente un conjunto de ficheros colocados de acuerdo a una determinada jerarquíaen el sistema de ficheros. Estos archivos son transferidos al servidor dentro un archivo jar, que en lugar deusar la extensión jar, usa la extensión war (Web Application Archive).Los archivos contenidos dentro del fichero war pueden ser clasificados en dos tipos: aquellos que deben

    ser directamente accesibles por los usuarios de la aplicación web; y los archivos que son necesarios para elfuncionamiento interno de la aplicación, pero que no deben ser accesibles desde el exterior.

    Dentro del archivo war estos dos tipos de archivos están claramente separados. Los archivos que no debenser accesibles por los usuarios deben ser colocados dentro de una carpeta llamada WEB-INF, ubicada en eldirectorio raíz del war.Los principales contenidos del directorio WEB-INF son:

  • 3.2 La aplicación Java del servidor 17

    • El fichero web.xml, denominado el descriptor de desplegado (deployment descriptor). Este archivole proporciona al servidor información de desplegado, como por ejemplo qué servlets contiene estaaplicación, en que rutas deben ser colocados, etc.

    • El directorio jsps que contiene la Java Server Pages. En nuestro caso no existe ya que no usamos estatecnología.

    • El directorio lib, contiene ficheros jars necesarios para la ejecución de esta aplicación.

    • El directorio classes, contiene los ficheros .class que componen esta aplicación.

    Como ya hemos mencionado, todos los demás archivos que estén fuera de este directorio estarán disponiblesa través del protocolo HTTP. Estos archivos incluyen fundamentalmente los documentos HTML, Javascript yCSS que conforman la aplicación del cliente.

    La creación del fichero war que contiene la estructura de ficheros descrita anteriormente es realizada por laaplicación Apache Maven, a partir de los contenidos de la carpeta src en el directorio raíz de nuestro códigofuente. Este proceso consiste fundamentalmente en tres pasos:

    • copiar los contenidos de las carpetas src/main/webapp y src/main/resources a la raíz de la estructura deficheros del archivo war.

    • copiar los ficheros .class generados al compilar el código fuente a la carpeta WEB-INF/classes.

    • copiar los ficheros .jar que contienen las librerías sobre las que depende nuestro código, en el directorioWEB-INF/lib.

    Este proceso de creación del fichero war que acabamos de describir es realizado por maven en la fasepackage, después de la fase compile.

    La manera en la que el desarrollador comunica a maven cómo se debe crear la aplicación es por tanto tansimple como colocar el código Java de la aplicación en la carpeta src/main/java y el resto de documentos ensrc/main/webapp.Una vez descrita la estructura de una aplicación y como se crea, analicemos ahora los componentes

    fundamentales que son tres:

    • El descriptor de desplegado web.xml

    • El fichero de configuración de JPA/Hibernate persistence.xml

    • El código Java de la aplicación

    web.xml

    El fichero web.xml es un documento XML que sirve para transmitir al servidor de aplicaciones (en este casoTomcat) información acerca de como configurar los recursos webs contenidos en la aplicación web. Ennuestro caso esto ha consistido fundamentalmente en mapear las URLs a las clases JAX-RS que hemosdefinido, en definir la página de inicio de la aplicación, y establecer las restricciones de seguridad de lasURLs asociadas a nuestros recursos web.Es de destacar que en este archivo no están contenidas las asociaciones entre URLs y recursos web, ya

    JAX-RS define un sistema de anotaciones para este propósito que será descrito cuando veamos JAX-RS endetalle.

    También es necesario tener en cuenta que no todas las restricciones de seguridad tienen por qué apareceren el fichero web.xml. En el caso de que necesiten reglas de seguridad demasiado complejas como para serexpresadas en la estructura de un documento XML, se pueden crear restricciones de seguridad programáticas,que son impuestas por el propio código Java. En nuestro caso, existen este tipo de restricciones de seguridadsobre el recurso /usuarios, que ya veremos en su momento.

    A continuación se muestran unos fragmentos que ilustran el cometido del descriptor web.xml.Para definir la página de inicio de la aplicación.

    1 2 welcome.html3

    Para establecer el método de autenticación a HTTP BASIC.

  • 18 Capítulo 3. Aplicación en el servidor y API REST

    1 2 BASIC3 Servicio de fisioterapia ejerciciodb4

    En la sección 3.4 se puede encontrar más información acerca del método de autenticación HTTP BASIC.A continuación se muestra un ejemplo de cómo imponer una restricción de seguridad. Únicamente los

    usuarios que posean el rol “admin” pueden acceder al recurso contraseña.

    1 2 Password can only be changed by admin3 4 Password handling5 /rest/password/*6 7 8 admin9 10

    persistence.xmlEl otro gran archivo de configuración que se incluye en el fichero war es persistence.xml, que sirve paraestablecer la configuración del proveedor del servicio de persistencia JPA/Hibernate. Este es un archivo XMLcon el siguiente contenido:

    1 5 6 java:comp/env/jdbc/EjercicioDB7 8

    Código 3.1 Fichero persistence.xml.

    En este fichero estamos asignando un nombre (“manager1”) a una fuente de datos existente en el servidorTomcat que viene identificada por la URI “java:comp/env/jdbc/EjercicioDB”. En el código fuente usaremosla cadena de caracteres “manager1” para referirnos a cierta conexión a una base de datos sin tener queespecificar los parámetros de dicha conexión. Los parámetros de la conexión a la base de datos solamentetendrán que ser indicados en el archivo de configuración de Tomcat en el que se definió la fuente de datos.Posteriormente, cuando expliquemos cómo se usa JPA/Hibernate, veremos dónde se hace uso del nombreque hemos asignado a nuestra fuente de datos.Para ver en mayor profundidad el funcionamiento de JPA/Hibernate, véase la sección 3.2.3.

    3.2.2 Funcionamiento de JAX-RS

    JAX-RS son las siglas de Java API for RESTful Web Services que es una especificación de API para la creaciónde APIs RESTful en Java.

    La implementación de JAX-RS que hemos usado ha sido Jersey, por ser la implementación de referencia.Para decirle a Maven que debe incluir la librería Jersey en nuestra aplicación basta con añadir las siguientes

    líneas en la sección de dependencias del fichero pom.xml.

    1 2 org.glassfish.jersey.bundles3 jaxrs-ri4 2.22.25

    La API de JAX-RS consiste en un conjunto de anotaciones que indican al contenedor web qué métodos dequé clases van a despachar las peticiones, y cuáles son las entradas y salidas que dichos métodos quierentener.

  • 3.2 La aplicación Java del servidor 19

    Veamos varios ejemplos extraídos del código fuente para comprender el funcionamiento de JAX-RS.

    1 /*2 Copyright 2018 Policarpo Caballero Peña3 See LICENSE for details.4 */5 package ejercicio;67 import javax.ws.rs.ApplicationPath;8 import javax.ws.rs.core.Application;910 /**11 Root path for REST resources12 */13 @ApplicationPath("/rest")14 public class App extends Application {15 }

    Código 3.2 Fichero App.java.

    Lo primero que vemos en este código es que las anotaciones de JAX-RS residen en el paquete javax.ws.rs.En este código podemos ver el uso de la anotación ApplicationPath que sirve para indicar el prefijo que van atener todas las rutas a los recursos REST que existan en nuestra aplicación.Si por ejemplo, estamos usando el protocolo HTTPS, nuestro dominio es larpicos.zapto.org, el puerto

    que usamos es el 8081, y la ruta sobre la que se despliega la aplicación es ejercicios, sabemos que las URLsa los recursos web de aplicación serán de la forma https:// larpicos.zapto.org:8081/ ejercicios/ *, y debido ala anotación ApplicationPath que acabamos de ver, las URLs de los recursos web REST, serán de la formahttps:// larpicos.zapto.org:8081/ ejercicios/ rest/ *.

    Veamos ahora un extracto de una de las clases que exponen un recurso REST.

    12 @Path("/musculos")3 public class RecursoMusculo {45 @GET6 @Produces(MediaType.APPLICATION_JSON)7 public Response get(@Context UriInfo uriinfo) {8 ...9 }1011 @POST12 @Consumes(MediaType.APPLICATION_JSON)13 @Produces(MediaType.APPLICATION_JSON)14 public Response post(ejercicio.dto.MusculoDto o) {15 ...16 }1718 ...1920 }

    Código 3.3 Recurso REST mediante JAX-RS.

    Esta clase se denomina RecursoMusculo y permite realizar operaciones de lectura, escritura, creación yborrado de objetos de tipo MusculosDto que representan músculos.

    Las anotaciones que vemos en este extracto son Path, GET, POST, Consumes y Produces.La anotación Path sirve para indicar la ruta asociada a este recurso REST. Esto quiere decir que los mensajes

    HTTP que se reciban con el valor de ruta igual a /ejercicios/rest/musculos serán procesados por esta claseJava.La anotaciones GET, POST que vemos en este ejemplo, y otras tales como PUT, DELETE, o HEAD sirven para

    indicar que el método que reciba la anotación será el encargado de atender los mensajes HTTP del tipocorrespondiente que realicen sobre la ruta de este recurso REST.Finalmente las anotaciones Produces, Consumes sirven para indicar cuales son los tipos MIME del cuerpo

    del mensaje de petición, en el caso de Consumes, o del cuerpo del mensaje de respuesta, en el caso de Produces.

    https://larpicos.zapto.org:8081/ejercicios/*https://larpicos.zapto.org:8081/ejercicios/rest/*

  • 20 Capítulo 3. Aplicación en el servidor y API REST

    Es posible que varios métodos con la misma ruta en el path, se diferencien únicamente por el tipo MIME, ytambién es posible que un mismo método atienda distintos tipos MIME.El método post que aparece en este ejemplo, consume JSON y recibe como argumento un objeto de tipo

    ejercicio.dto.MusculoDto. Este objeto contiene una serie de campos que serán rellenados a partir de loscampos existentes en el JSON del cuerpo del mensaje. Esta conversión de JSON a objeto Java y viceversaes realizada de manera automática por la librería Jackson, lo cual supone un gran ahorro de tiempo, y siquisieramos soportar que los objetos fueran enviados en formato XML, sería extremadamente fácil de hacer,ya que bastaría con añadir otro tipo MIME a la lista de Consumes y nada más.

    3.2.3 Funcionamiento de JPA

    JPA son las siglas de Java Persistence API. Se trata de una API que permite definir un mapeo entre unconjunto de clases Java y unas tablas de una base de datos relacional, y usar dicho mapeo para acceder a lainformación de la base de datos a través de los objetos Java.JPA es tan solo una especificación y el proveedor de esta API que hemos elegido ha sido Hibernate, una

    implementación open source, muy popular y con buena documentación. Para decirle a Maven que debe incluirlas librerías de Hibernate dentro del fichero war de nuestra aplicación web, debemos añadir las siguienteslíneas dentro de la sección de nuestro fichero pom.xml.

    1 2 org.hibernate3 hibernate-search-orm4 \${hibernate-search-version}5

    La API de JPA se compone de dos grandes bloques: las anotaciones para definir el mapeo entre la base dedatos y los objetos Java; y las clases que permiten realizar operaciones sobre la base de datos con dichosobjetos.En las siguientes secciones se describen estas dos areas de la API JPA.

    Mapeo ORM

    El Object-Relational Mapping consiste en establecer la correspondencia entre una tabla de la base de datos yuna clase de java. En nuestro caso las clases que se corresponden con las tablas SQL, se encuentran en elpaquete ejercicio.dao, donde dao quiere decir data access object.Las clases de este paquete son lo que se ha dado en llamar POJOs, que significa Plain Old Java Object.

    Esto quiere decir que se trata de clases que simplemente contienen una serie de campos y unos métodospara el acceso a dichos campos; las clases no contienen ninguna lógica compleja, y simplemente agrupan unconjunto de datos. Veamos un ejemplo de este tipo de clases.

    1 @Entity2 @Table(name="musculos")3 public class MusculoDao {4 private String nombre;5 private String descripcion;6 private String urlfoto;7 private Set ejercicios;8 private int id;910 public MusculoDao() {11 nombre = new String();12 descripcion = new String();13 urlfoto = new String();14 id = 0;15 }1617 public MusculoDao(ejercicio.dto.MusculoDto m) {18 nombre = new String(m.getNombre());19 descripcion = new String(m.getDescripcion());20 urlfoto = new String(m.getUrlfoto());21 id = m.getId();22 }2324 @Id25 @GeneratedValue(strategy=GenerationType.IDENTITY)

  • 3.2 La aplicación Java del servidor 21

    26 @Column(name="id_musculo")27 public int getId() {28 return id;29 }30 public void setId(int id) {31 this.id = id;32 }3334 @Column(name="nombre")35 public String getNombre() {36 return nombre;37 }38 public void setNombre(String nombre) {39 this.nombre = nombre;40 }4142 @Column(name="descripcion")43 public String getDescripcion() {44 return descripcion;45 }46 public void setDescripcion(String descripcion) {47 this.descripcion = descripcion;48 }4950 @Column(name="urlfoto")51 public String getUrlfoto() {52 return urlfoto;53 }54 public void setUrlfoto(String urlfoto) {55 this.urlfoto = urlfoto;56 }5758 @ManyToMany(59 cascade = {60 CascadeType.DETACH,61 CascadeType.MERGE,62 CascadeType.REFRESH,63 CascadeType.PERSIST64 },65 targetEntity = EjercicioDao.class)66 @JoinTable(67 name="musculosdeejercicios",68 joinColumns={@JoinColumn(name="id_musculo", referencedColumnName="id_musculo")},69 inverseJoinColumns={@JoinColumn(name="id_ejercicio", referencedColumnName="id_ejercicio")

    })70 public Set getEjercicios() {71 return ejercicios;72 }73 public void setEjercicios(Set e) {74 this.ejercicios = e;75 }76 }

    Código 3.4 Ejemplo de clase DAO.

    Lo primero que vemos es que la clase MusculoDao contiene los siguientes campos: nombre, descripción,urlfoto, ejercicios e id. Para cada uno de estos campos o variables de instancia existen 2 métodos asociados.El método de lectura, también denominado getter, que en el caso de nombre se llama getNombre, y el métodode escritura, o setter, que continuando con el ejemplo se llama setNombre. Es muy importante que se respetela convención de que los nombres de los métodos getter/setter sigan la convención set + Campo, y get +Campo, ya que JPA se basa en esta convención a la hora de determinar cuales son los métodos asociados acada campo.Vemos que esta clase POJO ha recibido una serie de anotaciones. Veamos el significado de cada una de

    ellas.La primera es la anotación Entity que aparece justo antes de la clase. Esta anotación le indica a JPA que

    esta clase es una clase que interviene en el mapeo ORM, y cuyas instancias podrán ser guardas y obtenidasde la base de datos.

  • 22 Capítulo 3. Aplicación en el servidor y API REST

    A continuación de la anotación Entity aparece la anotación Table con elemento name tomando el valor“musculos”. Esta anotación indica a qué tabla de la base de datos corresponde esta clase.

    Estas dos anotaciones son las que se aplican a nivel de clase. El resto de las anotaciones solo afectarán acada una de las variables de instancia que se corresponden con los campos de la tabla de la base de datos. Lasanotaciones de los campos pueden ser aplicadas, o bien sobre la variable de instancia, o bien sobre uno de susmétodos de acceso; esto resulta indiferente. Nosotros hemos decidido aplicarlas sobre uno de los métodos.En el caso de la variable id, que se corresponde con la clave primaria de la tabla, nos encontramos tres

    anotaciones: Id, GeneratedValue, y Column. La anotación Id le indica a JPA que este campo es la claveprimaria de la tabla. La anotación Generatedvalue le indica cuál es la estrategia a seguir en el caso de quese intente insertar una nueva fila en la tabla sin especificar el valor para la clave primaria. En este casoestamos siguiendo la estrategia IDENTITY, que consiste en el proveedor de la persistencia usará una columnaidentidad que es autogenerada por la base de datos. Finalmente, la anotación Column indica el nombre de lacolumna de la tabla que se corresponde con esta variable de instancia.

    El resto de las variables de instancia se mapean de una manera muy sencilla, donde solo se usa la anotaciónColumn para indicar la correspondencia con las columnas de la tabla subyacente.Un caso especial es el del campo ejercicios, que contiene el conjunto de los ejercicios fisioterapéuticos

    en los que participa este músculo. Puesto que se trata de un conjunto no ordenado y en el que no se deberepetir ningún elemento la representación en Java de este campo se realiza mediante un Set. En la base dedatos este campo se expresa mediante una tabla adicional que relaciona las tablas de músculos con la tablade ejercicios. La anotación JoinTable sirve para indicar cuál es la tabla que establece esta correspondencia.El elemento name de esta anotación designa la tabla de correspondencia y los elementos joinColumns einverseJoinColumns indican los nombres de las columnas sobre las que realizar los joins.

    La anotación ManyToMany que aparece antes de JoinTable sirve para indicar que se trata de una relaciónmuchos a muchos ya que en un ejercicio pueden participar múltiples músculos y un mismo músculo puedeaparecer en distintos ejercicios. En la anotación ManyToMany se le indica qué se debe hacer cuando serealice una operación de persistencia en una de las tablas involucradas en esta relación. Al establecer elcomportamiento en cascada para la operación persist, cuando un objeto de tipo músculo sea añadido a la basede datos, los objetos ejercicios nuevos que pudieran estar contenidos en el Set del campo ejercicios tambiénserán guardados en la base de datos. Sin embargo, al no haber establecido una relación de cascada para laoperación de delete, cuando borremos un objeto musculo de la base de datos, los ejercicios en los que esemúsculo aparecía, no serán borrados, que es justo el comportamiento que queremos.La idea de las relaciones en cascada es una de las características más potentes que nos ofrece JPA, y que

    simplifica enormemente el trabajo con una base de datos.Manejo de entidades

    Una vez hemos definido las correspondencias con la base de datos de un conjunto de clases estamos preparadospara realizar operaciones de persistencia con las instancias de estas clases. De ahora en adelante nos referiremosa estas instancias con el término entidades.Las operaciones de persistencia se ejecutan a través de un objeto llamado el gestor de entidades de la

    clase EntityManager. En el código fuente de la aplicación todas las interacciones con los objetos de tipoEntityManager se encuentran localizadas en la clase ejercicio.rest.RestUtil. A continuación, se muestra unbreve fragmento de código que ilustra como se crea el objeto EntityManager.

    1 private static final EntityManagerFactory emf =2 Persistence.createEntityManagerFactory("manager1");3 public void metodo() {4 EntityManager em = emf.createEntityManager();5 }

    Código 3.5 Creación de EntityManager.

    La idea es que se crea un objeto EntityManagerFactory una sola vez en el ciclo de vida de la aplicación, ya partir de este objeto creamos un EntityManager cada vez que deseemos realizar una transacción sobre labase de datos. Obsérvese que al crear el EntityManagerFactory se ha especificado el mismo nombre que seindicó en el archivo persistence.xml (véase la sección 3.2.1).Una vez que tenemos un objeto EntityManager podemos realizar sobre él distintas operaciones.Para realizar una operación de búsqueda usaremos el método find, que recibe como argumentos la clase de

    entidad que queremos buscar y el índice que identifica el objeto que queremos recuperar.

  • 3.2 La aplicación Java del servidor 23

    1 UtilDao tmp = entitymanager.find(UtilDao.class, 7);

    Si queremos añadir un nuevo objeto a la base de datos, usaremos el método persist del gestor de entidades,que recibe como único argumento el objeto que deseamos guardar.Si queremos actualizar un objeto que ya existe en la base de datos y que acabamos de recuperar, lo que

    debemos hacer es modificar directamente el objeto y después pasarlo como argumento al método merge delgestor de entidades.Finalmente, la otra operación fundamental cuando se trabaja con entidades es remove, que recibe como

    argumento la entidad que se desea borrar de la base de datos.En todos estos casos debemos encapsular las operaciones que ejecutemos dentro de una transacción como

    se ilustra en el siguiente fragmento.

    12 public static Response deleteElement (Integer id, ClassesInfo ci) {3 Response r;4 EntityManager em = createEntityManager();5 EntityTransaction t = em.getTransaction();6 t.begin();78 try {9 Object o = em.find(ci.daoClass, id);10 if (o != null) {11 em.remove(o);12 r = Response.ok("null", MediaType.APPLICATION_JSON).build();13 } else {14 r = Response.status(Response.Status.NOT_FOUND).build();15 }16 t.commit();17 } catch (Exception e) {18 t.rollback();19 throw e;20 } finally {21 em.close();22 }2324 return r;25 }

    Código 3.6 Ejemplo de manejo de entidades.

    Este código define una función que realiza el borrado de una entidad de una clase genérica Data AccessObject (DAO).Primero, se crea el objeto gestor de entidades mediante una pequeña función auxiliar que hace uso del

    EntityManagerFactory. Después, se indica el inicio de una transacción mediante la creación de un objetoEntityTransaction y la invocación de su método begin. A continuación, se inicia un bloque try/catch/finally.En la clausula finally nos debemos asegurar de que el método close del EntityManager es invocado indepen-dientemente de si ha habido un error o no. En el caso de que se produzca un error, se ejecutará el métodorollback para cancelar la transacción y se continuará la propagación del error. Finalmente, el flujo del códigoen caso de que no haya errores será obtener la entidad de la base de datos mediante el método find, y sueliminación mediante el método remove. Si no se han producido errores, aplicamos la transacción medianteel método commit de la EntityTransaction.

    3.2.4 Estructura del código fuente

    Finalmente, el contenido más importante de la aplicación web lo constituye el código fuente Java, que seencuentra en la carpeta src/main/java.

    Todos los paquetes Java que componen la aplicación web son hijos de un paquete padre llamado ejercicio.En el paquete ejercicio podemos encontrar tres paquetes hijos: el paquete dao que contiene las clases DAOque implementan el mapeo de la base de datos; el paquete dto que contiene las clases que llevan a cabo elmapeo a JSON; y el paquete rest que contiene las clases que ofrecen el servicio web RESTful medianteJAX-RS. Dentro de este último paquete encontramos la clase RestUtil que contiene una serie de métodosestáticos que realizan el manejo de entidades según se explicó en la sección 3.2.3.

  • 24 Capítulo 3. Aplicación en el servidor y API REST

    El código existente en los paquetes dto y dao es muy parecido y corresponde a lo que se conoce en elmundo Java como Plain Old Java Object (POJO)s. Un POJO es simplemente un objecto Java que contieneuna serie de campos, y unos métodos para acceder a dichos campos. Cuando la aplicación reciba una peticióna través de JAX-RS, es posible que el método que atienda dicha petición reciba como uno de sus argumentosun objeto POJO de una de las clases Data Transfer Object (DTO). Este objeto DTO habrá sido creado apartir del JSON que estaba contenido en el cuerpo del mensaje de la petición. Este es un proceso realizadopor la implementación de JAX-RS, sin que nosotros tengamos que realizar más esfuerzo que el de definirestos objetos POJO. De igual modo, cuando el servidor genera una respuesta es posible que en el cuerpo delmensaje HTTP viaje la representación en formato JSON de un objeto DTO que es la respuesta.

    Por otra parte, la interacción con la base de datos también requiere del uso de POJOs, que denominaremosDAOs. Es importante darse cuenta de que no es adecuado reutilizar los mismos POJOs que se usan en lainterfaz con JAX-RS, para la interfaz con la base de datos. Esto es así debido a que los POJOs que se empleancon la base de datos contienen una representación completa de la base de datos, y nosotros no queremosexponer por completo esta información, en particular en lo que se refiere a las contraseñas de los usuarios ysus roles.El uso de dos tipos de clases POJO diferentes: las DAO y las DTO, para realizar el transporte de la

    información, nos obliga a definir un constructor en cada clase DAO o DTO que nos permita realizar laconversión de clase DAO a DTO y viceversa. La invocación de estos constructores será un paso necesario quedeberá ocurrir tanto cuando vaya a entrar información en la base de datos, como cuando salga información.En estas conversiones de información siempre intervendrá una pareja de clases: una será la clase DAO y laotra su clase DTO correspondiente. Debido a que la lógica de procesamiento de entidades está implementadamediante un código genérico, tanto la clase DAO, como la clase DTO, serán en realidad tipos genéricos.Los genéricos son una característica del lenguaje Java que fue añadida mucho después de que el lenguajefuese creado y presentan por tanto algunas deficiencias. En particular, en este caso nos topamos con el hechode que no es posible invocar el constructor de un tipo genérico. Para sortear este problema, se ha creado laclase ClassesInfo, cuyo propósito es ofrecer unos métodos genéricos que realicen esta conversión. Puesto queClassesInfo involucra tanto a las clases DAO como las DTO, se consideró que esta clase no debía pertenecera ninguno de esos paquetes y se ubicó en el paquete rest.

    Una vez explicado el papel que desempeñan las clases DAO y DTO como transmisores de la informaciónentre la aplicación y la base de datos; y la aplicación y la parte de red, respectivamente, procedamos a explicarel funcionamiento del núcleo de la aplicación que es el paquete rest.

    En el paquete rest se encuentran las clases que contienen los métodos que atienden las peticiones REST.Para cada uno de los recursos REST hemos creado una clase cuyo nombre es la palabra “Recurso” y elnombre del recurso. Una excepción a esta regla la constituyen las clases Me y MeRoles que dan acceso a lainformación personal sobre el usuario actual y los roles de dicho usuario.Cada una de estas clases recurso, contiene métodos que atienden las operaciones GET, POST sobre el

    recurso o tabla, y las operaciones GET, PUT, POST y DELETE sobre cada una de las instancias del recurso, ofilas de la tabla. La asociación entre los métodos y las operaciones REST se lleva a cabo mediante anotacionescomo se explica en la sección 3.2.2 sobre el funcionamiento de JAX-RS.La lógica contenida en estos métodos GET, PUT, POST y DELETE, es fundamentalmente la misma,

    independientemente de qué recurso se trate. Por ello, y para evitar una repetición del código inútil y claramenteperjudicial, esta lógica ha sido extraída de dichos métodos y movida a una clase denominada RestUtil, dondeha sido implementada de una forma genérica. Esta clase constituye, por tanto, el centro neurálgico de laaplicación.La clase RestUtil se compone de una serie de métodos estáticos, cada uno de los cuales atiende un

    determinado tipo de petición.Todos los métodos existentes en RestUtil siguen fundamentalmente el mismo patrón:

    • Crear el gestor de entidades para poder acceder a la base de datos, e iniciar una transacción.

    • Realizar la conversión de DTO a DAO mediante un objeto ClassesInfo si se trata de un método queacepta como entrada entidades, es decir los métodos de tipo POST y PUT.

    • Realizar la consulta, creación, actualización, o borrado de entidades mediante el gestor de entidadesdependiendo de qué método se trate.

    • Realizar commit sobre la base de datos para cerrar la transacción y generar la respuesta para el usuario,posiblemente realizando una conversión de DAO a DTO.

  • 3.3 La API REST 25

    En el diagrama UML de clases de la figura 3.2 se intenta ilustrar la relación entre RestUtil, ClassesInfo ylas clase DAO y DTO.

    Figura 3.2 Diagrama de clases UML de RestUtil.

    3.3 La API REST

    Todos los recursos que componen la API del servicio prestado por el servidor se corresponden con rutas hijasde la ruta ejercicio/rest. En la tabla 3.1 aparece un listado de todos los recursos disponibles y los métodos alos que responden. Para hacer la más fácil la exposición, hemos omitido algunos recursos adicionales queserán explicados en la sección 3.3.1. Las rutas son relativas a ejercicio/rest.

    En la API podemos distinguir dos tipos de operaciones GET. Las que son invocadas sobre una tabla entera ydevuelven una página de dicha tabla; y las que son invocadas sobre una fila de una tabla para leer únicamenteesa fila. En ningún caso las operaciones GET reciben como argumento de entrada una entidad, y en ningúncaso producen ninguna modificación sobre la base de datos.Las operaciones GET sobre tabla pueden ser paginadas mediante parámetros pasados en el PATH. En

    concreto, el parámetro “since_id” indica el desplazamiento de la página con respecto al comienzo de la tablaen filas, y el parámetro “count” indica el número de filas que debe contener esta página. Si no se especificanestos parámetros en el mensaje GET, los valores por defecto son 0 y 10, respectivamente.

    En cuanto a los métodos POST, igualmente nos encontramos dos tipos de método POST: los usados sobreuna tabla para añadirle una nueva fila, y los usados sobre una fila en particular para modificarla. Los métodosPOST siempre reciben como argumento de entrada una entidad que debe ser de la clase DTO asociada adicho recurso. En la respuesta al método POST, el servidor devolverá siempre la representación JSON dela entidad que ha sido creada o editada, incluyendo el identificador del objeto, para que de esta manera elcliente sepa el identificador que le corresponde al objeto en caso de que se haya creado un nuevo objeto en labase de datos.

  • 26 Capítulo 3. Aplicación en el servidor y API REST

    Tabla 3.1 Listado de rutas de la API REST.

    Ruta Métodos Descripción

    /ejercicios GET Obtener una página de listado de objetos ejercicioPOST Crear un nuevo objeto ejercicio

    /ejercicios/ GET Obtener el objeto ejercicio designado por idPOST Modificar el objeto ejercicio designado por idPUT Modificar el objeto ejercicio designado por idDELETE Eliminar el objeto ejercicio designado por id

    /musculos GET Obtener una página de listado de objetos músculoPOST Crear un nuevo objeto músculo

    /musculos/ GET Obtener el objeto músculo designado por idPOST Modificar el objeto músculo designado por idPUT Modificar el objeto músculo designado por idDELETE Eliminar el objeto músculo designado por id

    /utiles GET Obtener una página de listado de objetos útilesPOST Crear un nuevo objeto útil

    /utiles/ GET Obtener el objeto útil designado por idPOST Modificar el objeto útil designado por idPUT Modificar el objeto útil designado por idDELETE Eliminar el objeto útil designado por id

    /recursos GET Obtener una página de listado de objetos recursosPOST Crear un nuevo objeto recurso

    /recursos/ GET Obtener el objeto recurso designado por idPOST Modificar el objeto recurso designado por idPUT Modificar el objeto recurso designado por idDELETE Eliminar el objeto recurso designado por id

    /usuarios GET Obtener una página de listado de objetos usuariosPOST Crear un nuevo objeto usuario

    /usuarios/ GET Obtener el objeto usuario designado por idPOST Modificar el objeto usuario designado por idPUT Modificar el objeto usuario designado por idDELETE Eliminar el objeto usuario designado por id

    /rutinas GET Obtener una página de listado de objetos rutinasPOST Crear un nuevo objeto rutina

    /rutinas/ GET Obtener el objeto rutina designado por idPOST Modificar el objeto rutina designado por idPUT Modificar el objeto rutina designado por idDELETE Eliminar el objeto rutina designado por id

    /me GET Obtener el objeto usuario correspondiente al usuario actual/me/roles GET Obtener los roles correspondientes al usuario actual/multimedia POST Crear un nuevo objeto multimedia

    /password/GET Obtener contraseña de usuario dado por idPOST Modificar contraseña de usuario dado por idPUT Modificar contraseña de usuario dado por id

    Los métodos PUT únicamente están disponibles para la edición de filas individuales, y funcionan exacta-mente igual que sus homólogos POST. Según la RFC 7231 [2] sobre la semántica del protocolo HTTP/1.1,en una petición POST, la URI indica un recurso que maneja la representación de los datos recibidos, mien-tras que en una petición PUT, la URI indica el recurso que es reemplazado por los datos que llegan. Unaimplementación que quiera ser conforme a esta indicación sobre la semántica de los mensajes PUT y queaceptara mensajes PUT sobre el recurso tabla tendría entonces que aceptar como entidad de entrada unarepresentación de todo el contenido de la tabla, lo cuál es algo que en muchos casos puede resultar ineficiente.Por ello, hemos optado por no permitir una actualización de la tabla al completo, y por tanto, no se aceptanmensajes PUT sobre las tablas.

    Finalmente, los métodos DELETE se admiten únicamente sobre filas individuales, no reciben ningún tipo

  • 3.3 La API REST 27

    Tabla 3.2 Recursos web relacionados con ejercicios.

    Ruta Métodos Descripción/ejercicios//musculos GET Obtener una página de listado

    de objetos músculos asociadosa un ejercicio

    /ejercicios//musculos/POST Asociar un objeto músculo a un

    objeto ejercicioPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre un músculo y un ejercicio/ejercicios//utiles GET Obtener una página de listado

    de objetos útiles asociados a unejercicio

    /ejercicios//utiles/POST Asociar un objeto útil a un

    objeto ejercicioPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre un útil y un ejercicio/ejercicios//recursos GET Obtener una página de listado

    de objetos recursos asociados aun ejercicio

    /ejercicios//recursos/POST Asociar un objeto recurso a un

    objeto ejercicioPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre un recurso y un ejercicio/ejercicios//rutinas GET Obtener una página de listado

    de objetos rutinas asociados aun ejercicio

    /ejercicios//rutinas/POST Asociar un objeto rutina a un

    objeto ejercicioPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre una rutina y un ejercicio

    de argumento de entrada, salvo el identificador de objeto presente en la ruta del recurso, y no devuelventampoco ninguna entidad en el mensaje de respuesta. Hubiera sido posible aceptar mensajes DELETE sobrela tabla al completo que produjeran un borrado total de los contenidos de la tabla, pero se optó por no ofreceresta funcionalidad en la API, por ser raramente útil.En todos los casos, es necesario que el cliente incluya en sus mensajes una cabecera que contenga las

    credenciales según se explica en la sección 3.4 sobre seguridad.

    3.3.1 Relación entre los recursos

    Los objetos obtenidos en formato JSON mediante las invocaciones a la API descritas anteriormente nocontienen información acerca de sus vínculos con otras entidades. Esto es así debido a que el número deobjetos enlazados podría ser muy elevado.Una solución podría haber sido la de introducir esta información de una forma paginada. Teniendo en

    cuenta que cada entidad puede tener varias relaciones con otras entidades (por ejemplo, ejercicios estárelacionado con músculos, útiles, rutinas y recursos), las invocaciones a la API se volverían muy complejas,ya que el usuario tendría que especificar los parámetros de paginación, para cada una de estas relacionesentre entidades.

    La solución más acertada y qué es la práctica habitual es la de exponer estas relaciones mediante recursosadicionales que “cuelgan” de cada entidad. Por ejemplo, si tenemos un objeto ejercicio en rest/ejercicios/15,los músculos asociados a dicho ejercicio podrán ser accedidos mediante rest/ejercicios/15/musculos, losútiles estarán en rest/ejercicios/15/utiles, y así sucesivamente.

  • 28 Capítulo 3. Aplicación en el servidor y API REST

    Tabla 3.3 Recursos web relacionados con ejercicios: relaciones recíprocas.

    Ruta Métodos Descripción/musculos//ejercicios GET Obtener una página de listado

    de objetos ejercicio asociados aun músculo

    /musculos//ejercicios/POST Asociar un objeto ejercicio a un

    objeto músculoPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre un músculo y un ejercicio/utiles//ejercicios GET Obtener una página de listado

    de objetos ejercicio asociados aun útil

    /utiles//ejercicios/POST Asociar un objeto ejercicio a un

    objeto útilPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre un útil y un ejercicio/recursos//ejercicios GET Obtener una página de listado

    de objetos ejercicios asociadosa un recurso

    /ejercicios//recursos/POST Asociar un objeto ejercicio a un

    objeto recursoPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre un recurso y un ejercicio/rutinas//ejercicios GET Obtener una página de listado

    de objetos ejercicios asociadosa una rutina

    /rutinas//ejercicios/POST Asociar un objeto ejercicio a un

    objeto rutinaPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre una rutina y un ejercicio

    Tabla 3.4 Recursos web relacionados con usuarios.

    Ruta Métodos Descripción/rutinas//usuarios GET Obtener una página de listado de

    objetos usuarios asociados a unarutina

    /usuarios//rutinas/POST Asociar un objeto rutina a un objeto

    usuariosPUT Misma operación que POSTDELETE Eliminar la asociación existente

    entre un usuario y un rutina

    Obsérvese que las relaciones están implementadas en la base de datos de forma que cuando el usuarioañada, por ejemplo, un músculo a un ejercicio, el ejercicio también quedará añadido automáticamente almúsculo, ya que la tabla que implementa la relación es la misma en ambas direcciones.

    3.4 Seguridad y control del acceso

    Puesto que deseamos que el servicio prestado por la aplicación solo esté disponible para los usuariosregistrados en el sistema, debemos establecer una política de seguridad en la aplicación. Esto consiste en

  • 3.4 Seguridad y control del acceso 29

    dos tareas: definir un sistema de autenticación, para que en el sistema exista el concepto de usuario y rol; ypor otra parte, imponer unas restricciones de seguridad a los usuarios que definan qué actividades puedenrealizar y cuáles no.

    3.4.1 Método de autenticación

    Aunque es posible que una aplicación cree sus propios métodos de autenticación, esta no es una tarea trivialen absoluto. Por ello, en la plataforma Java EE las aplicaciones web pueden especificarle al servidor deaplicación a través del descriptor de aplicación web, el método de autenticación que desean usar y el servidorde aplicación realizará esta tarea en lugar de ellas.El método de autenticación elegido es el método de autenticación de acceso básico definido en la RFC

    7617 y que de ahora en adelante llamaremos HTTP BASIC para abreviar y por ser esta la denominación quese usa para este método en el descriptor de la aplicación web.

    Dicho método no requiere la creación d