16.5.10

Groovy on Grails (III): Tecnologías asociadas :: Grails

Grails

En este apartado, se va a profundizar en los aspectos más relevantes de Grails mediante descripciones y ejemplos. No se puede considerar este apartado como un manual de usuario de Grails, más bien como un pequeño tutorial de introducción a éste potente framework web.

En los siguientes apartados vamos a tratar varios aspectos de Grails, desde su estructura hasta llegar a su funcionalidad pasando por la implementación de controladores, gsp’s, etc …

  1. Estructura de la aplicación
El primer paso en la implementación de un nuevo proyecto en Grails, es la creación de la estructura de directorios del proyecto. Para realizar este paso, Grails nos proporciona un comando que nos crea automáticamente la estructura de directorios:
$> grails create-app
seguidamente a esta instrucción introducimos el nombre de la aplicación y a continuación Grails nos crea la estructura necesaria para administrar nuestro proyecto.

Una de las ideas principales de Grails es la aplicación de convenciones de desarrollo de aplicaciones Web, siguiendo esta convención se crean los archivos y directorios que se usarán en la mayoría de aplicaciones Web. Aunque esta estructura de directorios no es estática, ya que la podemos configurar según nuestras necesidades.

Esta estructura de ficheros nos sitúa automáticamente los Paths donde van a ir almacenados las vistas, controladores, librerías,… donde Grails va a ir colocando los nuevos elementos que se vayan creando automáticamente durante la implementación del proyecto.

Si se tiene experiencia utilizando Apache Ant, se puede crear manualmente este sistema de directorios modificando el archivo de /src/grails/build.xml que encontramos en el directorio GRAILS_HOME.
  1. Base de datos
La base de datos que viene configurada por defecto cuando creamos un nuevo proyecto en Grails es volátil y utiliza el lenguaje de base de datos HSQL. Si queremos que nuestra base de datos deje de ser volátil y queremos que tenga una permanencia (en el localhost), se modificará la siguiente línea en el fichero:
…/grails-app/conf/ApplicationDataSource.groovy

dataSource {
   pooled = false
   driverClassName = "com.mysql.jdbc.Driver"
   username = "root"
   password = ""
}

environments {
   development {
      dataSource {
         dbCreate = "update" // one of 'create', 'create-drop','update'
         url = "jdbc:mysql://localhost/petStore_dev"
      }
   }

   test {
      dataSource {
         dbCreate = "update"
         url = "jdbc:mysql://localhost/petStore_test"
      }
   }

   production {
      dataSource {
         dbCreate = "update"
         url = "jdbc:mysql://localhost/petStore_prod;shutdown=true"
      }
   }
}

Como podemos observar en el código, modificando el valor de dbCreate por update, establecemos una base de datos permanente. Observamos también que por cada tipo de implementación, ya sea de desarrollo, testeo o producción podemos tener una base de datos diferente, lo que facilita la futura implantación del proyecto.

Si por comodidad se quiere utilizar otro tipo de lenguaje de base de datos, tan sólo se ha de descargar el driver correspondiente y almacenarlo en el directorio lib del proyecto. Seguidamente se ha de modificar el nombre del driver en el anterior código, así como la situación de las bases de datos que se utilizaran.
  1. Clases de dominio
El Mapeo de Objetos Relacionales de Grails (GORM) utiliza internamente Hibernate 3, pero para poder implementar la aplicación Web no es necesario tener ningún conocimiento sobre Hibernate. Para realizar este mapeo Grails utiliza las llamadas clases de dominio, que determina los objetos mapeados en la base de datos. Se pueden linkar clases de dominio utilizando relaciones proporcionando metodos dinámicos para realizar operaciones CRUD (Create, Read, Update, Delete), sobretodo mediante Scaffolding.

Grails dispone de una instrucción para la creación automática de clases, que nos almacenará las nuevas clases en el directorio …/grails-app/domain/ ,
$> grails create-domain-class
a dicha instrucción solamente le hemos de proporcionar el nombre de la clase y ya tendremos una nueva clase disponible para configurar.

Estas clases de dominio pueden disponer, además de sus propiedades y campos, de métodos propios y declaraciones de constraints para las propiedades y campos. Es posible establecer una relación de 1-1, 1-n o n-n entre clases directamente en la implementación de dichas clases, este y anteriores elementos los veremos en el siguiente ejemplo.

class Pet {
   String name
   String type
   String description
   Float price
   byte[] image

   static hasMany = [carts:Cart]
   static belongsTo = Cart

   static constraints = {
      name(maxLength:50, blank:false)
      type(inList:['Bird','Cat', 'Dog', 'Fish', 'Ferret','Rodent'], blank:false)
      description()
      price(min:0f)
      image(nullable:true, maxSize:65536) /* 64K */
   }

   static mapping = {
      description type: 'text'
   }
}
En el anterior ejemplo descubrimos las ventajas de las clases de dominio de Grails, las restricciones directas en código y la relación entre diferentes clases directamente en código.
  • Restricciones directas en código
