E-Tare@s

De WikiII

Equipo de proyecto

  • Nombre del equipo:
    • JDT
  • Jefe de Proyecto:
    • Daniel Crespo Bernal
  • Miembros:
    • Miguel Ángel Vera Márquez: arquitecto software, administrador de la base de datos, analista/programador.
    • Emilio de Torres Fernández: diseñador de la interfaz, administrador de sistemas, analista/programador.
    • Daniel Crespo Bernal: jefe de proyecto, administrador de sistemas, analista/programador, codificador de pruebas.
  • Home del proyecto en Assembla:
  • Reuniones:
    • Miércoles de 18:00 a 21:00 (horario de clase).
    • Viernes de 19:00 a 21:00.


Contenido

Entregable E1: Planificación y configuración

Planificación

Planificación detallada de las actividades

Configuración

Framework

Hemos elegido Grails como framework para desarrollar nuestro proyecto por las siguientes razones:

  • Permite un desarrollo muy rápido ideal para proyectos ágiles.
  • Posee un alto grado de compatibilidad con Java por lo que la curva de aprendizaje no será muy pronunciada.
  • Tiene por debajo otros frameworks muy importantes como Spring e Hibernate.
  • Nos desentendemos en gran medida de la configuración gracias a la "Codificación a través de convenciones".


Pasos a seguir para su instalación en un sistema operativo Windows:

  1. Descargarse e instalar el JDK de Java.
  2. Crear la variable de entorno JAVA_HOME de manera que apunte al directorio donde se ha instalado el jdk.
  3. Descargarse grails de la página oficial.
  4. Descomprimir el fichero en el directorio en el que vayamos a trabajar con grails. Es importante que el nombre de la carpeta no contenga espacios en blanco.
  5. Crear la variable de entorno GRAILS_HOME de manera que apunte al directorio donde se encuentra grails.
  6. Añadir al PATH la ruta de la carpeta "bin" contenida dentro de la carpeta de grails.


IDE

El entorno de desarrollo elegido es Netbeans ya que incorpora groovy y permite la gestión de proyectos de grails.

Su instalación es muy sencilla. Primero hay que descargarse Netbeans 6.8 y después seguir los pasos que se van indicando.

¿Cómo se crea un proyecto de grails en Netbeans?

  • Archivo -> Proyecto nuevo
  • Categoría -> groovy, Proyecto -> Grails Aplication
  • Establecer el nombre del proyecto y el lugar donde se va a guardar. Dentro de este menú tenemos que entrar en "Configure Grails" y seleccionar el directorio donde se ha instalado el framework. Si se ha establecido la variable GRAILS_HOME este último paso es opcional.


Base de datos

Para nuestro proyecto vamos a utilizar MySQL como Sistema Gestor de Base de Datos. Los pasos para configurarlo son los siguientes:

  • Descargarse MySQL e instalarlo.
  • Crear la BD para la aplicación:
create database etareas;
  • Seleccionar la BD:
use etareas
  • Crear un usuario concediéndole todos los permisos sobre la BD etareas:
grant all on etareas.* to 'etareas'@'localhost' identified by 'etareas';
  • Una vez iniciada la aplicación por primera vez en modo test, esta creará las tablas en la BD. Después sólo queda añadir manualmente un usuario de tipo administrador:
insert into usuario(nombre,email,apellidos,identificador,rol,password,version) values  ("Peter","pp@etareas.com","Pattern","peterp","Admin","peterp",0);

Ya se ha creado la BD de la aplicación en producción pero ahora necesitamos crear la BD para las pruebas:

  • Crear la BD para la aplicación:
create database etareastest;
  • Seleccionar la BD:
use etareastest
  • Crear un usuario concediéndole todos los permisos sobre la BD etareas:
grant all on etareastest.* to 'etareas'@'localhost' identified by 'etareas';
  • Una vez iniciada la aplicación por primera vez en modo test, esta creará las tablas en la BD. Después sólo queda añadir manualmente un usuario de tipo administrador:
insert into usuario(nombre,email,apellidos,identificador,rol,password,version) values  ("Peter","pp@etareas.com","Pattern","peterp","Admin","peterp",0);


Bibliotecas

Las bibliotecas que vamos a utilizar en el desarrollo de nuestro proyecto son las siguientes:


Apache Ant

Apache Ant es una herramienta usada en programación para la realización de tareas mecánicas y repetitivas, normalmente durante la fase de compilación y construcción (build). Es similar a Make pero desarrollado en lenguaje Java y requiere la plataforma Java.

