1 de abr. de 2011

Grails - El Santo Grial del Desarrollo rápido (Parte II)

Vamos a continuar con la serie de Grails, si recordáis en la parte I de esta serie empezamos a crear una aplicación que servía para gestionar los contactos. Al final de la entrada anterior se decía que había que hacer click en ContactoController, pero porque no hacer las cosas algo mejor, es decir, porque no introducir una pantalla de login y un menú, y si además ponemos una gestión de usuarios y permitimos dar de alta, modificar y eliminar usuarios, habremos realizado una aplicación que tendrá más aspecto de aplicación.

Esto es justo lo que vamos a hacer en esta parte de la mini-serie.

Vamos a comenzar paso a paso nuestra “nueva” aplicación de Contactos.
  1. Creación de los usuarios, grupos y permisos.
Para este proceso vamos a utilizar un plugin de los diversos plugins que posee grails (http://www.grails.org/Plugins), en concreto uno llamado Stark-Security. Ahora bien, y ¿cómo utilizo un plugin? Pues muy sencillo, simplemente hay que instalarlo, y para instalarlo hay que ejecutar un simple comando de grails.
grails install-plugin stark-security
Al ejecutar este comando tenemos la siguiente salida por consola:
grails install-plugin stark-security
Welcome to Grails 1.2.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Users/javi/java/grails-1.2.0

Base Directory: /Users/javi/proyectos/grails-howto-series/agenda
Resolving dependencies...
Dependencies resolved in 1433ms.
Running script /Users/javi/java/grails-1.2.0/scripts/InstallPlugin.groovy
Environment set to development
Reading remote plugin list …
Plugin list out-of-date, retrieving..
[delete] Deleting: /Users/javi/.grails/1.2.0/plugins-list-core.xml
[get] Getting: http://svn.codehaus.org/grails/trunk/grails-plugins/.plugin-meta/plugins-list.xml
[get] To: /Users/javi/.grails/1.2.0/plugins-list-core.xml
....................................................
[get] last modified = Wed Feb 02 03:16:38 CET 2011
Reading remote plugin list ...
Plugin list out-of-date, retrieving..
[delete] Deleting: /Users/javi/.grails/1.2.0/plugins-list-default.xml
[get] Getting: http://plugins.grails.org/.plugin-meta/plugins-list.xml
[get] To: /Users/javi/.grails/1.2.0/plugins-list-default.xml
......................................................................................
[get] last modified = Thu Feb 10 06:22:21 CET 2011
[copy] Copying 1 file to /Users/javi/.grails/1.2.0/projects/agenda.parte2/plugins
Installing plugin stark-security-0.4.3
[mkdir] Created dir: /Users/javi/.grails/1.2.0/projects/agenda.parte2/plugins/stark-security-0.4.3
[unzip] Expanding: /Users/javi/.grails/1.2.0/plugins/grails-stark-security-0.4.3.zip into /Users/javi/.grails/1.2.0/projects/agenda.parte2/plugins/stark-security-0.4.3
Executing stark-security-0.4.3 plugin post-install script ...
Plugin stark-security-0.4.3 installed
Plug-in provides the following new scripts:
------------------------------------------
grails stark-security-install-full
grails stark-security-install-without-dao
Si os fijáis en las dos últimas líneas de la salida anterior, veréis que este plugin ofrece dos nuevos comandos, el que nos interesa es stark-security-install-full, así que ahora tenemos que ejecutar el nuevo comando que nos ha aportado este plugin.
grails stark-security-install-full


Este comando, producirá la siguiente salida por consola:
grails stark-security-install-full
Welcome to Grails 1.2.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Users/javi/java/grails-1.2.0

Base Directory: /Users/javi/proyectos/grails-howto-series/agenda
Resolving dependencies...
Dependencies resolved in 2061ms.
Running script /Users/javi/.grails/1.2.0/projects/agenda/plugins/stark-security-0.4.3/scripts/StarkSecurityInstallFull.groovy
Environment set to development
[copy] Copying 1 file to /Users/javi/proyectos/grails-howto-series/agenda/grails-app/domain
[copy] Copying 1 file to /Users/javi/proyectos/grails-howto-series/agenda/grails-app/domain
[copy] Copying 1 file to /Users/javi/proyectos/grails-howto-series/agenda/grails-app/services
[copy] Copying 1 file to /Users/javi/proyectos/grails-howto-series/agenda/grails-app/controllers
[mkdir] Created dir: /Users/javi/proyectos/grails-howto-series/agenda/grails-app/views/access
[copy] Copying 1 file to /Users/javi/proyectos/grails-howto-series/agenda/grails-app/views/access
[copy] Copying 1 file to /Users/javi/proyectos/grails-howto-series/agenda/grails-app/conf
[copy] Copying 1 resource to /Users/javi/proyectos/grails-howto-series/agenda
[unjar] Expanding: /Users/javi/proyectos/grails-howto-series/agenda/grails-shared-files.jar into /Users/javi/proyectos/grails-howto-series/agenda
[delete] Deleting: /Users/javi/proyectos/grails-howto-series/agenda/grails-shared-files.jar
[copy] Copying 1 resource to /Users/javi/proyectos/grails-howto-series/agenda
[unjar] Expanding: /Users/javi/proyectos/grails-howto-series/agenda/grails-app-files.jar into /Users/javi/proyectos/grails-howto-series/agenda
[delete] Deleting: /Users/javi/proyectos/grails-howto-series/agenda/grails-app-files.jar
Ya tenemos instalada y, prácticamente, configurada la gestión de usuarios de nuestra aplicación, vamos a probar la aplicación, para ello:
grails run-app
Y accedemos como siempre usando un navegador web a la dirección http://localhost:8080/agenda

Como se puede ver la pantalla principal sigue siendo la misma que en la parte I de esta serie, pero aparece un nuevo Controlador (AccessController), si se hace click en el aparece esta pantalla:


Es una pantalla de login que ya contiene la lógica necesaria para poder gestionar el acceso de los usuarios, pero ¿qué usuario tengo para poder acceder?.

Primero vamos a modificar el usuario que nos instala el plugin de Stark-Security, para ello editamos User.groovy y añadimos tres atributos nuevos de tipo String (name, lastName, email).

Para añadir un usuario editamos el archivo BootStrap.groovy que se encuentra en la carpeta grails-app/conf y ponemos lo siguiente:
class BootStrap {

def init = { servletContext ->
if (!User.findByUsername("admin")) {
// Create the superuser account
def superUser = new User(username: 'admin',
password: 'admin',
name:"admin",
lastName:"admin",
email:"admin@admin.com")
// Create ROLE USER and assign to superUser created before
def role = new Role(authority:"ROLE_USER",description:"Role users")
superUser.addToRoles(role)
superUser.save()
}
}
def destroy = {
}
}
Si queréis obtener una lista con todos los plugins disponibles no tenéis más que ejecutar el siguiente comando:
grails list-plugins
  1. Establecimiento de la pantalla de login como pantalla principal.
Para establecer la pantalla de login como pantalla principal de la aplicación, simplemente hay que editar el archivo UrlMappings.groovy, ubicado en la carpeta grails-app/conf, y poner lo siguiente:



class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(view:"/access/login")
"500"(view:'/error')
}