Como podemos observar, utilizando una closure con el nombre “constraints”, podemos configurar las restricciones que queremos que tengan las propiedades y los campos de la clase, lo que nos facilitará la implementación posteriormente cuando se creen las vistas y los controladores.
  • Relación entre clases directamente en código
Para realizar una relación entre clases, tan sólo se ha de establecer una variable relacional:
    • Sección 1 de la relación: Utilizaremos la variable belongsTo con valor igual a la clase con la que estamos relacionando.
    • Sección n de la relación: Utilizaremos la variable anterior belongsTo, además de la variable hasMany con valor igual a la clase con la que estamos relacionando mediante un mapa extendido, especificando el nombre de la variable que almacenará la colección de valores.
  1. Controladores y vistas
Una vez que las clases de dominio ya se han creado, es el momento de utilizar un nuevo comando de Grails que nos auto genera los CRUD básicos para nuestra aplicación Web:
$> grails generate-all
Gracias a este comando se crean los llamados controladores y las vistas básicas que necesitaremos para gestionar nuestra clase de dominio.

Los controladores se almacenarán en el directorio grailsapp\ controllers. Dichos controladores son los responsables de el manejo de las peticiones de nuestra aplicación Web. Los controladores son los sustitutos naturales de los Servlets de Java, con la ventaja de que su implementación es tan sencilla como crear una closure por cada tipo de petición que queramos que atienda. A continuación vamos a ver un ejemplo de controladores e introduciremos el concepto de Scaffolding en Grails.

class CartController {
   def index = { redirect(action:list,params:params) }

   def scaffold = Cart

   def list = {

      if(!params.max) params.max = 10
      [ cartList: Cart.list( params ) ]
   }

   def show = {
      def cart = Cart.get( params.id )

      if(!cart) {
         flash.message = "Cart not found with id ${params.id}"
         redirect(action:list)
      }
      else { return [ cart : cart ] }
   }

   def delete = {
      def cart = Cart.get( params.id )

      if(cart) {
         cart.delete()
         flash.message = "Cart ${params.id} deleted"
         redirect(action:list)
      }
      else {
         flash.message = "Cart not found with id ${params.id}"
         redirect(action:list)
      }
   }

   def edit = {
      def cart = Cart.get( params.id )

      if(!cart) {
         flash.message = "Cart not found with id ${params.id}"
         redirect(action:list)
      }
      else {
         return [ cart : cart ]
      }
   }

   def update = {
      def cart = Cart.get( params.id )

      if(cart) {
         cart.properties = params
      
         if(!cart.hasErrors() && cart.save()) {
            flash.message = "Cart ${params.id} updated"
            redirect(action:show,id:cart.id)
         }
         else {
            render(view:'edit',model:[cart:cart])
         }
      }
      else {
         flash.message = "Cart not found with id ${params.id}"
         redirect(action:edit,id:params.id)
      }
   }

   def create = {
      def cart = new Cart()
      cart.properties = params
      return ['cart':cart]
   }

   def save = {
      def cart = new Cart(params)

      if(!cart.hasErrors() && cart.save()) {
         flash.message = "Cart ${cart.id} created"
         redirect(action:cartBuy,id:params.id)
      }
      else {
         render(view:'create',model:[cart:cart])
      }
   }
}
En este ejemplo, podemos ver los controladores básicos que se crean con el comando anterior, añadiendo además la opción de Scaffolding con la variable “scaffold”.

Los controladores básicos son los de Creación, Actualización, Edición y Modificación, pero posteriormente se pueden ir añadiendo funcionalidades como el logging de usuarios, etc...

Una vez el controlador ha procesado la petición, la delega a la vista apropiada. Para realizarlo Grails utiliza un mecanismo de convención, en el cuál el controlador delega la petición a la vista que tiene su mismo nombre, la cuál se encuentra almacenada en grails-app/views/name/ donde name es el nombre de la clase dominio. En dicha carpeta podemos encontrar la vista en formato JSP o GSP, ya que Grails admite ambos formatos.
  1. Funcionalidad
Grails incorpora un servidor de management con el que se puede ejecutar nuestra aplicación de Grails antes de importarla. Utilizando el comando especifico:
$> grails run-app
de compilación y ejecución con nuestra aplicación, el servidor inicia nuestra aplicación en la dirección http://localhost:8080/nameApp, donde “nameApp” es el nombre de nuestra aplicación Web.

Posteriormente podemos exportar nuestra aplicación en un fichero war para importarlo en un Tomcat utilizando el comando:
$> grails war
Después de esta breve introducción a Grails, realizaremos una aplicación Web de ejemplo basada en una tienda virtual de mascotas, donde profundizaremos más en los aspectos de Grails además de una comparación directa con la implementación de una aplicación semblante en Java.

1 comentario:

Unknown dijo...

hace mucho que no actualizas, no?