Proyecto final de DAM: Spring Data Rest

Desarrollo de una app dentro de la asignatura de proyecto del ciclo formativo DAM

Uno de los momentos más emocionantes y estresantes de un ciclo formativo es la etapa de desarrollo del proyecto final de ciclo. Los alumnos se vuelcan totalmente para conseguir un proyecto de gran calidad que demuestre lo excelentemente preparados que están cuando acaban estos estudios.

Pues bien, nosotros no somos una excepción y nos ha llegado el momento de desarrollar nuestra idea. Para explicar un poco el contexto, cabe destacar que somos alumnos de 2º curso de Desarrollo de Aplicaciones Multiplataforma (DAM) en el centro de estudios STUCOM de Barcelona.

Como proyecto final hemos decidido desarrollar una aplicación que permita a los ciudadanos de una localidad poder registrar incidencias que vean en la calle para que, así, el ayuntamiento pueda dar una solución rápida y efectiva a esos contratiempos.

Los motivos que nos han llevado a trabajar en esta idea son básicamente dos: En primer lugar creemos que el mundo de las smartcities es el futuro próximo. Pensamos que los ciudadanos forman parte de la población en la que viven y que deben colaborar a mantener y mejorar su zona. Y, en segundo lugar, nuestro objetivo es poder ayudar a la gente a mejorar su estilo y nivel de vida para que se sientan más felices e integrados. Fases en el desarrollo del proyecto de DAM:

 

Definición de las partes del proyecto

Después de esta pequeña introducción toca explicar más profundamente en que consiste el proyecto final. Pues bien, toda aplicación informática consta de dos partes bien diferenciadas.

Una de ellas es la parte de Back End o servidor, la parte interna que el usuario final no ve pero que es la que maneja toda la lógica. La otra parte es con la que los usuarios interactúan, es decir, la parte Front End o cliente.

Hoy vamos a centrarnos más en la parte del servidor. Para ello hemos utilizado el lenguaje de programación Java junto con el framework Spring Data Rest. Esto nos permite construir un Back End sólido y muy escalable, perfectamente preparado para soportar una estructura extensa de clientes. Pero, antes de nada, vamos a explicar qué es exactamente el framework Spring Data.

Framework Spring Data Rest

Spring Data es un proyecto de SpringSource cuyo propósito es unificar y facilitar el acceso a distintos tipos de tecnologías de persistencia, tanto a bases de datos relacionales como a las del tipo NoSQL.

Spring ya proporcionaba soporte para JDBC, Hibernate, JPA, JDO o MyIbatis, simplificando la implementación de la capa de acceso a datos, unificando la configuración y creando una jerarquía de excepciones común para todas ellas.

Y ahora, Spring Data viene a cubrir el soporte necesario para distintas tecnologías de bases de datos NoSQL y, además, integra las tecnologías de acceso a datos tradicionales, simplificando el trabajo a la hora de crear las implementaciones concretas.

Con cada tipo de tecnología de persistencia los DAOs (Data Access Objects) ofrecen las funcionalidades típicas de un CRUD (Create-Read-Update-Delete ) para objetos de dominio propios, métodos de búsqueda, ordenación y paginación. Spring Data proporciona interfaces genéricas para estos aspectos (CrudRepository, PagingAndSortingRepository) e implementaciones específicas para cada tipo de tecnología de persistencia.

Finalmente, el framework Spring Data Rest trabaja sobre Spring Data permitiendo que las entidades, de las cuales se derivan los DAOs, se expongan directamente como puntos RESTful webservice. Esto da como resultado poder montar un RESTful webservice en cuestión de minutos y sin código adicional.

image1

Estructura del Servidor

Como podemos ver en la imagen superior, un Back End tipo se divide en 4 capas, a saber, la capa Domain, la capa Repository, la capa Controller y la capa Service.

Capa Domain:

Es la capa más básica de todas. En esta división se encuentran las clases entidad, también llamadas POJO. Estas clases definen los objetos que se reflejarán en la base de datos. En nuestro caso harían referencia los usuarios, incidencias, etc…

