viernes, 3 de agosto de 2018

Construir Una Aplicación Web Con Vaadin Flow Utilizando Spring Boot, Spring Data Jpa Con Base De Datos Mysql.


Este artículo vamos a crear una aplicación CRUD con una combinación de Spring Data JPA y Vaadin Flow. Por otra parte utilizaremos Spring Boot, que nos facilitara la configuración con JPA. En la parte de la interfaz de usuario se construirá bajo el ambiente Vaadin Flow, como todo sabrán es la nueva versión del framework de Vaadin 10 para construir aplicaciones web modernas. Una de las ventajas que se puede acceder a la API de navegadores, componentes web o incluso elementos DOM simples, directamente desde el lado del servidor de Java. Por lo tanto permitirá a los desarrolladores ser más súper productivo al crear interfaces de usuario en Java o usar plantilla HTML que se puede integrar con cualquier BackEnd que use Java. En este ejemplo utilizaremos la interfaz de usuario en Java. En conclusión o en otras palabras “Vaadin Flow es un framework que va permitir crear aplicaciones web usando web-componentes y Java”

A continuación las herramientas que vamos a utilizar.

REQUISITOS:

Descripción
Software
Link de Descarga
Lenguaje de programación
Java SE 8
Entorno Integrado de Desarrollo (IDE)
Intellij
Framework
Vaadin
Versión 10
Base de Datos
MySQL
https://dev.mysql.com/downloads/mysql/5.7.html
Entorno Integrado GUI
MySQL Workbench

https://dev.mysql.com/downloads/workbench/
Grid Filter Highlighter
Vaadin

Realizare un breve introducción de cada componente que utilizaremos en esta demo, el objetivo es para que las personas que están apenas comenzando en el mundo de los framework’s Spring y Vaadin interactúen de la manera más sencilla posible y que le sirva de guía para emprender un proyecto intermedio o avanzado. 

El proyecto se puede desarrollar de dos formas la primera con Maven y la segunda por bque se puede visualizar en la siguiente dirección https://start.spring.io. Por lo tanto este proyecto lo desarrollaremos con la segunda opción.

  • Que es MAVEN?

Apache Maven es una herramienta de gestión de proyectos de software. La base de Maven es el modelo de objetos del proyecto “pom”. El objetivo de Maven es facilita y unifica el proceso de desarrollo de software. 

El “pom” es un archivo pom.xml que contiene información básica sobre el proyecto. La información básica sobre el proyecto se puede encontrar al principio del archivo pom.xml, que define, por ejemplo, la versión de la aplicación, el formato del paquete, etc.

La versión mínima del archivo pom.xml debe contener la raíz del proyecto, modelVersion groupId, artifactId y versión, como se puede observar en la Figura 1.


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.gmendozag.co</groupId>
 <artifactId>Crud-Vaadin</artifactId>
 <version>1.0-SNAPSHOT</version>

 <name>Crud-Vaadin</name>
 <description>Aplicación de Spring Boot y Vaadin</description>
Figura 1

Las dependencias se definen dentro de la sección de dependencias, como se puede observar en la Figura 2:

<dependencies>
    <dependency>            
        <groupId>org.springframework.boot </groupId>
 <artifactId>spring-boot-starter-data-jpa</artifactId>
     </dependency>
     <dependency>   
         <groupId>com.vaadin</groupId>
  <artifactId>vaadin-spring-boot-starter</artifactId>
     </dependency>
     <dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <scope>runtime</scope>
     </dependency>
     <dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <scope>runtime</scope>
     </dependency>
     <dependency>   
         <groupId>net.amahdy</groupId>
  <artifactId>vaadin-grid-filter-h-flow</artifactId>
  <version>1.0.0</version>
     </dependency>
</dependencies>
Figura 2

  • CREAR UN PROYECTO BASADO EN SPRING INITIALIZR:
Crearemos nuestro proyecto de BackEnd con Spring Intializr, es una herramienta basada en web, fácil para crear nuevas aplicaciones basada en Spring o crear proyectos Spring Boot. Spring Intializr se puede encontrar en https://start.spring.io Como se puede observar en la Figura 3.

  
Figura 3

La diferencia de Spring Initializr y Spring Boot es:
 
Spring Initializr es una herramienta basada en la web que le permite crear esqueletos de proyectos para aplicaciones Spring.

Spring Boot simplifica el proceso de desarrollo de aplicaciones de Spring.

Generaremos el proyecto con Maven, seleccionamos Java y la última versión de Spring Boot. En el campo Grupo, definiremos nuestro ID de grupo, que también se convertirá en un paquete base en nuestro proyecto Java. En el campo Artefacto, definiremos el ID del artefacto, que también será el nombre de nuestro proyecto en Intellij.

En la sección Dependencias, seleccionaremos las dependencias que se necesitan en nuestro proyecto, para este proyecto seleccionamos las siguientes dependencias Vaadin, JPA y MySQL. Spring Boot proporciona paquetes iniciales que simplifican su configuración de Maven. Los iniciadores Spring Boot son en realidad un conjunto de dependencias que puede incluir en su proyecto. Puede escribir las dependencias en el campo de búsqueda o cambiar a la versión completa y ver todos los paquetes de inicio y las dependencias disponibles:

Para crear una nueva aplicación, nos dirigimos a la siguiente dirección http://start.spring.io y agregue las dependencias de Vaadin y MySQL como se muestra en la siguiente Figura 4:

Generar en: Maven Project
Con: Java
Spring Boot: 2.0.3
  • DATOS DEL PROYECTO
Group: com.gmendoza
Artifact: democrud
Name: democrud
Descripción: *Opcional
Package Name: com.gmendoza.democrud
Packaging: Jar
Java Version: 8
  • DEPENDENCIAS
Vaadin, JPA, MySQL

Figura 4

Haga clic en el botón Generar Proyecto y extraiga el archivo zip generado. Debería obtener un proyecto Maven que puede importar a su IDE favorito, en este ejemplo utilizaremos el poderoso Intellij.
  • CREAR BASE DE DATOS EN MYSQL
Podemos utilizar el editor de MySQL Workbench como se muestra en la figura 5 o línea de comando con la siguiente instrucción CREATE DATABASE DEMO;

Figura 5

  • USO DE JPA PARA CREAR Y ACCEDER A UNA BASE DE DATOS
Crearemos una base de datos usando clases de entidad. 

Utilizaremos MySQL una base de datos SQL es realmente buena para un rápido desarrollo o demostración. 
  • CONCEPTOS BÁSICOS DE ORM, JPA E HIBERNATE 
Object-Relational Mapping (ORM) es una técnica que permite buscar y manipular desde una base de datos utilizando un paradigma de programación orientado a objetos. ORM es muy bueno para los programadores porque se basa en conceptos orientados a objetos. También facilita el desarrollo sea mucho más rápido y reduce la cantidad de código fuente. Por lo tanto “ORM” en su mayoría es independiente de cualquier base de datos, por lo cual los desarrolladores no tienen que preocuparse por las declaraciones SQL específicas del proveedor. 
La API persistente de Java (JPA) proporciona mapeo relacional de objetos para desarrolladores de Java. La entidad JPA es una clase Java que presenta la estructura de una tabla de base de datos. Los campos de una clase de entidad presentan las columnas de las tablas de la base de datos.

Hibernate es la implementación de JPA basada en Java más popular, y en este caso se usa en Spring Boot como valor predeterminado. Hibernate es un producto maduro y es ampliamente utilizado en aplicaciones a gran escala.
  • CREANDO LAS CLASES DE ENTIDAD
Una clase de entidad es una clase Java simple que se anota con la anotación @Entity de JPA. Las clases de entidad usan la convención de nomenclatura de JavaBean estándar y tienen los métodos apropiados getter y setter. Los campos de clase tienen visibilidad privada.