Para su instalación en Windows hay que seguir los siguientes pasos:

  • Descargar Ant de la siguiente dirección: http://ant.apache.org/
  • Descomprimir archivo y ponerla por ejemplo en C:\Ant
  • Abrir el panel de control de windows: Sistemas->Opciones Avanzadas->Variables de entorno
  • En Varibles del sistema creamos una nueva con los siguiente datos:
    • Nombre de varible: ANT_HOME
    • Valor de variable: C:\Ant
  • Modificamos la variable del sistema PATH:
    • Valor de variable: PATH=%PATH%;%ANT_HOME%\bin;

En versiones anteriores de Grails al crear una aplicación mediante el comando create-app se generaba automáticamente el fichero build.xml. En la versión que hemos utilizado, la 1.2.1, es necesario generar dicho fichero ejecutando el siguiente comando desde el directorio raiz del proyecto:

grails integrate-with --ant 

En el fichero build.xml se identifican los siguientes objetivos:

  • clean: limpia la aplicación Grails.
  • compile: compila el código fuente de la aplicación.
  • test: ejecutga los tests unitarios.
  • run: equivalente a "grails run-app"
  • war: crea un fichero WAR.
  • deploy: se utiliza pare implementar una distribución automática.


Cada uno de estos objetivos se puede ejecutar desde el directorio raiz del proyecto de la siguiente manera, por ejemplo:

ant war


JUnit

JUnit es un conjunto de bibliotecas que son utilizadas en programación para hacer pruebas unitarias de aplicaciones Java.

El framework que viene incorporado con la instalación por defecto de Grails es Junit3 y contiene las siguientes clases:

  • JUnit3GrailsEnvironmentTestSuite
  • JUnit3GrailsTestType
  • JUnit3GrailsTestTypeMode
  • JUnit3GrailsTestTypeResult
  • JUnit3GrailsTestTypeRunner
  • JUnit3ListenerEventPublisherAdapter


SVN

Para poder llevar un desarrollo en paralelo de la aplicación es necesario tener instalado un sistema de control de versiones.

Nuestro repositorio está situado en Assembla y para poder actualizar/descargarnos la última versión, es necesario configurar svn en Netbeans.

Los pasos para llevar a cabo esta tarea son:

  • Instalación:
    • Instalar svn en plataformas de 32 bits:
      • Dentro de Netbeans: Equipo -> Subversion -> Verificar
      • Obtener los binarios empaquetados
    • Instalar svn en plataformas de 64 bits:
      • Descargar el cliente svn
      • Instalarlo y agregarlo al PATH.
      • Reiniciar Netbeans.
  • Configurar el repositorio:
    • Equipo -> Subversion -> Verificar.
    • Introducir la dirección del repositorio.
    • Introducir el usuario y el password de Assembla.
    • Especificar la carpeta del repositorio donde se encuentra el proyecto.

Entregable E2: Requisitos y arquitectura

Introducción

El proyecto a desarrollar consiste en un sistema interactivo destinado a establecer una relación entre profesores y padres de un colegio de manera que los primeros especificarán en la web las tareas para casa encomendadas a los alumnos y los segundos podrán visualizar dichas tareas y realizar consultas al profesor sobre ellas.

Especificación preliminar

El modelo subyacente de intercambio de información entre los profesores y padres consistirá en un wiki. En nuestra aplicación, las asignaturas serán las páginas wiki. Bajo esta premisa la aplicación implementa las funcionalidades usuales:

  • Ver una asignatura
  • Listar asignaturas
  • Crear/Editar una asignatura
  • Publicar una asignatura
  • Despublicar una asignatura


Se establecen los siguientes perfiles de usuarios: administrador, profesor, padre/madre.

El sistema permitirá dar de alta usuarios de los perfiles profesor y padre/madre y páginas del siguiente tipo:

  • Asignatura: Creadas por los profesores que la podrán consultar y modificar. Los padres/madres se podrán suscribir a ellas para consultarlas.


El perfil administrador tendrá acceso a todas las funciones que se pidan de la aplicación.

El perfil padre/madre podrá consultar las páginas de asignatura en las que se haya registrado no pudiendo editarlas, ni publicar ni despublicar ninguna página de este tipo. Tendrá la posibilidad de enviar un mensaje al profesor que se publicará en la asignatura correspondiente. Los comentarios están asociados a la asignatura y serán visibles a todos los suscriptores de la misma así como al creador de la asignatura.

