Accediendo a los datos internos de Grails

A veces es inevitable tener la sensación de que Grails es demasiado sencillo y que esconde, a propósito, algo debajo. Debajo no tiene nada más que Spring, y gracias a ello, podemos entrar en sus “tripas”, verlo e incluso modificarlo.
Veamos algunas formas sencillas se obtener información útil para nuestros desarrollos.

Entorno

Primero es saber en que entorno estamos trabajando ahora mismo. Podemos hacer que nuestro BootStrap (o un controlador o servicio, lo que sea), ejecute una acción u otra en función del entorno actual en el que se ha arrancado. Para ello tenemos la clase grails.util.Environment y los métodos isDevelopmentMode() y getCurrent()

import grails.util.Environment

class BootStrap  {

     def init = { servletContext ->

         if (Environment.isDevelopmentMode()) {
             println "development"
         }

         switch (Environment.getCurrent().name) {
             case "development":
                 println "development"
                 break;
             case "otro" :
                 println "otro"
         }
     }
}

Para arrancar en un entorno u otro, hay que pasar el parámetro grails.env: grails -Dgrails.env=X war o grals -Dgrails.env=X run-app

application.properties

La configuración del application.properties se obtiene a través de ApplicationHolder.application.applicationMeta. Por ejemplo, el siguiente fragmento muestra todo el contenido de este fichero (es un GSP):

<%@ page import="org.codehaus.groovy.grails.commons.ApplicationHolder" %>

<h1>Meta:</h1>
<g:each in="${ApplicationHolder.application.applicationMeta}" var="name">

    <li>${name}</li>

</g:each>

Config.groovy

Todos nuestros datos de configuración que poquito a poco hemos ido metiendo en el Config.groovy están accesibles desde cualquier lugar de tu aplicación en el objeto ConfigurationHolder.config y ConfigurationHolder.flatConfig:

<%@ page import="org.codehaus.groovy.grails.commons.ConfigurationHolder" %> 

<h1>Config (flat)</h1>
<g:each in="${ConfigurationHolder.flatConfig}" var="name">

      <li>${name}</li>

</g:each>

<h1>Datasource</h1>
<g:each in="${ConfigurationHolder.config.dataSource}" var="name">

      <li>${name}</li>

</g:each>

Podemos crear en el fichero Config.groovy nuestra propia sección:

xmpp {
    priority = 20
    client {
          host = "192.168.3.1"
          port = 2832
          domain = "peterpan"
    }
}
ftp {
    user = "hoy"
    passwd = "gan"
}

Y luego acceder a estos valores desde un controlador así:

import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH

class TestController {

    def index = {
        def prio = CH.config.xmpp.priority
        def host = CH.config.xmpp.client.host
        def port = CH.config.xmpp.client.port
        def doma = CH.config.xmpp.client.domain

        def ftpuser = CH.config.ftp.user
        def ftppasw = CH.config.ftp.password
    }
}

basePath

Si quieres saber donde están físicamente los archivos de tu aplicación:

import org.codehaus.groovy.grails.commons.ApplicationHolder;
...
println ApplicationHolder.application.mainContext.servletContext.context.basePath

La factoría de Spring

Ahora vamos con Spring. Para acceder al contexto de la aplicación, al factory, tenemos ApplicationHolder.application.mainContext. De ahí podemos sacar beans, o mostrar todos los que ya hay:

<%@ page import="org.codehaus.groovy.grails.commons.ApplicationHolder" %>

<h1>System beans</h1>

<g:each in="${ApplicationHolder.application.mainContext.getBeanDefinitionNames()}" var="name">

      <li>${name}/li>

</g:each>

Incluso podemos obtener un bean del sistema con ApplicationHolder.application.mainContext.getBean(beanName)

web.xml

Finalmente, podemos acceder a los atributos y parámetros de nuestro archivo /WEB-INF/web.xml con ServletContextHolder.servletContext.context

<%@ page import="org.codehaus.groovy.grails.web.context.ServletContextHolder" %>

<h1>Servlet context Attributes:</h1>

<g:each in="${ServletContextHolder.servletContext.context.attributes}" var="name">
    <li>${name}</li>
</g:each>

<h1>Servlet context parameterss:</h1>

<g:each in="${ServletContextHolder.servletContext.context.parameters}" var="name">
    <li>${name}</li>
</g:each>

Y a otros valores como el contextPath con ServletContextHolder.servletContext.context.contextPath y el resto de método de la interfaz javax.servlet.ServletContext

Conclusión

Como podemos observar, la aparente simplicidad de Grails no sirve para protegernos ni para esconder toda su información: existe toda una serie de clases con las que Grails nos facilita obtener beans de la factoría Spring, datos de sus archivos de configuración y parámetros y atributos de la aplicación Web. Resumen de clases y métodos usados:

  • grails.util.Environment.isDevelopmentMode()
  • grails.util.Environment.getCurrent().name
  • grails.util.GrailsUtil.grailsVersion
  • org.codehaus.groovy.grails.commons.ApplicationHolder.application.applicationMeta
  • org.codehaus.groovy.grails.commons.ApplicationHolder.application.mainContext.servletContext.context.basePath
  • org.codehaus.groovy.grails.commons.ConfigurationHolder.config
  • org.codehaus.groovy.grails.commons.ConfigurationHolder.config.dataSource
  • org.codehaus.groovy.grails.commons.ConfigurationHolder.flatConfig
  • org.codehaus.groovy.grails.commons.ApplicationHolder.application.mainContext.getBean(beanName)
  • org.codehaus.groovy.grails.web.context.ServletContextHolder.servletContext.context.attributes
  • org.codehaus.groovy.grails.web.context.ServletContextHolder.servletContext.context.parameters

Espero que os haya servido de utilidad.

2 thoughts on “Accediendo a los datos internos de Grails

  1. Buen resumen de como bucear un poco en las interioridades de grails. Otra forma es usar la consola o shell para inspeccionar (inspect) los objetos con sus metodos, es lo que suelo hacer cuando intento destripar lo que me hace grails. Si te metes con los plugins (con El Plugin de gorm con hibernate) la cosa se complica un poco al intentar seguir el hilo de todol o que hace cuando pone en marcha los motores. Me sigue dando la sensacion que el contraste entre la simplicidad del desarrollo y la complejidad del framework no es mas pequeño que otros frameworks, incluso diria que mas.
    En ese sentido encontre muy util este tutorial que lamentablemente (o curiosamente) no se ha completado:
    http://github.com/dima767/grails-internals-handbook
    Nos leemos!

    • Si, yo también soy un asiduo de la grails console. De hecho, la uso bastante, sobre todo cuando tengo que hacer alguna query compleja o probar algo de código. Pero para inspeccionar objetos prefiero la ventana “Expression evaluation” del modo debug de IntelliJ IDEA, con el que puedes usar tanto Groovy como Java. Lo curioso es que en el modo Java, Groovy te enseña los objetos con sus verdaderas clases, claro que no funcionan los métodos y atributos dinámicos claro, pero es interesante ver como aparecen los groovy.lang.Reference :)

Comments are closed.