Spring Boot - Servicio Data RESTful con acceso a datos con JPA (Front end basado en RESTful hypermedia)

- Prerequisitos

Genera tu proyecto con Spring Boot INITIALIZR.

- Spring boot starter test (este te lo agrega Spring por default para tus pruebas)

- Spring boot starter data JPA.

- H2 como manejador de BD (esta en particular vive en memoria y solo es para esta cápsula). Puedes utilizar la BD que prefieras.

- Spring boot starter data rest.

 

1. Configuración MAVEN

<groupId>com.ledzedev.springboot.datarest</groupId>
<artifactId>ledzedev-spring-boot-datarest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>ledzedev-spring-boot-datarest</name>
<description>Proyecto demo de un servicio de tipo Data Rest Spring Boot con Base de Datos</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

 

2. Empezamos con una entidad de usuarios y un enum que nos servirá para la propiedad de sexo (M=masculino y F=femenino)

/**
* Código generado por Gerado Pucheta Figueroa
* Twitter: @ledzedev
* http://ledze.mx
* 11/Nov/2016.
*/
enum Sexo {

M, F
}


@Entity
class Usuario {


@Id
@GeneratedValue
private Long id;


private String nombre;

private Long edad;

private Sexo sexo;

public Usuario() {
}

public Usuario(String nombre, Long edad, Sexo sexo) {
this.nombre = nombre;
this.edad = edad;
this.sexo = sexo;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

public Long getEdad() {
return edad;
}

public void setEdad(Long edad) {
this.edad = edad;
}

public Sexo getSexo() {
return sexo;
}

public void setSexo(Sexo sexo) {
this.sexo = sexo;
}

@Override
public String toString() {

return "Usuario{" +
"id=" + id +
", nombre='" + nombre + '\'' +
", edad='" + edad + '\'' +
", sexo=" + sexo +
'}';
}
}

 

3. Agregamos la interfaz que habla con la BD.

/**
* Código generado por Gerado Pucheta Figueroa
* Twitter: @ledzedev
* http://ledze.mx
* 11/Nov/2016.
*/
@RepositoryRestResource
interface UsuarioRepositorio extends JpaRepository<Usuario, Long> {

Collection<Usuario> findByNombre(@Param("nom") String nombre);
}

 

4. A la clase principal "LedzedevSpringBootDatarestApplication", le agregamos el CommandLineRunner para la carga inicial de nuestro servicio Rest.

- Agregamos 6 usuarios a la BD, como carga inicial y escribimos un log para indicar que la carga se realizó.


/**
* Código generado por Gerado Pucheta Figueroa
* Twitter: @ledzedev
* http://ledze.mx
* 11/Nov/2016.
*/
@Bean
CommandLineRunner runner(UsuarioRepositorio ur){
return x ->{
Arrays.asList(
new Usuario("Gerardo", 36L, Sexo.M) ,
new Usuario("Fidel", 33L, Sexo.M) ,
new Usuario("Hugo", 32L, Sexo.M) ,
new Usuario("Sarai", 27L, Sexo.F) ,
new Usuario("Anallely", 32L, Sexo.F) ,
new Usuario("Maribel", 35L, Sexo.F)
).forEach(ur::save);

log.info("Carga inicial en BD - Hecha.");
};
}

 

Resultados

- Corremos el main de nuestra clase LedzedevSpringBootDatarestApplication y como resultado debemos ver el texto del log que escribimos.

 

 

 

- Abrimos nuestro browser (Google Chrome en mi caso)

- http://localhost:8080/usuarios

El resultado nos debe mandar el json enriquecido (así lo llamo) de todas las propiedades que necesitamos.


 

NOTA: Podemos observar que a diferencia de un servicio RESTful simple, los servicios RESTful basados en hypermedia nos devuelven mas información valiosa y de hecho nos devuelve por defecto la paginación; lo único que tenemos que hacer es ver la definición original del servicio y ver como se puede mandar a llamar la paginación.

 

Tecleamos http://localhost:8080 y nos devuelve en automático la definición y el profile(que son las definiciones de todos los métodos)

El resultado de llamar con paginación. Por ejemplo:

Quiero la página 0.

Quiero que el tamaño de la página sea de 2 Usuarios (como tenemos 6 usuarios, tengo posibilidad de 3 páginas)

IMPORTANTE: el índice de las páginas empieza en cero, así que la 2a página sería la número 1, la 3a página, sería la número 2, etc. Ver la imagen a continuación.

Por default el servicio me devuelve los links para el manejo de la paginación (first, serlf, next, last).

 

- Por último probamos nuestro método para buscar por la propiedad nombre.

 

- Extra bonus

Agregar una propiedad al JSON que nos devuelve el servicio RESTful (basado en hypermedia)

Agregamos un ResourceProcessor y agregamos la propiedad que necesitamos:

/**
* Código generado por Gerado Pucheta Figueroa
* Twitter: @ledzedev
* http://ledze.mx
* 11/Nov/2016.
*/
@Component
class UsuarioResourceProcessor implements ResourceProcessor<Resource<Usuario>> {


@Override
public Resource<Usuario> process(Resource<Usuario> usuarioResource) {

usuarioResource.add(new Link("http://localhost:8080/images/usuario_"+usuarioResource.getContent().getId() + ".jpg","foto-perfil"));
return usuarioResource;
}
}

El resultado después de reiniciar nuestro servicio queda de la siguiente forma:

 

Te puedes descargar mi código directamente de mi repositorio en github o te los puedes descargar en formato zip.

 

Artículos Relacionados

- Spring Boot INITIALIZR
- Spring Boot - Servicio RESTful con Base de Datos

Documentación original

- Accessing JPA Data with REST / Accediendo a datos JPA con REST