Llevo ya dos o tres semanas jugando con Grails. La parte de hacer código estupenda, se hace mucho con muy poco, la parte de vistas y controladores bien, la de modelo y base de datos me ha dado algún problemilla, pero supongo que lo habitual si te metes con cosas que hay por debajo, como Hibernate y encima no lo controlas.
Sin embargo, me ha dado por configurar el DataSource para la base de datos. Por defecto, Grails pone una base de datos HSQLDB. Si en el fichero DataSource.groovy cambias los parámetros de conexión y pones otra base de datos, también funciona bien todo. Puse una base de datos MySQL, puse en el directorio lib el jar con el conector de MySQL, cambié los parámetros de conexión y todo correcto.
Pero claro, a mi me gustaría hacer un war de mi aplicación y ponerlo en algún sitio descargable para que la gente se lo descargue, lo ponga en su servidor, configure la base de datos a su gusto y le funcione en su entorno. Y ahí es donde me he encontrado con problemas y cosas que no me han parecido muy lógicas.
DataSource.groovy es un fuente groovy, por lo que una vez compilado, metido en un war y desplegado, no se puede cambiar fácilmente. Tampoco parece muy amigable poner en las instrucciones de instalación que se toquen los fuentes groovy y se compilen, obligando a descargar el entorno grails al que sólo quiera instalar y utilizar la aplicación.
Pero no hay problema, se mira en la documentación de grails y se acaba encontrando que se puede poner un fichero de propiedades normalito, de los de toda la vida, con la configuración de la base de datos. Estas propiedades sobreescriben a las de DataSource.groovy. Unicamente hay que hacer dicho fichero de properties y en el fichero Config.groovy poner esto al principio
grails.config.locations = ["file:path/fichero.properties"]
Podemos poner file:, como en el ejemplo, o classpath:, para cogerlo del classpath.
Lo del classpath funciona correctamente, basta meter el fichero de propiedades en el el directorio WEB-INF/classes y todo bien. Pero claro, yo soy un poco "tikis-mikis" y no me gusta meter un fichero de configuración en el directorio de classes. No creo que sea un lugar intuitivo donde alguien busque un fichero de configuración. Quizás un directorio conf o algo así….
Así que me decanto por la opción file. Pero se me presenta otro problema. Cuando despliego mi war en un Tomcat, el directorio actual de ejecución resulta ser el directorio en el que está el script de arranque del Tomcat (el catalina.bat o catalina.sh). Desde ahí no se puede poner un path relativo hacia el fichero de configuración. Bueno, sí se puede, pero sería así de feo ../webapps/MiAplicacion/WEB-INF/conf/fichero.propiedades o algo así. Y si en vez de Tomcat es otro servidor, igual no existe eso de webapps (no lo sé).
Pues nada, vamos a ver si conseguimos de alguna forma el directorio raíz de la aplicación una vez desplegada, para poder poner el path relativo desde ahí. Las variables predefinidas de grails en el config.groovy no ayudan. Tenemos ${appName}, para el nombre de la aplicación y no recuerdo las otras, pero eran dos o tres nada más y hacen referencia al número de versión de la aplicación y poco más. Nada sobre ningún path donde se está ejecutando nuestra aplicación. Siento no poner el enlace donde he visto esas tres variables, pero la maravillosa documentación de grails no me permite volver a encontrarlo fácilmente.
Sí podemos poner variables de entorno, por lo que definir una variable propia, estilo MIAPLICACION_HOME o ${userHome} sí valen. Pero tampoco es una solución elegante. No podemos decir a nuestro usuario que defina una variable de entorno indicando dónde ha desplegado tomcat nuestra aplicación y rearranque el Tomcat entero, o que se vaya a su HOME y ponga un fichero, sobre todo si el Tomcat se arranca como servicio/demonio. Es más, poner el fichero de propiedades en un sitio fijo y apuntado por una variable de entorno, la que sea, no nos permitiría desplegar dos instancias de nuestra aplicación en el mismo servidor.
Sigo investigando y descubro que hay una maravillosa cosa llamada ServletContext en la que creo que puedo obtener este path que me hace falta para localizar el fichero de propiedades. Veo además en Grails que las clases groovy tienen accesible un servletContext como atributo (o parecido). Qué casualidad, justo Config.groovy y DataSource.groovy no lo tienen, así que directamente no lo tengo accesible. Bueno, no pasa nada, ServletContextHolder lo tiene guardado como atributo estático, así que ahí podemos acceder a él. Pues nuevamente vaya, resulta que durante la ejecución de Config.groovy y DataSource.groovy, ese atributo es null.
El ServletContext se le pasa a Grails en la clase Bootstrap, método init() y cuando se llama a eso, ya se han leído todas las propiedades, cargado el dataSource y establecido la conexión a la base de datos por defecto. Ni tenemos el ServletContext disponible antes, ni podemos cambiar el DataSource después.
Así que nada, la única opción transparente para posibles usuarios es meter dicho fichero de propiedades en el classpath, en el directorio classes.
Así que mi conclusión es que grails puede estar muy bien para hacer una aplicación web que tú vas a montar y de la que tú eres responsable del servidor, quizás una aplicación web corporativa o para poner al público en un dominio concreto y ya en ejecución, Pero desde luego, no parece muy amigable si tu intención es hacer un war que luego la gente en general pueda descargarse y montar en su propio servidor. Es más, muchas aplicaciones piden al usuario a través de la misma interface web la configuración de la base de datos (url, username y password). No sé si es posible hacer esto en grails, pero si lo primero que hace grails, incluso antes de tener el servletContext disponible, es liarse a cargar ficheros de propiedades y establecer las conexiones con la bd, dudo mucho que cuando se le muestre la página de bienvenida al usuario se pueda cambiar fácilmente nada de eso.
Y encima otra cosa que me preocupa, resulta que mi aplicación son tres clases de modelo, otros tres o cuatro clases de controlador, un par de páginas gsp….. y he tenido que aumentarle la memoria al tomcat para que sea capaz de ejecutarla. El war generado ocupa 26 Megas y Tomcat empezó a dar OutOfMemory con frecuencia, por lo que tuve que subirle la memoria.
En fin, dejaré el fichero de properties en el el directorio classes (ya he perdido bastante tiempo para algo que creo no tiene solución), haré un par de cosas más que me quedan pendientes y dejaré aparcado grails una temporada. Quizás lo retome si tengo que hacer una aplicación para el departamento, pero desde luego, no lo vuelvo a escoger si mi intención es hacer una aplicación que la gente pueda instalarse en sus propios servidores.
.png)