El perfil profesor podrá crear/editar páginas correspondientes a las asignaturas que imparte así como publicarlas y despublicarlas pero no borrarlas. El profesor posee las funcionalidades del perfil padre/madre.

Funcionalidades de la aplicación

A continuación se propone una versión preliminar de las funcionalidades con que debe ampliarse la aplicación y que deben dirigir el análisis y diseño.

  • Administración de usuarios: altas, bajas, modificaciones y listados de los usuarios registrados en el sistema.
  • Administración de Asignatura: crear, borrar, listar, ver, editar, publicar y despublicar asignaturas.
  • Seguridad: Inicio de sesión en la aplicación y registro de usuarios para el acceso a las páginas del wiki.
  • Administración de suscripciones: suscribirse y anular la suscripción.


Las funciones de Administración de suscripciones estarán disponibles para todos los perfiles de usuario. Las funciones de Administración de Asignatura estarán disponibles para el usuario que haya creado la asignatura con las limitaciones establecidas en el apartado anterior. Las funciones de Seguridad, administración de usuarios y las incluidas en los perfiles anteriores estarán disponibles para los usuarios administradores.

Arquitectura

La aplicación se desarrollara bajo la arquitectura MVC (Modelo Vista Controlador) empleando el framework Grails:

Modelo

El modelo de datos en una aplicación Grails está compuesto por las clases del Dominio, que se ubican en la carpeta grails-app/domain. Grails utiliza GORM, un gestor de persistencia escrito en Groovy, para controlar el ciclo de vida de las entidades y proporcionar una serie de métodos dinámicos que facilitan las búsquedas.

GORM está construido sobre Hibernate, una herramienta de mapeo objeto-relacional que se encarga de relacionar las entidades de una clase con las tablas de la BD y las propiedades de las entidades con los campos de las tablas.

Vista

Dentro del patrón MVC, la vista es la responsable de mostrar al usuario el estado actual del modelo de datos y las acciones a su disposición para que elija lo que desea hacer a continuación.

Grails incluye la tecnología GSP (Groovy Server Pages), inspirada en las páginas JSP.

Una vista en Graisl es un archivo con extensión gsp que reside en la carpeta grails-app/views de nuestro proyecto.


Controlador

Los controladores son los componentes responsables de recibir las órdenes del usuario, gestionar la ejecución de la lógica de negocio y después actualizar la vista para mostrar al usuario el estado en que ha quedado el modelo de datos.

La convención utilizada en Grails es que un controlador es cualquier clase que se encuentre en la carpeta grails-app/controllers de nuestro proyecto y cuyo nombre termine por Controller.

Una vez creado el modelo de datos, podemos solicitar a Grails que genere el controlador y las vistas necesarias para realizar operaciones CRUD con las entidades. Esta técnica se denomina scaffolding.

Diagramas de casos de uso

Sesión

Login
Cerrar sesión

Usuarios

Crear usuario
Editar usuario
Ver usuario
Eliminar usuario
Listar usuarios

Asignaturas

Crear asignatura
Editar asignatura
Ver asignatura
Eliminar asignatura
Listar asignaturas
Publicar/Despublicar asignatura
Suscribir a asignatura
Baja suscripción a asignatura
Buscar asignatura

Comentarios

Crear comentario

Entregable E3: Diagramas de análisis de robustez

Login

Crear asignatura

Editar asignatura

Ver asignatura

Listar asignatura

Crear comentario

Publicar/Despublicar asignatura

Eliminar asignatura

Cerrar sesión

Suscribir a asignatura

Cancelar suscripción de asignatura

Registrar usuario

Buscar asignatura

Consultar datos personales

Editar datos personales

Eliminar usuario

Listar usuarios

Entregable E4: Diseño

