Como leer variables de entorno con Grails

En diversos proyectos en los que he tenido la oportunidad de participar, siempre me he encontrado con el inconveniente de tener que tomar archivos de cierto tipo como insumo para mi aplicación entiéndase con un archivo PDF para mostrarlo al usuario un archivo de propiedades y hasta un archivo de Excel para leer su contenido, utilizando diversas técnicas para resolver el inconveniente ¿Dónde pongo el archivo?

Algunas soluciones que en su momento implemente y que podemos hacer son desde poner una ruta estática, hasta crear una carpeta dentro del contexto de mi aplicación, otra opción es declarar una variable de entorno, todas las opciones anteriores tienen ventajas y desventajas.

* Si creamos una ruta estática, la ventaja principal sobre este método, es que hay mucha información de cómo hacerlo por lo cual realizar la implementación seria muy fácil y rápido, la principal desventaja es que si por algún motivo queremos cambiar la ruta definida, tendremos que cambiarla directamente en el código y al mismo tiempo tenemos que recompilar y desplegar nuestra aplicación.

* Al definir una carpeta dentro del proyecto y referirnos a ella mediante el contexto, la ventaja seria que no necesitas definir la ruta estática en los equipos donde se vaya a ejecutar la aplicación pero bajar la ruta del contexto que le de cada servidor donde se despliegue la aplicación es un tanto complicado.

* Al declarar la ruta desde una variable de entorno la ventaja es que no tiene dependencia alguna con nuestra aplicación, y podremos cambiar la ruta cuantas veces quiéranos sin tener que compilar nuestra aplicación cada vez que necesitemos hacer un cambio de la ruta, mas sin embargo tenemos que definir esta variable de entorno en el equipo donde se realice el deploy de nuestro proyecto, esto puede ser un tanto beneficioso, pues nos ahorraría mucho trabajo, es por eso que estoy creando esta entrada para mostrar la manera de realizar la lectura desde nuestro proyecto en Grails además de que buscando un buen rato en internet no encontré mucha información al respecto y mucho menos en español.

Para implementar este ejemplo seguiremos con el ejercicio del tutorial anterior que puedes ver desde aquí: Creando mi primer proyecto con Groovy and Grails

Lo primero que tendremos que hacer, será crear el servicio "Leer Variable" para esto utilizamos el comando "create-service" como se muestra en la siguiente imagen:

Ahora abrimos la clase para editarla y que quede como se muestra a continuación:

 

Como podemos observar en el método definido automáticamente por Grails simplemente ponemos unas cuantas líneas de código, la primera para indicar un mensaje a la consola de la aplicación y la segunda es la que hace toda la magia, pues le indicamos que imprima lo que devuelve “getenv” y el nombre de nuestra variable de entorno que queremos leer. Hasta este punto y con este mínimo de código, al ejecutar nuestra clase Groovy e invocar la siguiente sentencia: System.getenv(String nombreVariableEntorno) automáticamente Grails nos devolverá un String con el contenido de esa variable o bien un null si no existe.

Hasta este punto podría decirles que ya de realizo lo que se pretendía con este tutorial, pero ahora vamos a demostrarlo y verlo en funcionamiento.

1.- Debemos declarar la variable de entorno que apunte a una ruta, para ello vamos a panel de control, configuración avanzada de sistema, variables de entorno creamos una nueva variable y le ponemos de nombre “RUTA_A_UN_ARCHIVO” y en valor de la variable le pondré una carpeta en mis documentos llamada archivos a leer, debe de quedar como se muestra en la imagen:

Damos aplicar y aceptar, Un error común aquí es que una vez definida la nueva variable de entorno, tenemos que reiniciar nuestro IDE para que la tome en cuenta, en algunos casos muy extremos habrá que reiniciar el equipo, en mi caso basto solo con reiniciar mi IDE.

Solo como fines demostrativos mostraremos el valor de la variable en una pantalla de nuestra aplicación por lo cual necesitaremos crear un controlador (controller) y una vista (gsp).

2.- Creando el controlador: En grails un controlador es una clase que tendrá definidos como atributos una serie de Closures, a nuestro controlador lo llamaremos LeerVariable, al ejecutar el comando tendremos en la carpeta de Controllers una nueva clase Groovy llamada LeerVariableController la cual modificaremos para que quede de la siguiente forma:

 