JPA crea una tabla en la base de datos con el nombre de la clase cuando se inicializa la aplicación. Si desea utilizar algún otro nombre para la tabla de la base de datos, puede usar la anotación @Table.

Para poder usar JPA y la base de datos MySQL, debemos tener las siguientes dependencias dentro del archivo pom.xml como se muestra en la Figura 6 y 7:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Figura 6


<dependency>    
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
Figura 7

  • CREAR PROYECTO EN INTELLIJ
Abrimos la ventana de Terminal y nos ubicamos dentro de la caperta del proyecto, comenzamos por crear un nuevo módulo de Maven usando el arquetipo de maven-archetype-simple de la siguiente manera: 

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes - DarchetypeArtifactId=maven-archetype-quickstart
Utilice las siguientes propiedades cuando se le solicite: 
  • groupId: com.gmendozag.co 
  • artifactId: Crud-Vaadin 
  • version: 1.0-SNAPSHOT 
  • package: com.gmendozag.co 
Hemos creado el proyecto como se puede observar en la Figura 8, adicionalmente se agregó los paquetes Entity, Repositorio y UI.

Figura 8

El siguiente paso vamos a crear la Clase Entidad con el nombre Cliente, en la parte superior colocamos la anotación Entity que se importa desde el paquete javax.persistence.

A continuación, agregamos algunos campos a nuestra clase. Los campos de la clase de entidad son asignados a columnas de tabla de la base de datos. Tener en cuenta que la clase de entidad debe contener una ID única que se utiliza como clave principal de la base de datos, como se puede observar en las Figura 9 y 10.


package com.gmendozag.co.Entity;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@Entity
public class Cliente {


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull(message = "Nombre Requerido")
    @Size(min = 3, max = 50, message = "El nombre debe estar en el rango, como minimo 3 y como maximo 50 caracteres")
    private String nombre;

    private String apellido;

    private String telefono;

    @NotNull(message = "Email es Requerido")
    @Pattern(regexp = ".+@.+\\.[a-z]+", message = "\n" + "Debe ser un correo electrónico válido")
    private String email;
Figura 9


public Cliente() { }

    public Cliente(String nombre, String apellido) {
        this.nombre=nombre;
        this.apellido=apellido;
    }

    public Cliente(String nombre, String apellido, String telefono, String email) {
        this.nombre = nombre;
        this.apellido = apellido;
        this.telefono=telefono;
        this.email=email;
    }

    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 String getApellido() {return apellido;}

    public void setApellido(String apellido){this.apellido = apellido;}

    public String getTelefono() {return telefono;}

    public void setTelefono(String telefono){this.telefono = telefono;}

    public String getEmail() {return email;}

    public void setEmail(String email) {this.email = email;} 
Figura 10

  • CREACIÓN CRUD REPOSITORIO
El Spring Boot Data JPA proporciona una interfaz CrudRepository para las operaciones CRUD, dándole funcionalidades a la clase entidad.
Ahora creamos nuestro repostorio la clase Repositorio dentro del paquete Repoistorio de la siguiente manera como se puede observar en la figura 11, creamos una clase llamada ClienteRepository. En el siguiente paso agregamos dos (2) métodos de búsquedas. El metodo findByApellidoStartsWithIgnoreCase es para realizar la consulta en este caso por apellido del cliente.


package com.gmendozag.co.Repositorio;

import com.gmendozag.co.Entity.Cliente;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ClienteRepository extends JpaRepository<Cliente, Long> {

    List<Cliente> findByApellidoStartsWithIgnoreCase(String apellido);

    List<Cliente> findAllBy(Pageable pageable);

    List<Cliente> findByApellidoLikeIgnoreCase(String nameFilter);

    // For lazy loading and filtering
    List<Cliente> findByApellidoLikeIgnoreCase(String nameFilter, Pageable pageable);

    long countByApellidoLikeIgnoreCase(String nameFilter);

    List<Cliente> findAll();
}
Figura 11