Patrones de diseño web empleados

  • Autocomplete: Se sugieren en una lista desplegable los posibles identificadores que se pueden consultar mediante la escritura en un campo de texto. Empleado en el buscador de asignaturas.
  • Action Button: Los botones de la aplicación tienen etiquetado el verbo correspondiente a la acción que realizan.
  • Paging: Cuando la lista de elementos sobre la que el usuario tiene que buscar es demasiado grande, se presentan agrupados en páginas con un número fijado de elementos permitiendo a los usuarios moverse fácilmente de unas páginas a otras.
  • View: Se muestra una vista general de una lista de objetos relacionados o de un mismo tipo (Lista de usuarios, lista de asignaturas suscritas, lista de mis asignaturas, lista de asignaturas publicadas, lista de todas las asignaturas).
  • Login: Cuando se necesite acceder a la aplicación se requerirá un nombre de usuario y una contraseña.
  • Registro: Los usuarios almacenan su información personal para un uso posterior.
  • Comment box: Se añade un pequeño formulario al final de una página y después del resto de comentarios de manera que permita a los usuarios enviar comentarios a la página. Usado para enviar comentarios en cada asignatura.
  • Constraint input: A la hora de introducir valores en un campo, sólo se permite al usuario escoger de entre un rango con la sintaxis correcta. Usado para cambiar el rol de los usuarios desde el perfil de administración.
  • Form: Se ofrece a los usuarios un formulario para que rellene los elementos necesarios. (Creación de asignaturas, creación de usuarios).
  • Footer Bar: Se incluye un pie de página con las condiciones de uso.
  • Alternating Row Colors: Se usan colores alternos en las filas de las tablas para hacerla más legible.
  • Input Error Message: Se indica a los usuarios que existe un problema, en qué lugar y cómo resolverlo. (Mensajes de validación a la hora de crear entidades).

Servicio web de usuarios

Se dispone de un servicio web que sigue la arquitectura REST e intercambia información en formato XML, con él se pueden realizar las operaciones relacionadas con la gestión de usuarios.

Existe un método en el controlador de Usuario llamado WS que se encarga de recibir la petición y analizar su tipo. En función de ello, llama a los métodos privados adecuados para gestionarla. Las peticiones HTTP tratadas son GET,POST, PUT y DELETE.

Para mostrar esta funcionalidad se usará rest-client que es una aplicación Swing que se puede utilizar para probar servicios web. La descarga de esta aplicación se encuentra en http://code.google.com/p/rest-client/

Para ejecutarla:

java -jar restclient-ui-2.3-jar-with-dependencies.jar

A continuación se muestran algunos ejemplos de uso.

Listar un usuario (petición GET)

Crear un usuario (petición POST)

La petición debe ser de tipo POST. El cuerpo de la petición debe ser del tipo “text/xml”;charset=UTF-8”. Los datos del usuario a dar de alta se proporcionan en formato XML tal y como se puede ver en la imagen. A continuación, se muestra el resultado de la petición una vez ejecutada.

En caso de error en la etiqueta <codigo> aparecería el valor 1 y en la etiqueta <mensaje> el motivo del error.

Modificar un usuario (petición PUT)

La petición debe ser de tipo PUT. El cuerpo de la petición debe ser del tipo “text/xml”;charset=UTF-8”. Los datos del usuario que vayan a ser modificados se proporcionan en formato XML tal y como se puede ver en la imagen. A continuación, Se muestra el resultado de la petición una vez ejecutada en la que se cambia la contraseña para el usuario cuyo id interno es 2.

Si el usuario no existiera se devolvería un resultado del siguiente tipo: <resultado> <codigo>1</codigo> <mensaje>El usuario no existe</mensaje> </resultado>

Borrar un usuario (petición DELETE)

La petición debe ser de tipo DELETE. El usuario a borrar se especifica en la URL.

En caso de error en la etiqueta <codigo> aparecería el valor 1 y en la etiqueta <mensaje> el motivo del error.

Entregable E5: casos de prueba

A la hora de diseñar las pruebas hemos seguido la siguiente documentación:

Una vez creados los tests, los pasos necesarios para ejecutarlos son los siguientes:

  1. Botón derecho sobre el nombre del proyecto -> Run Grails Command.
  2. Ejecutar: test-app.
  3. Entrar en: eTareas/target/test-reports/html/etareas.
  4. Visualizar el fichero HTML que contiene los resultados del test deseado.


La generación de pruebas unitarias ya viene integrada en un proyecto básico de Grails. Para crear pruebas funcionales es necesario instalar un plugin dentro del proyecto para que los test se puedan ejecutar correctamente, por lo que es necesario realizar los siguientes pasos:

  • Crear una carpeta plugins dentro del proyecto.
  • Modificar el fichero BuildConfig.groovy que está en la carpetas grails-app/conf y añadirle la línea: grails.project.plugins.dir = "./plugins"
  • Botón derecho sobre el nombre del proyecto -> Run Grails Command.
  • Ejecutar: install-plugin webtest
  • Ejecutar: create-webtest etareas.nombreTest


Los pasos para ejecutar la batería de tests vienen indicados en el manual de instalación situado en el entregable E8.


Usuario