Como podemos observar en la clase anterior solo definimos un Closure leerVariable que lo único que hace es instanciar la clase Service e invocar a su método (en este caso el método por default) serviceMethod(); y almacenar lo que devuelve en una variable de tipo cadena llamada “ruta”, al mismo tiempo que regresa esa variable a la cual nos podemos definir desde la vista como valor.

3. Creando la vista: Las vistas en Grails son simples archivos HTML que puede contener código de Groovy Server Pages (gsp) y/o tags específicos de Grails, tienen la extensión .gsp y se sugiere crear una vista por cada closure que contenga nuestro controlador, todas las vistas deben ir en el directorio “views” y dentro debe haber una carpeta con el nombre de nuestro controlador dentro de esta carpeta habrá una gsp con el nombre de nuestro closure.

El contenido de nuestra gsp es el siguiente:

Lo interesante de las gsp es que podemos leer variables definidas en nuestro closure como un valor de retorno así pues como podemos observar en la clase controller tenemos la siguiente línea:

 

lo que nos permite acceder al valor de la variable ruta en nuestra vista con la siguiente línea:

 

Ahora bien lo único que nos queda es ejecutar nuestra aplicación y acceder a la ruta de nuestra gsp que como bien recordamos es raíz/nombreProyecto/nombreCarpetaController/nombreNuestroClosure, así bien la ruta para este ejemplo seria:

 

y esta sería la salida en nuestro navegador:

Me gustaría saber que les pareció el tutorial, es a grandes rasgos una muestra de cómo trabaja un proyecto en Grails del cual se verán características más a fondo en próximos tutoriales.

Tutorial Original:

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

transactional

Me parece que LeerVariableService debería tener transactional=false para que no se genere una transacción cada que se ejecuta, pues ni siquiera se usa y solamente causa detrimento en el desempeño.

Como ejemplo de un servicio está bien, pero pues en la práctica sería más fácil y directo simplemente no tener este servicio y llamar directamente  , no? O definir este valor como una propiedad en Config.groovy y aprovechar lo de los ambientes, para tener distintos valores de esa variable en desarrollo, pruebas y producción...

Imagen de Shadonwk

Gracias por las

Gracias por las observaciones, soy relativamente muy nuevo en Grails y la finalidad de este tipo de post, es que haya retroalimentación para así aprender los tips como los que mencionas y que muchas veces no se encuentran en los libros.

Lo de hacer la llamada a System.getenv en un Servicio es porque de momento ahí lo necesito, pero efectivamente, las posibilidades son muchas :)

Imagen de Sr. Negativo

Buen post sobre Grails

En diversos proyectos en los que he tenido la oportunidad de participar, siempre me he encontrado con el inconveniente de tener que tomar archivos de cierto tipo como insumo para mi aplicación entiéndase con un archivo PDF para mostrarlo al usuario un archivo de propiedades y hasta un archivo de Excel para leer su contenido, utilizando diversas técnicas para resolver el inconveniente ¿Dónde pongo el archivo?
Algunas soluciones que en su momento implemente y que podemos hacer son desde poner una ruta estática, hasta crear una carpeta dentro del contexto de mi aplicación, otra opción es declarar una variable de entorno, todas las opciones anteriores tienen ventajas y desventajas.

Igual yo he tenido que hacer algo similar.

Buena info. 0_o

Imagen de Shadonwk

fe de erratas

como fe de erratas quiero comentarles sobre lo que escribio Enrique:

Me parece que LeerVariableService debería tener transactional=false para que no se genere una transacción cada que se ejecuta, pues ni siquiera se usa y solamente causa detrimento en el desempeño.

Comnetarles que no se refiere a generar una transacción cada que se ejecuta, mas bien es para idicar si cada uno de los metodos contenidos en el servicio son o no transaccionales lo que quiere decir que se realizara el commit solo sí el metodo termina sin ninguna excepción en caso contrario se realizara un rollback.

Imagen de ezamudio

pero...

Para que se realice un commit si el método termina sin ninguna excepción, es porque hay una transacción abierta. Cada que se ejecuta un método de un servicio que tiene transactional=true, se hace dentro de una transacción. Si no ocurre ningún problema, se da commit al final; si se arroja una excepción, se da rollback.

En este caso concreto, cada que se invoca el método de tu servicio, se hace dentro de una transacción. Esto significa que se abre una transacción, se ejecuta tu método, y luego se da commit a la transacción y se devuelve el valor. Todo eso para devolver una propiedad de sistema, cosa que no necesita de una transacción, ni se beneficia de tener una abierta. Si le pones transactional=false a tu servicio, ya no se crea ninguna transacción.