style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Grails ... un ejemplo

ec564-shomecode4

En este post crearemos un mini sistema para la gestión de tickets de soporte técnico.

¿Qué necesitamos?

  1. Tener instalado el JDK 8
  2. Tener instalado Grails
  3. Tener una BD (usaremos PostgreSQL en este ejemplo)

Tenemos los departamentos o áreas ).

areas

Se levantan los tickets

tickets

El encargado de dar soporte técnico responderá a las peticiones.

respuesta

Analizamos las relaciones.

Un Departamento tiene muchos Ticket(s)

Un Ticket pertenece a un Departamento

Una Respuesta pertenece a un Ticket

Tendremos en total tres clases:

  1. Departamento.groovy
  2. Ticket.groovy
  3. Respuesta.groovy

c2cd9-seleccic3b3n_008

Primer paso: crear el proyecto

$ grails create-app crud-app

Segundo paso: ubicarnos en la carpeta del proyecto creado

$ cd crud-app

Tercer paso: crear las tres clases

$ grails create-domain-class com.codemonkey.model.Departamento
$ grails create-domain-class com.codemonkey.model.Ticket
$ grails create-domain-class com.codemonkey.model.Respuesta

Departamento.groovy

package com.codemonkey.model

class Departamento {
    int iddepartamento
    String nombre
    String responsable

    static constraints = {
        nombre(blank: false)
        responsable(blank: false)
    }

    //Un Departamento tiene muchos Tickets
    static hasMany = [tickets: Ticket]

    String toString(){
        "**Departamento\nId:"+id+"\nNombre:"+nombre+"\nResponsable:"+responsable
    }
}

Ticket.groovy

package com.codemonkey.model

class Ticket {
    int idticket
    Date fecha
    String asunto
    String descripcion

    static constraints = {
        asunto(blank: false)
        descripcion(black: false)
    }

    //Una Tickets pertenece a un Departamento
    static belongsTo = [departamentos: Departamento]

    String toString(){
        "**Ticket\nId:"+id+"\nFecha:"+fecha+"\nAsunto:"+asunto+"\nDescripcion:"+descripcion
    }
}

Respuesta.groovy

package com.codemonkey.model

class Respuesta {
    int idrespuesta
    boolean solucionado
    String descripcion

    static constraints = {
        descripcion(blank: false)
    }

    //Una Respuesta pertenece a un Tickets
    static belongsTo = [tickets: Ticket]

    String toString(){
        String result = solucionado == true? "Solucionado" : "En espera"
        "**Respuesta\nId:"+id+"\nDescripcion:"+descripcion+"\nSolucionado:"+result
    }
}

Cuarto paso: configurar las dependencias necesarias y la conexión a la BD

build.gradle

 buildscript {
    repositories {
        mavenLocal()
        maven { url "https://repo.grails.org/grails/core" }
    }
    dependencies {
        classpath "org.grails:grails-gradle-plugin:$grailsVersion"
        classpath "org.grails.plugins:hibernate5:${gormVersion-".RELEASE"}"
        classpath "com.bertramlabs.plugins:asset-pipeline-gradle:2.14.8"
    }
}

version "0.1"
group "crud.app"

apply plugin:"eclipse"
apply plugin:"idea"
apply plugin:"war"
apply plugin:"org.grails.grails-web"
apply plugin:"asset-pipeline"
apply plugin:"org.grails.grails-gsp"

repositories {
    mavenLocal()
    maven { url "https://repo.grails.org/grails/core" }
}

dependencies {
    runtime('org.postgresql:postgresql')

    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-web-boot"
    compile "org.grails:grails-logging"
    compile "org.grails:grails-plugin-rest"
    compile "org.grails:grails-plugin-databinding"
    compile "org.grails:grails-plugin-i18n"
    compile "org.grails:grails-plugin-services"
    compile "org.grails:grails-plugin-url-mappings"
    compile "org.grails:grails-plugin-interceptors"
    compile "org.grails.plugins:cache"
    compile "org.grails.plugins:async"
    compile "org.grails.plugins:scaffolding"
    compile "org.grails.plugins:events"
    compile "org.grails.plugins:hibernate5"
    compile "org.hibernate:hibernate-core:5.1.5.Final"
    compile "org.grails.plugins:gsp"
    console "org.grails:grails-console"
    profile "org.grails.profiles:web"
    runtime "org.glassfish.web:el-impl:2.1.2-b03"
    runtime "com.h2database:h2"
    runtime "org.apache.tomcat:tomcat-jdbc"
    runtime "com.bertramlabs.plugins:asset-pipeline-grails:2.14.8"
    testCompile "org.grails:grails-gorm-testing-support"
    testCompile "org.grails:grails-web-testing-support"
    testCompile "org.grails.plugins:geb:1.1.2"
    testRuntime "org.seleniumhq.selenium:selenium-chrome-driver:2.47.1"
    testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
    testRuntime "net.sourceforge.htmlunit:htmlunit:2.18"
}