image2

Vamos a analizar, por ejemplo, la clase User.java de nuestro proyecto. Contemplando la imagen superior podemos ver varias peculiaridades. En primer lugar nos fijamos en las anotaciones que tienen los atributos de la clase.

Primero, es vital que usemos la anotación @Entity. Esta anotación es típica de Java Persistence API (JPA), lo que nos permite que Spring pueda crear una base de datos automáticamente entendiendo que esta clase es una entidad y, por tanto, un objeto de la BD.

Seguidamente encontramos la definición del primer atributo. En este caso usamos las anotaciones @Id y @GeneratedValue para dar a entender que este será el identificador de clase. Las siguientes anotaciones son validaciones de atributos para que, cuando se registre un nuevo objeto, se cumplan ciertos requisitos que el programador quiere.

Finalmente, tenemos que hacer referencia a las dos últimas anotaciones, concretamente @OneToMany(mappedBy = user). Estas anotaciones permiten crear una relación entre entidades de la base de datos. En este caso definimos una relación 1N hacia las clases Authorities y Incidence.

En la otra entidad usaremos la anotación @ManyToOne, lo que permite poder establecer una relación en los dos sentidos y comunicar las dos entidades correctamente. Esto lo podemos observar en la siguiente imagen.

image3

Definir así una relación permite que Spring Data Rest haga su magia y cree automáticamente las relaciones en la base de datos a través de hipervínculos. Para explicar esto un poco más detallado, hay que decir que este framework muestra los datos del servidor en un formato un tanto diferente al habitual. Lo normal es mostrar los datos del servidor a través del lenguaje JSON. Pues bien, Spring utiliza el lenguaje HAL + JSON permitiendo poder navegar entre todas las entidades relacionadas partiendo de una única búsqueda.

Por ejemplo, si hacemos una consulta GET para poder ver los usuarios registrados se nos muestra lo siguiente:

image4

Al haber usado las anotaciones anteriores correctamente, podemos comprobar que al mostrar un usuario también se nos muestran las relaciones existentes con ese usuario. Concretamente el campo _link (los campos que empiezan por “_” son típicos de HAL) ,debajo del campo points, muestra esas relaciones. Así podemos navegar entre ellas con tan sólo hacer una búsqueda.

Capa Repository:

Una vez explicado el funcionamiento de las entidades, hace falta explicar otra de las grandes magias de Spring Data Rest. Para definir rápidamente esta capa, comentar que cada entidad definida en la capa anterior debe tener una clase Repository en esta capa.

Esta clase Repository se programa de la siguiente manera:

Fácil, ¿verdad?. Cierto, es fácil de programar pero dentro encierra una lógica increíble. Para empezar, al igual que hacíamos con las clases entidad, debemos decirle a Spring que esta clase es de tipo Repository, para ello usamos la anotación @Repository.

Seguidamente definimos la clase como una interfaz y, muy importante, debe extender de CrudRepository<Entidad, Id>. Con esta línea de código el framework ya se encarga de crear todas las funcionalidades básicas, es decir el CRUD (Create, Update, Delete). De esta manera nos evitamos tener que escribir todas estas funcionalidades. Y, si queremos añadir campos de búsqueda personalizados para la entidad, sólo tenemos que usar la función findBy… y el resto será automático.

Capa Controller:

Finalmente encontramos la capa Controller. En esta capa encontramos las clases controladores que reciben peticiones específicas del cliente e interactúan con varios Repositories a la vez para llevar a cabo un seguido de operaciones en el servidor.

Por ejemplo, si un usuario se registra en nuestro servicio, primero debemos insertar el usuario en la base de datos y luego insertar el nuevo rango que tendrá. Esto provoca que tengamos que utilizar dos Repositories, en concreto el UserRepository y el AuthoritiesRepository. Para poder usar los dos a la vez creamos una clase Controller que se encargue de todas las operaciones bajo una mismas función.

image5

Capa Service:

