API REST 3. Publicar y consumir

Descripción

Publicar y consumir algunos métodos creados del API REST.

Publicar y Consumir

Usando CRUD

Simplemente usando los métodos que ya nos proporciona el CRUD

Crear Persona

Insertamos un nuevo registro a la tabla Persona.

  1. En la clase PersonaController
  2. Se mapea con /add
  3. Recibe los parámetros nombre, edad y sexo
  4. Se carga el Objeto Persona y se ejecuta la función save().
  5. Retorna el mensaje Agregado correctamente.
    @RequestMapping("/add")
    public String addPersona(@RequestParam  String nombre,@RequestParam  int edad,@RequestParam  String sexo) {
       Persona p = new Persona();
       p.setNombre(nombre);
       p.setEdad(edad);
       p.setSexo(sexo);
       personaRepository.save(p);
    		
       return "Agregado correctamente";
    }

     

Resultado

Consultar todas las Personas

Consultamos todos los registros de la tabla Persona.

  1. En la clase PersonaController
  2. Se mapea con /all
  3. No recibe parámetros
  4. Retorna el resultado de la función findAll().
    @RequestMapping("/all")
       public Iterable<Persona> getPersona() {
       return personaRepository.findAll();
    }

Resultado

Borra una Persona

Borramos un registro de la tabla Persona.

  1. En la clase PersonaController
  2. Se mapea con /delete
  3. Recibe el parámetro id
  4. Se carga el Objeto Persona y se ejecuta la función delete().
  5. Retorna el mensaje Borrado correctamente.
    @RequestMapping("/delete")
     public String deletePersona(@RequestParam int id) {
     Persona p = new Persona();
     p.setIdPersona(id);
     personaRepository.delete(p);
     return "Borrado correctamente";
     }
    

Resultado

Total de Personas

Total de registros de la tabla Persona.

  1. En la clase PersonaController
  2. Se mapea con /total
  3. No recibe parámetros
  4. Retorna el resultado de la función count().
    @RequestMapping("/total")
       public long totalPersona() { 
       return personaRepository.count();
    }

Resultado

Creamos consultas propias

Podemos crear otras consultas de acuerdo a nuestras necesidades

Persona por tipo de sexo

Obtenemos las Personas por su tipo de sexo

  1. En la interface PersonaRepository agregamos la consulta que filtra por tipo de sexo
    @Query("select p from Persona p where p.sexo = ?1")
    Iterable<Persona> findBySexo(String sexo);
  2. En la clase PersonaController
  3. Se mapea con /allBySexo
  4. Recibe el parámetro sexo
  5. Retorna el resultado de la función findBySexo().
    @RequestMapping("/allBySexo")
    public Iterable<Persona> getPersonaBySexo(@RequestParam String sexo) {
       return personaRepository.findBySexo(sexo);
    }

Resultado

Persona por tipo de sexo con paginado

Obtenemos las Personas por su tipo de sexo. Los resultados se muestran paginados.

  1. En la interface PersonaRepository agregamos la consulta que filtra por tipo de sexo y agrega paginado.
    @Query("select p from Persona p where p.sexo = ?1")
    Page<Iterable<Persona>> findBySexoPag(@Param("sexo") String sexo,Pageable pageable);
  2. En la clase PersonaController
  3. Se mapea con /sexoPag
  4. Recibe los parámetros sexo, inicio y bloque. Estos 2 últimos parámetros para el paginado.
  5. Se pasa los parámetros de paginado a la función findBySexoPag()
  6. Retorna el resultado de la función findBySexoPag().
    @RequestMapping(value="/sexoPag")
       public Page<Iterable<Persona>> personaPag(@RequestParam String sexo,@RequestParam int inicio,@RequestParam int bloque) {
       return personaRepository.findBySexoPag(sexo, new PageRequest(inicio, bloque));
    }

Resultado

Persona por tipo de sexo con paginado y ordenado por un campo

Obtenemos las Personas por su tipo de sexo. Los resultados se muestran paginados y ordenados por un campo.

  1. En la clase PersonaController
  2. Se mapea con /sexoOrder
  3. Recibe los parámetros sexo, inicio, bloque y orden.
  4. Se pasa los parámetros de paginado y orden a la función findBySexoPag()
  5. Retorna el resultado de la función findBySexoPag().
    @RequestMapping(value="/sexoOrder")
       public Page<Iterable<Persona>> personaOrder(@RequestParam String sexo,@RequestParam int inicio,@RequestParam int bloque,@RequestParam String orden) {
       return personaRepository.findBySexoPag(sexo, new PageRequest(inicio, bloque,Sort.Direction.ASC, orden));
    }

Resultado

Otras opciones

Podemos crear otras consultas con otros métodos HTTP; POST, PUT, DELETE  o PATCH. También enviando HEAD en la petición.

Agregar Persona con el método POST