A continuación se detallan las pruebas unitarias y funcionales relacionadas con la entidad Usuario.

Pruebas unitarias

Las pruebas unitarias creadas en el archivo UsuarioTests.groovy realizan las siguientes comprobaciones:

  • Test 1: se comprueba que se crea bien un objeto de tipo usuario.
  • Test 2: se comprueba que un usuario se guarda correctamente en la BD.
  • Test 3: se comprueba que un usuario se ha borrado correctamente de la BD


Resultado:

Pruebas funcionales y de integración

Las pruebas creadas en el archivo UsuariosWebTests.groovy realizan las siguientes comprobaciones:

  • Test 0: en todos los tests el usuario inicia correctamente la sesión.
  • Test 1: comprueba que un usuario se puede registrar correctamente.
  • Test 2: comprueba todos los casos posibles en los que falla el registro de un nuevo usuario.
  • Test 3: comprueba que los usuarios se listan correctamente.
  • Test 4: comprueba que un usario es editado correctamente.
  • Test 5: comprueba que un usuario es eliminado correctamente.


Resultado:

Página

A continuación se detallan las pruebas unitarias y funcionales relacionadas con la entidad Página.

Pruebas unitarias

Las pruebas unitarias creadas en el archivo PaginaTests.groovy realizan las siguientes comprobaciones:

  • Test 1: se comprueba que se crea bien un objeto de tipo página.
  • Test 2: se comprueba que una página se guarda correctamente en la BD.
  • Test 3: se comprueba que una página se ha borrado correctamente de la BD


Resultado:

Pruebas funcionales y de integración

Las pruebas creadas en el archivo PaginasWebTests.groovy realizan las siguientes comprobaciones:

  • Test 1: comprueba que una página se crea correctamente y que no deja crear otra con el mismo título.
  • Test 2: comprueba que una página se edita correctamente. Produce un fallo que será tratado más abajo.
  • Test 3: comprueba que se listan correctamente todas las páginas de la aplicación.
  • Test 4: comprueba que se listan correctamente las asignaturas que ha creado el usuario que ha iniciado la sesión.
  • Test 5: comprueba que cuando un usuario crea una página, automáticamente se suscribe a ella y que las acciones publicar/despublicar funcionan correctamente. Inicialmente la página no aparece en "Mis suscripciones" porque no está publicada, pero una vez que se publique sí lo hará.
  • Test 6: comprueba que una página se elimina correctamente y que al hacerlo desaparece de "Mis suscripciones", de "Mis asignaturas" y de "Todas las asignaturas".


Resultado:

Test 2

Este test intenta comprobar que una página se edita correctamente. El problema que encuentra es que el editor WYSIWYG está hecho en javascript y el plugin de las pruebas funcionales, Webtest, no lo permite. Vamos a ir mostrando el error paso a paso:

  1. El editor que se obtiene al ejecutar la aplicación es el siguiente.
  2. Cuando se ejecuta el test se obtiene un error porque no encuentra el elemento html con id=contenido. El error se debe a que intenta llamarse a una función JavaScript.
  3. Si se observa la página que se ha generado al ejecutar los tests se puede apreciar que los botones del editor no aparecen y que el elemento con id=contenido sí existe pero no puede acceder a él.
Archivo:Editor.png
1. Editor original
Archivo:FalloEditar.png
2. Fallo encontrado
Archivo:PaginaGenerada.png
3. Editor generado por Webtest

Comentario

A continuación se detallan las pruebas unitarias y funcionales relacionadas con la entidad Comentario.

Pruebas unitarias

Las pruebas unitarias creadas en el archivo ComentarioTests.groovy realizan las siguientes comprobaciones:

  • Test 1: se comprueba que se crea bien un objeto de tipo comentario.
  • Test 2: se comprueba que un comentario se guarda correctamente en la BD.
  • Test 3: se comprueba que un comentario se ha borrado correctamente de la BD


Resultado:

Pruebas funcionales y de integración

Las pruebas creadas en el archivo ComentarioWebTests.groovy realizan las siguientes comprobaciones:

  • Test 1: comprueba que un comentario se crea correctamente.


Resultado:


Suscripción

A continuación se detallan las pruebas unitarias y funcionales relacionadas con la entidad Suscripción.

Pruebas unitarias

Las pruebas unitarias creadas en el archivo SuscripcionTests.groovy realizan las siguientes comprobaciones:

  • Test 1: se comprueba que se crea bien un objeto de tipo suscripción.
  • Test 2: se comprueba que una suscripción se guarda correctamente en la BD.
  • Test 3: se comprueba que una suscripción se ha borrado correctamente de la BD