Ahora bien, ya tenemos la pantalla de login para poder acceder a la aplicación, ahora vamos a decirle donde debe ir el usuario cuando haya hecho login en nuestra aplicación de forma satisfactoria, para ello abrimos el archivo AccessController.groovy (grails-app/controllers/) y modificamos un poquito el código que tenemos en el método login, vamos a poner lo siguiente:
def login = {
def user = User.findByUsernameAndPassword(params.j_username,params.j_password)
if (user) {
session.user = user
redirect(url: "../home.gsp")
}
flash.message = "Login failed, please try again."
}
Ahora debemos crear la pantalla home.gsp, para esto vamos a utilizar la pantalla index.gsp que crea por defecto. Creamos un nuevo archivo dentro de la carpeta grails-app/views/ que vamos a llamar, evidentemente, home.gsp; abrimos los dos archivos y copiamos el contenido de index.gsp en home.gsp, ahora modificamos el contenido de home.gsp de tal forma que quede, por ejemplo, de la siguiente forma:






<html>
<head>
<title>Welcome to Grails HOWTO Series Parte II</title>
<meta name="layout" content="main" />
<style type="text/css" media="screen">
#nav {
margin-top:20px;
margin-left:30px;
width:228px;
float:left;
}
.homePagePanel * {
margin:0px;
}
.homePagePanel .panelBody ul {
list-style-type:none;
margin-bottom:10px;
}
.homePagePanel .panelBody h1 {
text-transform:uppercase;
font-size:1.1em;
margin-bottom:10px;
}
.homePagePanel .panelBody {
background: url(images/leftnav_midstretch.png) repeat-y top;
margin:0px;
padding:15px;
}
.homePagePanel .panelBtm {
background: url(images/leftnav_btm.png) no-repeat top;
height:20px;
margin:0px;
}
.homePagePanel .panelTop {
background: url(images/leftnav_top.png) no-repeat top;
height:11px;
margin:0px;
}
h2 {
margin-top:15px;
margin-bottom:15px;
font-size:1.2em;
}
#pageBody {
margin-left:280px;
margin-right:20px;
}
</style>
</head>
<body>
<div id="nav">
<div class="homePagePanel">
<div class="panelTop">
</div>
<div class="panelBody">
<h1>Datos de Usuario:</h1>
<ul>
<li><b>Usuario: </b>${session.user.username}</li>
<li><b>Nombre: </b>${session.user.name}</li>
<li><b>Apellidos: </b> ${session.user.lastName}</li>
<li><b>E-mail: </b>${session.user.email}</li>
</ul>
<h1>Plugins Instalados</h1>
<ul>
<g:set var="pluginManager"
value="${applicationContext.getBean('pluginManager')}"></g:set>
<g:each var="plugin" in="${pluginManager.allPlugins}">
<li>${plugin.name} - ${plugin.version}</li>
</g:each>
</ul>
</div>
<div class="panelBtm">
</div>
</div>
</div>
<div id="pageBody">
<h1>Grails HOWTO Series - Agenda</h1>
<p>Bienvenido a la nueva entrada de la serie de tutoriales de Grails:</p>
<p>Actualmente puedes acceder a la visualización de tus contactos,
tambi&eacute;n puedes crear alg&uacute;n contacto nuevo
directamente desde esta pantalla:</p>
<div id="controllerList" class="dialog">
<h2>Accesos directos:</h2>
<ul>
<li class="controller">
<g:link controller="contacto" action="list">
Lista de Contactos
</g:link>
</li>
<li class="controller">
<g:link controller="contacto" action="create">
Crear un nuevo Contacto
</g:link>
</li>
</ul>
</div>
</div>
</body>
</html>