@RequestMapping(value="/add",method=RequestMethod.POST)
   public String addPersonaPost(@RequestParam  String nombre,@RequestParam  int edad,@RequestParam  String sexo) {
   Persona p = new Persona();
   p.setNombre(nombre);
   p.setEdad(edad);
   p.setSexo(sexo);
   personaRepository.save(p);
   return "Agregado correctamente";
}

Resultado. Utilizando curl:

Obtener Personas del sexo=M mediante HEAD

@RequestMapping(value="/sexo",headers={"sexo=M"})
   public Iterable<Persona> personaM() {
   return personaRepository.findBySexo("M");
}

Resultado. Utilizando curl:

Otros

Descargar Proyecto

Se puede descargar el proyecto completo de https://github.com/arielolivagh/gs-rest-service-complete/tree/v2.0

SpringBoot 8. Kanban con JPA

Clase DatabaseConfig.java

Es necesario agregar las clase DatabaseConfig.java en el paquete com.proyecto.config para el acceso a la Base de Datos. Su contenido es:

package com.proyecto.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Contains database configurations.
 */
@Configuration
@EnableTransactionManagement
public class DatabaseConfig {

  // ------------------------
  // PUBLIC METHODS
  // ------------------------

  /**
   * DataSource definition for database connection. Settings are read from
   * the application.properties file (using the env object).
   */
  @Bean
  public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("db.driver"));
    dataSource.setUrl(env.getProperty("db.url"));
    dataSource.setUsername(env.getProperty("db.username"));
    dataSource.setPassword(env.getProperty("db.password"));
    return dataSource;
  }

  /**
   * Declare the JPA entity manager factory.
   */
  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean entityManagerFactory =
        new LocalContainerEntityManagerFactoryBean();
    
    entityManagerFactory.setDataSource(dataSource);
    
    // Classpath scanning of @Component, @Service, etc annotated class
    entityManagerFactory.setPackagesToScan(
        env.getProperty("entitymanager.packagesToScan"));
    
    // Vendor adapter
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
    
    // Hibernate properties
    Properties additionalProperties = new Properties();
    additionalProperties.put(
        "hibernate.dialect", 
        env.getProperty("hibernate.dialect"));
    additionalProperties.put(
        "hibernate.show_sql", 
        env.getProperty("hibernate.show_sql"));
    additionalProperties.put(
        "hibernate.hbm2ddl.auto", 
        env.getProperty("hibernate.hbm2ddl.auto"));
    entityManagerFactory.setJpaProperties(additionalProperties);
    
    return entityManagerFactory;
  }

  /**
   * Declare the transaction manager.
   */
  @Bean
  public JpaTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = 
        new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(
        entityManagerFactory.getObject());
    return transactionManager;
  }
  
  /**
   * PersistenceExceptionTranslationPostProcessor is a bean post processor
   * which adds an advisor to any bean annotated with Repository so that any
   * platform-specific exceptions are caught and then rethrown as one
   * Spring's unchecked data access exceptions (i.e. a subclass of 
   * DataAccessException).
   */
  @Bean
  public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
  }


  // ------------------------
  // PRIVATE FIELDS
  // ------------------------
  
  @Autowired
  private Environment env;

  @Autowired
  private DataSource dataSource;

  @Autowired
  private LocalContainerEntityManagerFactoryBean entityManagerFactory;


} // class DatabaseConfig

Agregamos la dependencia del conector mysql en el archivo pom.xml.

    	<dependency>
      		<groupId>mysql</groupId>
      		<artifactId>mysql-connector-java</artifactId>
    	</dependency>

Y agregamos los datos de conexión en application.properties.

# Database
db.driver: com.mysql.jdbc.Driver
db.url: jdbc:mysql://localhost:3306/kanban?zeroDateTimeBehavior=convertToNull
db.username: root
db.password: root

# Hibernate
hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql: true
hibernate.hbm2ddl.auto: update
entitymanager.packagesToScan:com.proyecto

Crear repositorios

Los repositorios (Repository) son interfaces que contienen los métodos necesarios para el acceso a Base de Datos.

Vamos a generar las clases RepositoryArticle y RepositoryColumn en el paquete com.proyecto.repository.

Clase RepositoryArticle:

package com.proyecto.repository;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.proyecto.model.Article;

@Repository
@Transactional
public class RepositoryArticle {

	public List<Article> getList(){
		return  entityManager.createQuery("from Article").getResultList();
	}
	
	@PersistenceContext
	private EntityManager entityManager; 

}

Clase RepositoryColumn:

package com.proyecto.repository;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.proyecto.model.Column;

@Repository
@Transactional
public class RepositorioColumn {

	public List<Column> getList(){
		return  entityManager.createQuery("from Column").getResultList();
	}
	
	@PersistenceContext
	private EntityManager entityManager; 

}

Crear dominios

Los dominios son clases que implementan los conceptos del problema que estamos resolviendo. En este caso es el modelado de las tablas Article y Column.

