miércoles, 23 de noviembre de 2016

Vaadin 7 + Grails 3.2 Plugin Spring-Boot

Para aquellos amantes de aplicaciones Grails, pero que desean un toque de UI con Vaadin pueden usar de lleno el plugin que propicia oficialmente Vaadin en su web que se integra a Spring y Spring-Boot.

Un proyecto completo y funcional con solo el Vaadin plugin oficial, un adicional para compilar widgets y otros pequeños elementos de configuración de Grails es todo lo que necesitaremos.

Demo Git Repositorio grails3vaadinspringboot


Como se hace?


Lo primero que debemos hacer es iniciar un proyecto Grails (La demo es 3.2.3) como de costumbre en nuestro IDE preferido (IntelliJ fue el usado en mi caso)

Una vez creado pasamos a configurar nuestro build.gradle para las dependencias deseadas con las siguientes instrucciones:

  • Agregamos esto para configurar un caso de Vaadin que da problemas con el hibernate
    configurations {
        //noinspection GroovyAssignabilityCheck
        'vaadin-client' {
            resolutionStrategy.force "javax.validation:validation-api:1.0.0.GA"
            exclude module: 'spring-boot-starter-web'
            exclude module: 'spring-boot-vaadin'
        }
    }
    
    
  • Adicionamos los repositorios tantos a el caso normal como el buildscript
    maven { url "https://repo.spring.io/libs-release" }
    maven { url "http://maven.vaadin.com/vaadin-addons" }
    maven { url "https://plugins.gradle.org/m2/" }
    
    
  • Adicionamos un Boom para que siempre busque tope en las dependencias
    mavenBom "com.vaadin:vaadin-bom:$vaadinVersion"
    
    
  • Adicionamos las dependencias deseadas (Pueden agregar los plugins si desean)
    compile "com.vaadin:vaadin-spring-boot-starter:$vaadinSpringVersion"
    compile "com.vaadin:vaadin-spring-boot:$vaadinSpringVersion"
    compile "com.vaadin:vaadin-push:$vaadinVersion"
    
    
  • Una vez aqui solo falta configurar un plugin en el classpath para poder compilar los elementos de Vaadin
    
    classpath "fi.jasoft.plugin:gradle-vaadin-plugin:$vaadinGradleVersion"
    
    
  • Configuramos el plugin extra para que nos trabaje con los elementos deseados.vaadin {
    //noinspection GroovyAssignabilityCheck
    version "$vaadinVersion"
    widgetset 'AppWidgetSet'
    vaadinTestbench.enabled = false
    }
  • Ahora activamos el plugin para que trabaje.
    apply plugin: fi.jasoft.plugin.GradleVaadinGroovyPlugin
  • Por Ultimo refrescamos las dependencias y vemos que se descarguen todos los elementos y configure correctamente.

En fin el resultado del archivo tiene que ser este (Conste que la versión de Grails influye en las dependencias):

import fi.jasoft.plugin.GradleVaadinGroovyPlugin

buildscript {
    repositories {
        mavenLocal()
        maven { url "https://repo.grails.org/grails/core" }
        maven { url "https://repo.spring.io/libs-release" }
        maven { url "http://maven.vaadin.com/vaadin-addons" }
        maven { url "https://plugins.gradle.org/m2/" }
    }
    dependencies {
        classpath "org.grails:grails-gradle-plugin:$grailsVersion"
        classpath "com.bertramlabs.plugins:asset-pipeline-gradle:2.11.6"
        classpath "org.grails.plugins:hibernate5:6.0.4"
        classpath "fi.jasoft.plugin:gradle-vaadin-plugin:$vaadinGradleVersion"
    }
}

version "1.0.0.0"
group "grails3vaadinspringboot"

apply plugin: "eclipse"
apply plugin: "idea"
apply plugin: "war"
apply plugin: 'groovy' // Need it
apply plugin: "org.grails.grails-web"
apply plugin: "org.grails.grails-gsp"
apply plugin: "asset-pipeline"
apply plugin: GradleVaadinGroovyPlugin

configurations {
    //noinspection GroovyAssignabilityCheck
    'vaadin-client' {
        resolutionStrategy.force "javax.validation:validation-api:1.0.0.GA"
        exclude module: 'spring-boot-starter-web'
        exclude module: 'spring-boot-vaadin'
    }
}

repositories {
    mavenLocal()
    maven { url "https://repo.grails.org/grails/core" }
    maven { url "https://repo.spring.io/libs-release" }
    maven { url "http://maven.vaadin.com/vaadin-addons" }
    maven { url "https://plugins.gradle.org/m2/" }
}

dependencyManagement {
    imports {
        mavenBom "org.grails:grails-bom:$grailsVersion"
        mavenBom "com.vaadin:vaadin-bom:$vaadinVersion"
    }
    applyMavenExclusions false
}