  • CONFIGURACIÓN DEL ARCHIVO APPLICTION.PROPERTIES 
Este archivo de se puede encontrar dentro la carpeta resources, en este archivo configuramos la conexión con la base de datos MySQL, como se puede observar en la Figura 12.


spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=

spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto = update

# Naming strategy
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy

# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
Figura 12

Ahora viene los más importante crear la UI del proyecto nada más y nada menos con Vaadin Flow.

Adicionamos la clase MainView que extiende de VerticalLayout en esta clase, como se puede observar la Figura 13 y 14.


@Route
@Theme(value = Lumo.class, variant = Lumo.LIGHT)
public class MainView extends VerticalLayout {

    private final ClienteRepository repo;
    private final ClienteEditor editor;
    final Grid<Cliente> grid;
    final TextField filter;
    private final Button addNewBtn, addNewBtnCar;

    public MainView(ClienteRepository repo, ClienteEditor editor) {

        this.repo = repo;
        this.editor = editor;
        this.grid = new Grid<>(Cliente.class);
        this.filter = new TextField();
        this.addNewBtn = new Button("Nuevo Cliente", VaadinIcon.PLUS.create());
        this.addNewBtnCar = new Button("Nuevo Vehiculo", VaadinIcon.PLUS.create());

        HorizontalLayout actions = new HorizontalLayout(filter, addNewBtn);

        add(actions, grid, editor);

        grid.setHeight("300px");
        grid.setColumns("id","email","telefono","nombre");
        grid.getColumnByKey("id").setWidth("50px").setFlexGrow(0);
Figura 13


filter.setPlaceholder("Filtro por Apellido");
        filter.setValueChangeMode(ValueChangeMode.EAGER);
        filter.addValueChangeListener(e -> listCustomers(e.getValue()));

        grid.addColumn(new ComponentRenderer<>(VaadinGridFilterH::new,
                   (highlighter, person) -> {
              highlighter.setItem(person.getApellido());
              highlighter.setFilter(filter.getValue());
            })).setHeader("Apellido");

        grid.asSingleSelect().addValueChangeListener(e -> {
            editor.editCustomer(e.getValue());
        });


        addNewBtn.addClickListener(e -> editor.editCustomer(new Cliente("", "")));
        // Listen changes made by the editor, refresh data from backend
        editor.setChangeHandler(() -> {
            editor.setVisible(false);
            listCustomers(filter.getValue());
        });
        listCustomers(null);
    }

    void listCustomers(String filterText) {
        if (StringUtils.isEmpty(filterText)) {
            grid.setItems(repo.findAll());
        }
        else {
            grid.setItems(repo.findByApellidoStartsWithIgnoreCase(filterText));
        }
    }
Figura 14

En el siguiente paso creamos la clase ClienteEditor, este formulario contendrá todo lo relacionado con el nuevo cliente, actualización o eliminación, como se puede observar la Figura 15.


@SpringComponent
@UIScope
public class ClienteEditor extends VerticalLayout implements KeyNotifier {

    private final ClienteRepository repository;

    private Cliente cliente;

    /* Campos entidad Cliente */
    TextField nombre = new TextField("Nombre");
    TextField apellido = new TextField("Apellido");
    TextField email = new TextField("Email");
    TextField telefono = new TextField("Telefono");