Vamos a generar las clases DomainArticle y DomainColumn en el paquete com.proyecto.domain.

Clase DomainArticle:

package com.proyecto.domain;

import java.io.Serializable;

import com.proyecto.model.Column;

public class DomainArticle implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id;
	private String descripcion;
	private String nombre;
	private String titulo;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getDescripcion() {
		return descripcion;
	}
	public void setDescripcion(String descripcion) {
		this.descripcion = descripcion;
	}
	public String getNombre() {
		return nombre;
	}
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	public String getTitulo() {
		return titulo;
	}
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}

}

Clase DomainColumn:

package com.proyecto.domain;

import java.io.Serializable;
import java.util.List;

public class DomainColumn implements Serializable {

	private static final long serialVersionUID = 1L;
	private int id;
	private String titulo;
	private List<DomainArticle> article;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTitulo() {
		return titulo;
	}
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}
	public List<DomainArticle> getArticle() {
		return article;
	}
	public void setArticle(List<DomainArticle> article) {
		this.article = article;
	}
	
}

Modificar Controller

Vamos a modificar los controller para accesar a los datos de las tablas correspondientes.

Clase ControllerArticle

Agregamos

@Autowired
private RepositoryArticle repositoryArticle;

Con esta anotación autoconectamos con el repositorio de Articles.

Creamos el método getList()

@RequestMapping(value="/articulos", method=RequestMethod.GET)
	@ResponseBody
	public List<DomainArticle> getList(){
		List<DomainArticle> articulos = new ArrayList<DomainArticle>();
		List<Article> listArticle = repositoryArticle.getList();
		for (Article article : listArticle) {
			DomainArticle domainArticle = new DomainArticle();
			domainArticle.setId(article.getId());
			domainArticle.setDescripcion(article.getDescripcion());
			domainArticle.setNombre(article.getNombre());
			domainArticle.setTitulo(article.getTitulo());
			
			articulos.add(domainArticle);
		}
		return articulos;
	}
  1. Se conecta al repositorio de Articles y extrae en un List todos los Articles.
  2. Recorremos el arreglo y lo cargamos en su respectivo domain.
  3. Al ejecutar http://localhost:8090/kanban/articulos

Clase ControllerColumn

Agregamos

@Autowired
private RepositoryColumn repositoryColumn;

Con esta anotación autoconectamos con el repositorio de Column.

Creamos el método getList()

@RequestMapping(value="/columnas", method=RequestMethod.GET)
	@ResponseBody
	public List<DomainColumn> getList(){
		List<DomainColumn> columnas = new ArrayList<DomainColumn>();
		List<Column> listColumn = repositoryColumn.getList();
		for (Column colum : listColumn) {
			DomainColumn domainColumn = new DomainColumn();
			domainColumn.setId(colum.getId());
			domainColumn.setTitulo(colum.getTitulo());
			
			List<DomainArticle> articulos = new ArrayList<DomainArticle>();
			for (Article articulo : colum.getArticles()) {
				DomainArticle domainArticle = new DomainArticle();
				domainArticle.setId(articulo.getId());
				domainArticle.setDescripcion(articulo.getDescripcion());
				domainArticle.setNombre(articulo.getNombre());
				domainArticle.setTitulo(articulo.getTitulo());
				articulos.add(domainArticle);
			}
			domainColumn.setArticle(articulos);
			columnas.add(domainColumn);
		}
		return columnas;
	}
  1. Se conecta al repositorio de Column y extrae en un List todos las columnas.
  2. Recorremos el arreglo y lo cargamos en su respectivo domain.
  3. Se extraen los Articles de cada columna y lo agrega a los articulos del dominio.
  4. Al ejecutar http://localhost:8090/kanban/columnas

 

Kanban con JPA

Nuevos archivos js y html

En resources/static/js duplicamos kanbanWeb.js. Le cambiamos el nombre a kanbanjpa.js. Cambiamos  la url a:

url:		"columnas",

y en el método buildsKanban cambiamos la variable columns a:

var columns = data;

En resources/templates duplicamos kanbanWeb.html. Le cambiamos el nombre a kanbanjpa.html. Cambiamos la referencia al script de kanban:

<!-- kanban  -->
<script type="text/javascript" src="js/kanbanjpa.js"	charset="UTF-8"></script>

Crear nuevo Controller

Creamos un nuevo controller en el paquete com.proyecto.controller llamado ControllerKanbanjpa.

package com.proyecto.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class ControllerKanbanjpa {
	@RequestMapping(value = "/jpa",method = RequestMethod.GET)
	public String index(){
		return "kanbanjpa";
	}
}

Al ejecutar http://localhost:8090/kanban/jpa. Tenemos las columnas y artículos de Kanban cargados desde la Base de Datos por medio de JPA.

Se puede descargar el proyecto completo de https://github.com/arielolivagh/kanbanjpa