bootRun {
    jvmArgs('-Dspring.output.ansi.enabled=always')
    addResources = true
    String springProfilesActive = 'spring.profiles.active'
    systemProperty springProfilesActive, System.getProperty(springProfilesActive)
}

tasks.withType(Test) {
    systemProperty "geb.env", System.getProperty('geb.env')
    systemProperty "geb.build.reportsDir", reporting.file("geb/integrationTest")
    systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver')
    systemProperty "webdriver.gecko.driver", System.getProperty('webdriver.gecko.driver')
}

assets {
    minifyJs = true
    minifyCss = true
}

configurations.all {
    resolutionStrategy.cacheDynamicVersionsFor 10, 'minutes'
}

project.configurations.compile.resolvedConfiguration.resolvedArtifacts.each {
 println '   [Dependencias] '
 println 'artifact: '+it.name
 println 'referencia: '+it.file
 println '**************************'
}

application.yml

---
grails:
    profile: web
    codegen:
        defaultPackage: crud.app
    gorm:
        reactor:
            # Whether to translate GORM events into Reactor events
            # Disabled by default for performance reasons
            events: false
info:
    app:
        name: '@info.app.name@'
        version: '@info.app.version@'
        grailsVersion: '@info.app.grailsVersion@'
spring:
    main:
        banner-mode: "off"
    groovy:
        template:
            check-template-location: false

# Spring Actuator Endpoints are Disabled by Default
endpoints:
    enabled: false
    jmx:
        enabled: true

---
grails:
    mime:
        disable:
            accept:
                header:
                    userAgents:
                        - Gecko
                        - WebKit
                        - Presto
                        - Trident
        types:
            all: '*/*'
            atom: application/atom+xml
            css: text/css
            csv: text/csv
            form: application/x-www-form-urlencoded
            html:
              - text/html
              - application/xhtml+xml
            js: text/javascript
            json:
              - application/json
              - text/json
            multipartForm: multipart/form-data
            pdf: application/pdf
            rss: application/rss+xml
            text: text/plain
            hal:
              - application/hal+json
              - application/hal+xml
            xml:
              - text/xml
              - application/xml
    urlmapping:
        cache:
            maxsize: 1000
    controllers:
        defaultScope: singleton
    converters:
        encoding: UTF-8
    views:
        default:
            codec: html
        gsp:
            encoding: UTF-8
            htmlcodec: xml
            codecs:
                expression: html
                scriptlets: html
                taglib: none
                staticparts: none
endpoints:
    jmx:
        unique-names: true

---
hibernate:
    cache:
        queries: false
        use_second_level_cache: false
        use_query_cache: false
dataSource:
    pooled: true
    jmxExport: true
    driverClassName: org.postgresql.Driver # org.h2.Driver
    username: postgres #sa
    password: 5432 #''

environments:
    development:
        dataSource:
            dbCreate: update
            url: jdbc:postgresql://localhost:5432/inventario #jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
    test:
        dataSource:
            dbCreate: update
            url: jdbc:postgresql://localhost:5432/inventario #jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
    production:
        dataSource:
            dbCreate: none
            url: jdbc:postgresql://localhost:5432/inventario #jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
            properties:
                jmxEnabled: true
                initialSize: 5
                maxActive: 50
                minIdle: 5
                maxIdle: 25
                maxWait: 10000
                maxAge: 600000
                timeBetweenEvictionRunsMillis: 5000
                minEvictableIdleTimeMillis: 60000
                validationQuery: SELECT 1
                validationQueryTimeout: 3
                validationInterval: 15000
                testOnBorrow: true
                testWhileIdle: true
                testOnReturn: false
                jdbcInterceptors: ConnectionState
                defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED

Quinto paso: generar las vistas, etc.

$ grails generate-all "*"

Sexto paso: ejecutar aplicación

$ grails run-app

Abrir el navegador en:http://127.0.0.1:8080/

Es todo por el momento.

Links:

Introducción a grails (en javamexico.org)

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">