La existencia de esta capa depende de cada proyecto. Este apartado se encarga de la Business Logic (Lógica de negocio). Las clases que aquí se encuentran trabajan aspectos característicos del negocio. Por ejemplo, si desarrollamos una aplicación de venta de billetes de avión, esta capa gestionaría información concreta de los aviones o de la compañía, aspectos que se diferencian del propio funcionamiento de la aplicación. La capa Service trabaja entre las capas Controller y Repository.

WebSecurityConfiguration

Ya hemos visto la estructura de nuestro Back End en detalle. Pero todavía nos queda un último aspecto que destacar. Hablamos de Spring Security. Esta funcionalidad permite blindar el servidor para que los datos que manejamos estén a buen recaudo.

Para ello, debemos crear una clase llamada WebSecurityConfiguration que se encargará de otorgar a cada usuario un papel (role) que determinará el acceso que tiene a las diferentes funcionalidades. Como es lógico, en una aplicación existen varios papeles, como los administradores y los usuarios base.

Spring Security nos permite definir qué es lo que puede hacer cada usuario para tener controlados en todo momento nuestros datos. A continuación vemos una imagen de la clase:

image6

Como podemos observar, en este caso hacemos que la ruta “/user/registration” sea de acceso libre, así cualquier persona podrá acceder a esa parte de la aplicación para poder registrarse. Fuera de esta ruta, para acceder a todo lo demás se debe estar registrado. Es por esto que se especifica el tipo de papel que debe tener el usuario y se el obliga a autenticarse.

Pero ¿cómo funciona esta tecnología? Cuando se accede a una parte de la aplicación Spring Security comprueba si se necesita estar autenticado. Si así es, se le pide al usuario que introduzca sus credenciales. Una vez lo ha hecho se comprueban que sean válidas de la siguiente manera.

Se busca en la base de datos 3 campos del usuario. El primero es el campo enabled. Debe estar a 1 para que el usuario esté activo. Después se buscan los campos usernamey password. Estos campos deben llamarse tal cual y, si no es el caso, se debe hacer un cast de estos campos para que así sea. Esto se puede comprobar en la línea 44 de código de la imagen anterior.

Una vez Spring ha validado al usuario, únicamente debe comprobar que el papel asignado para ese usuario sea válido para la ruta a la que intenta acceder. Si es así, se le autenticará y podrá disfrutar de esa funcionalidad plenamente.

Además de la seguridad de los papeles para cada usuario, otra manera de añadir seguridad a nuestro servidor es encriptando las contraseñas en la base de datos. Este paso es vital en cualquier sistema de gestión de contraseñas y nuestro Back End no iba a ser menos.

Para ello hemos utilizado la funcionalidad BcryptPasswordEncoder de Spring Security que permite hacer hash de las contraseñas para posteriormente guardarlas en la BD. Esta función utiliza BCrypt como sistema de encriptación, un sistema muy complejo que otorga una gran seguridad. Para utilizarlo se usa el siguiente código:

image7

La primera función comprueba si la contraseña hasheada de la BD corresponde con la que ha introducido el usuario. Para ello, primero debe encriptar la introducida por el usuario y luego comparar las dos contraseñas encriptadas.

La segunda función es la que se encarga de encriptar una contraseña introducida. Como vemos, se llama a la clase BCryptPasswordEncoder, más concretamente al método .encode(password). Del resto ya se encarga Spring Security.

Conclusión

Esta es una explicación detallada del servidor de nuestro proyecto final para el ciclo de DAM. Nos gustaría adjuntar todo el código del proyecto para un mejor entendimiento del mismo pero no nos es posible ya que estamos participando en un concurso y estamos a la espera de evaluación.

 

Aún así, Bruno y un servidor estaremos encantados de resolver cualquier duda. Para ello podéis escribirnos un correo electrónico a brunokellerperez@gmail.com o alexandre.martiol@gmail.com. Estaremos encantados de poder resolver todas las dudas.

 

En una entrega posterior abordaremos la parte de Front End que será desarrollada como una aplicación web escrita en AngularJS y otra aplicación móvil para iOS.

 

Alexandre Martínez Olmos

Bruno Kéller Pérez

Acerca del autor