Vamos a probar que lo que hemos hecho está bien hecho, para ello lanzamos la aplicación con el comando de siempre, y navegamos a la url de la aplicación. Tras hacer login el resultado debería ser algo parecido a esto:


Una vez que tenemos la aplicación funcionando con el aspecto que, más o menos, queremos, vamos a proceder a modificar, un poco alguna cosa más de la aplicación, para conseguir una navegación consistente entre las páginas.

  1. Modificación de páginas para navegación más coherente y adición de logout.
Para conseguir una navegación más consistente en la aplicación hay varias opciones, algunas son más complicadas que otras, así que voy a optar por lo más sencillo, que consiste en editar las páginas GSP de contacto (create, edit, list y show).

En el inicio de las páginas hay un tag HTML div cuyo nombre es nav, este tag contiene los enlaces para poder acceder a las distintas funcionalidades de la entidad que manejamos, en concreto la que nos interesa modificar es la siguiente:

<a class="home" href="${createLink(uri: '/')}">Home</a>

La vamos a sustituir por esta otra:

<a class="home" href="${createLink(uri: '/index')}">Home</a>


Ahora editamos UrlMappings.groovy para que quede lo siguiente:

class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(view:"/access/login")
"/index" (view:"/home")
"500"(view:'/error')
"/access/logout"(view:"/access/login")
}

Con estos cambios que hemos realizado en UrlMappings.groovy cuando navegamos hacia index automáticamente se redirige a home.gsp

Con esto ya tenemos una navegación algo más coherente.

Ahora añadamos la funcionalidad de logout, para esto editamos la pantalla home.gsp y añadimos:

<li><g:link url="./access/logout">Salir</g:link></li>

Tras la línea siguiente:

<li><b>E-mail: </b>${session.user.email}</li>

Nuestra nueva pantalla principal se parecerá a esto:

Nuestra nueva pantalla principal se parecerá a esto:



Y ahora pasemos al siguiente punto...

  1. Ejecutar la aplicación

Ahora lo interesante es probar la aplicación para ello vamos a la consola y ejecutamos de nuevo el comando:

grails run-app

Abrimos un navegador y vamos a la dirección que nos dice al final de la salida por consola:


Y ahora a probar la aplicación... para esto lo que tenemos que introducir el usuario y password creados en la clase BootStrap.groovy y entramos en la nueva pantalla que hemos creado, ahora ya podemos dar de alta contactos, actualizarlos y borrarlos.

Espero que os haya gustado esta segunda parte de la serie. En próximas fechas tendremos otras partes...

Salud y a disfrutar!!!