dependencies {
    compile "org.springframework.boot:spring-boot-starter-logging"
    compile "org.springframework.boot:spring-boot-autoconfigure"
    compile "org.grails:grails-core"
    compile "org.springframework.boot:spring-boot-starter-actuator"
    compile "org.springframework.boot:spring-boot-starter-tomcat"
    compile "org.grails:grails-dependencies"
    compile "org.grails:grails-web-boot"
    compile "org.grails.plugins:cache"
    compile "org.grails.plugins:scaffolding"
    compile "org.grails.plugins:hibernate5"
    compile "org.hibernate:hibernate-core:5.1.2.Final"
    compile "org.hibernate:hibernate-ehcache:5.1.2.Final"
    console "org.grails:grails-console"
    profile "org.grails.profiles:web"
    runtime "com.bertramlabs.plugins:asset-pipeline-grails:2.11.6"
    runtime "com.h2database:h2"
    testCompile "org.grails:grails-plugin-testing"
    testCompile "org.grails.plugins:geb"
    testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
    testRuntime "net.sourceforge.htmlunit:htmlunit:2.18"

    compile "com.vaadin:vaadin-spring-boot-starter:$vaadinSpringVersion"
    compile "com.vaadin:vaadin-spring-boot:$vaadinSpringVersion"

    compile "com.vaadin:vaadin-push:$vaadinVersion"

    // Vaadin plugins
    compile("org.vaadin.addons.lazyquerycontainer:vaadin-lazyquerycontainer:7.6.1.3") {
        transitive = false
    }
    compile "org.vaadin.addons:fontawesomelabel:1.3.4"
}

bootRun {
    jvmArgs = ['-Dspring.output.ansi.enabled=always']
}

assets {
    minifyJs = true
    minifyCss = true
}

vaadin {
    //noinspection GroovyAssignabilityCheck
    version "$vaadinVersion"
    widgetset 'AppWidgetSet'
    vaadinTestbench.enabled = false
}


Con esto realizado el proyecto funciona?, No!, aun nos faltan unos elementos

Dentro del proyecto realizaremos unos cambios menores para hacer que Grails nos ejecute el caso de Vaadin adicionando un decorador a el main de la aplicación que se encuentra en grails-ppp y en la carpeta init "Application.groovy"

@ComponentScan(["my.package.one", "my.package.two"])

Debe quedar así

package grails3vaadinspringboot

import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.context.annotation.ComponentScan

@ComponentScan(["grails3vaadinspringboot", "com.alsnightsoft.vaadin.demo"])
class Application extends GrailsAutoConfiguration {
    static void main(String[] args) {
        GrailsApp.run(Application, args)
    }
}

Una vez hecho lo anterior nos falta crear el Bean que configura a Vaadin en nuestro Grails, ya como dimos los paquetes que usaremos en nuestro proyecto solo debemos crear una clase en donde nuestro ComponentScan la encuentre y esta debe quedar así:

package com.alsnightsoft.vaadin.demo.utils.configurations

import com.vaadin.spring.annotation.EnableVaadin
import com.vaadin.spring.server.SpringVaadinServlet
import groovy.transform.CompileStatic
import org.springframework.boot.web.servlet.ServletRegistrationBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

/**
 *  Created by aluis on 7/4/16.
 */
@SuppressWarnings("GroovyUnusedDeclaration")
@Configuration
@EnableVaadin
@CompileStatic
class VaadinConfiguration {

    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        return new ServletRegistrationBean(new SpringVaadinServlet(), "/*", "/VAADIN/*")
    }
}

Ahora que ya nuestro proyecto encontrará la configuración que nos falta configuraremos la UI quedándonos como ejemplo esta:

import com.vaadin.annotations.Push
import com.vaadin.annotations.Theme
import com.vaadin.annotations.Widgetset
import com.vaadin.server.VaadinRequest
import com.vaadin.spring.annotation.SpringUI
import com.vaadin.ui.Label
import com.vaadin.ui.UI
import groovy.transform.CompileStatic

/**
 *  Created by aluis on 11/22/16.
 */
@Push
@Theme("valo")
@Widgetset("AppWidgetSet")
@SpringUI(path = "/")
@CompileStatic
class DemoUI extends UI {

    @Override
    protected void init(VaadinRequest vaadinRequest) {
        setContent(new Label("Work!"))
    }
}

Por fin nuestro proyecto esta listo para arrancar, pero puede darnos unos pequeños problemas con los widgets (puede que con el theme sino sabemos configurarlo), pero tranquilos!, solo es correr 2 simples comandos de Gradle para que nos agregue el AppWidgetSet y los compile que son los siguientes (usando IntelliJ solo vamos a la pestaña de Gradle y en Vaadin le damos doble click a esos métodos)


  1. vaadinUpdateWidgetset
  2. vaadinCompile

Con esto corremos el proyecto en BootRun o en modo Grails y tendremos un poco para jugar. En el demo se usan algunas clases auxiliares para el patrón I18N y dar paso a los servicios, así como la implementación del multi idioma.