Resultado:

Pruebas funcionales y de integración

Las pruebas creadas en el archivo SuscripcionWebTests.groovy realizan las siguientes comprobaciones:

  • Test 1: comprueba que un usuario puede suscribirse correctamente a una asignatura.
  • Test 2: comprueba que un usuario elimina su suscripción a una asignatura correctamente.


Resultado:

Todas las entidades

Resultado de ejecutar todos los tests funcionales y de integración a la vez:

Entregable E6: diseño del esquema de la base de datos y del ORM

Diagrama E/R de la Base de Datos

El siguiente es el diagrama original de BD:


Finalmente dicho diagrama, por los problemas que generan en Grails las relaciones M:N, ha tenido que ser sustituido por el siguiente:


Grails Object Relational Mapping(GORM)

Grails usa una configuración personalizada de APIs de Hibernate para permitir de una manera muy fácil el mapeo Objeto-Relacional mediante el uso de convenciones. Esta técnica de mapeo se denomina GORM (Grails Object-Relational Mapping). GORM crea un envoltorio de Hibernate para ser utilizado mediante capas escritas en lenguaje Groovy. Aquí no se utiliza ficheros de configuración externos basados en XML.

El proceso utilizado por Hibernate para convertir un modelo en una tabla es el siguiente:

  1. Se crea una tabla por cada modelo manteniendo el mismo nombre.
  2. Se crea en cada tabla una columna por cada atributo del modelo manteniendo las restricciones establecidas a través de las constraints.
  3. Se crea implícitamente un campo id único en cada tabla.
  4. Se añade un campo version a través del cual Hibernate gestiona la integridad transaccional.


Tanto el campo id como el campo version van a ser excluirlos de los diagramas de las tablas ya que unicamente serán usados internamente por Grails.


Modelo en Grails de Usuario package etareas

class Usuario {

   static hasMany = [usuarioSuscripciones:Suscripcion, paginasCreadas:Pagina, comentarios:Comentario]
   static mappedBy = [usuarioSuscripciones:"usuarioSuscrito", paginasCreadas:"propietario", comentarios:"comentador"]

   String identificador
   String password
   String nombre
   String apellidos
   String email
   String rol
    
   Set usuarioSuscripciones
   Set paginasCreadas
   List comentarios


   String toString(){
       return identificador
   }

   static constraints = {
       identificador(unique:true,blank:false)
       nombre(blank:false)
       apellidos(nullable:false,blank:false)
       password(password:true,blank:false)
       email(email:true,blank:false)
       rol(blank:false)
       usuarioSuscripciones(nullable:true)
       paginasCreadas(nullable:true)
       comentarios(nullable:true)

   }

   static roles = ["Admin","Profesor","Padre"]

}


Modelo en Grails de Pagina

package etareas

class Pagina {

   static hasMany = [paginaSuscripciones:Suscripcion,comentariosPagina:Comentario]
   static mappedBy = [paginaSuscripciones:"paginaSuscrita", comentariosPagina:"paginaPertenencia"]
   static belongsTo = Usuario

   List comentariosPagina
   Boolean publicada 
   String titulo
   String contenido
   Usuario propietario
   Set paginaSuscripciones

   String toString(){
       return titulo
   }

   static constraints = {
       propietario(nullable:false)
       titulo(unique:true, blank:false)
       contenido(nullable:true, maxSize:999999)
       publicada(nullable:false)
       paginaSuscripciones(nullable:true)
       comentariosPagina(nullable:true)
   }
}

Modelo en Grails de Comentario

package etareas

class Comentario {

   static belongsTo = [Usuario, Pagina]
 
   Date fecha
   String texto
   Usuario comentador
   Pagina paginaPertenencia

   static constraints = {
       comentador(nullable:false)
       paginaPertenencia(nullable:false)
       texto(blank:false, maxSize:1000)
   }
}


Modelo en Grails de Suscripción

package etareas

class Suscripcion {

   static belongsTo = [Usuario, Pagina]

   Usuario usuarioSuscrito
   Pagina paginaSuscrita

   static constraints = {
       usuarioSuscrito(nullable:false)
       paginaSuscrita(nullable:false)
   }
}


Mapeo objeto-relacional

Entregable E7: código implementado

Repositorio en Assembla

Entregable E8: manuales

Manual de usuario

Manual de instalación

Herramientas personales