    /* Acciones botonos */
    Button save = new Button("Guardar", VaadinIcon.CHECK.create());
    Button cancel = new Button("Cancelar");
    Button delete = new Button("Eliminar", VaadinIcon.TRASH.create());
    HorizontalLayout actions = new HorizontalLayout(save, cancel, delete);
    Binder<Cliente> binder = new Binder<>(Cliente.class);
    private ChangeHandler changeHandler;
Figura 15

Si quieren detallar más sobre el formulario aquí le dejo la entrada anterior donde explico con detalle la parte del Diseño. https://geovanny0401.blogspot.com/2018/06/desarrollar-aplicaciones-web-java-sin.html.

Por ultimo adicionamos el RESALTADOR GRID Basado en https://github.com/amahdy/vaadin-grid-filter-h, Resalta todas las letras en los elementos de Grid de un texto de filtro dado. Por A.Mahdy AbdelAziz

Agregamos la siguiente dependencia al archivo Maven pom.xml, como se muestra en la Figura 16.

<dependency>
    <groupId>net.amahdy</groupId>
    <artifactId>vaadin-grid-filter-h-flow</artifactId>
    <version>1.0.0</version>
</dependency>

<repositories>
    <repository>
 <id>vaadin-addons</id>
 <url>http://maven.vaadin.com/vaadin-addons</url>
    </repository>
</repositories>
Figura 16

En el archivo MainView agregamos el siguiente código como se muestra en la Figura 17.

grid.addColumn(new ComponentRenderer<>(VaadinGridFilterH::new,
                   (highlighter, person) -> {
              highlighter.setItem(person.getApellido());
              highlighter.setFilter(filter.getValue());
            })).setHeader("Apellido");
Figura 17

  • EJECUCIÓN DEL PROYECTO
Para esta demo existen dos (2) formas de ejecutar el proyecto una directamente por el IDE y la segunda con el siguiente comando: mvn spring-boot:run

Ahora, estamos listos para ejecutar nuestra aplicación y navegar a localhost:8080. como se puede observar en la figura 18.

Figura 18

A continuación, presionamos el botón nuevo cliente y lo adicionamos como se puede observar en la figura 19.
Figura 19

Ahora podemos observar como se ve nuestra pagina principal como se puede observar en la figura 20

Figura 20

En la figura 21, como se puede observar se encuentra errado la dirección del email del cliente, realizamos actualizamos los datos
Figura 21


En la figura 22, se encuentra actualizado el dato.
Figura 22

En la figura 23, utilizamos el RESALTADOR GRID consultando los clientes por la Letra M resaltando todos los cliente que comience por dicha letra.


Figura 23

Descargar proyecto final

Estaré haciendo una encuesta por twitter desde mi cuenta @geovanny0401, para que los usuarios escojan por medio de la mejor votación que tema le gustaría para la siguiente publicación.  

REFERENCIAS:
  • https://vaadin.com/flow
  • Libro: Hands-On Full Stack Development with Spring Boot 2.0 and React, By Juha Hinkula
  • https://spring.io/guides/gs/crud-with-vaadin/

5 comentarios:

  1. I need the correct maven settings.xml file as I am getting errors like

    ERROR] /E:/sts-bundle/vaadin/VaadinSpringBoot-LDAP/src/main/java/hello/CustomerRepository.java:[3,47] package org.springframework.data.jpa.repository does not exist
    [ERROR] /E:/sts-bundle/vaadin/VaadinSpringBoot-LDAP/src/main/java/hello/CustomerRepository.java:[7,45] cannot find symbol
    symbol: class JpaRepository
    [ERROR] /E:/sts-bundle/vaadin/VaadinSpringBoot-LDAP/src/main/java/hello/Customer.java:[3,25] package javax.persistence does not exist
    [ERROR] /E:/sts-bundle/vaadin/VaadinSpringBoot-LDAP/src/main/java/hello/Customer.java:[4,25] package javax.persistence does not exist
    [ERROR] /E:/sts-bundle/vaadin/VaadinSpringBoot-LDAP/src/main/java/hello/Customer.java:[5,25] package javax.persistence does not exist

    ResponderEliminar
  2. Buenos días,

    Java son trata de eliminar ~/.m2/repository al parecer es un problema de configuración.

    Saludos,

    ResponderEliminar
  3. Estos formularios son Responsives? o hay que hacerle algo adicional

    ResponderEliminar