Capítulo 2: Mi primer proyecto OX
Crear un proyecto nuevo
Una vez abierto el Eclipse y apuntando al
workspace que viene en la distribución de OpenXava.
Usando el asistente de Eclipse apropiado hemos de crear un nuevo proyecto Java llamado
Gestion. Ahora tenemos un proyecto Java vacío en el
workspace, el siguiente paso es darle la estructura correcta para un proyecto OpenXava.
Vamos al proyecto
OpenXavaPlantilla y editamos el archivo
CrearNuevoProyecto.xml de esta forma:
<property name="proyecto" value="Gestion" />
Ahora hemos de ejecutar
CrearNuevoProyecto.xml usando Ant. Podemos hacerlo con
Botón Derecho en CrearNuevoProyecto.xml > Run as > Ant Build
Seleccionamos el proyecto
Gestion y pulsamos F5 para refrescar.
Con esto ya tenemos nuestro proyecto listo para empezar a trabajar, pero antes de nada tenemos que tener una base de datos configurada.
Configurar base de datos
OpenXava genera una aplicación Java EE/J2EE pensada para ser desplegada en un servidor de aplicaciones Java (desde la v2.0 las aplicaciones OpenXava también funcionan en un simple servidor de servlets, como Tomcat). Dentro de OpenXava solo se indica el nombre JNDI de la fuente de datos, y en nuestro servidor de aplicaciones tenemos que configurar nosotros esa base datos. El configurar una fuente de datos en un servidor de aplicaciones es algo que va más allá de esta guía, sin embargo a continuación se da las instrucciones concretas para poder realizar este primer proyecto usando el Tomcat incluido en la distribución de OpenXava e Hypersonic como base de datos. Este Tomcat esta en la carpeta
openxava-3.x/tomcat.
Con el Tomcat parado editar el archivo
context.xml en el directorio de Tomcat
conf, en ese archivo tenemos que añadir la siguiente entrada:
<Resource name="jdbc/GestionDS" auth="Container" type="javax.sql.DataSource"
maxActive="20" maxIdle="5" maxWait="10000"
username="sa" password="" driverClassName="org.hsqldb.jdbcDriver"
url="jdbc:hsqldb:hsql://localhost:1666"/>
Lo importante aquí es el nombre JNDI, que es a lo único que se hace referencia desde OpenXava, en este caso
MiGestionDS. Los atributos
driverClassName y
url dependen de nuestra base de datos, en este caso estamos usando Hypersonic.
Nuestro primer componente de negocio
Crear un componente de negocio OpenXava es fácil: La definición para cada componente es una clase Java con anotaciones. Para empezar vamos a crear una clase llamada
Almacen:
- Nos ponemos en la carpeta src y usamos Botón Derecho > New > Package
- Creamos un paquete llamado org.openxava.gestion.modelo
- Nos ponemos en el paquete org.openxava.gestion.modelo y usamos Botón Derecho > New > Class
- Creamos una clase llamada Almacen
Ahora hemos de editar nuestra nueva clase y escribir el siguiente código:
package org.openxava.gestion.modelo;
import javax.persistence.*;
import org.openxava.annotations.*;
@Entity
public class Almacen {
@Id @Column(length=3) @Required
private int codigo;
@Column(length=40) @Required
private String nombre;
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
}
Esta clase contiene (y contendrá) toda la información necesaria por la aplicación sobre el concepto de negocio de Almacen. En este momento sólo tenemos la estructura de datos, pero en esta clase podemos poner el mapeo contra la base de datos, la lógica de negocio, la presentación visual, el manejo de datos tabulares, etc.
En realidad esta clase es una
Entity que sigue el estándar EJB3. Para definir una clase como una entidad lo único que necesitamos es usar la anotación
@Entity en la declaración de la clase.
Dentro de entidad vemos definidas un conjunto de propiedades, vamos a examinarlo:
@Id // 1
@Column(length=3) // 2
@Required // 3
private int codigo; // 4
private int getCodigo() { // 4
return codigo;
}
private void setCodigo(int codigo) { // 4
this.codigo = codigo;
}
Este es su significado:
- @Id: Indica si esta propiedad forma parte de la clave. La clave identifica a cada objeto de forma única y normalmente coincide con la clave en la tabla de base de datos.
- @Column(length= ): Longitud de los datos visualizados. Es opcional, pero suele ser útil para hacer mejores interfaces gráficos y generar las tablas de la base de datos.
- @Required: Indica si hay que validar la existencia de información en esta propiedad antes de crear o modificar.
- La propiedad definida de la forma usual para una clase Java. Todo tipo válido para una propiedad Java se puede poner, lo que incluye tipos integrados, clases del JDK, clases propias, etc.
Las posibilidades de una propiedad van mucho más allá de lo que aquí se muestra, se puede ver una explicación más completa en el capitulo sobre el
modelo.
La tabla
Antes de poder probar la aplicación hemos de crear la tabla en la base de datos:
- Arrancamos la base de datos: Desde la línea de órdenes vamos a la carpeta openxava-3.x/tomcat/bin y ejecutamos:
- En Linux/Unix: ./start-hsqldb.sh gestion-db 1666
- En Windows: start-hsqldb gestion-db 1666
- Creamos la tabla:
- Editamos Gestion/build.xml. Buscamos la tarea ant actualizarEsquema.
- Ponemos el valor correcto para schema.path, en este caso “../OpenXavaTest/lib/hsqldb.jar”.
- Ejecutamos la tarea ant actualizarEsquema.
- Arrancamos el Tomcat y ya está todo listo.
Ejecutar nuestra aplicación
Después de nuestro duro trabajo tenemos derecho a ver el fruto de nuestro sudor, así que allá vamos:
Y ahora podemos jugar con nuestro módulo y ver como funciona.
También puedes desplegar el módulo como portlet JSR-168, de esta forma:
- Ejecutamos la tarea ant generarPortlets.
- Coge el archivo Gestion.war en la carpeta openxava-3.x/workspace.dist/Gestion.dist y despliegalo en tu portal.
Automatizando las pruebas
Aunque parece que lo más natural es probar la aplicación con un navegador e ir viendo lo mismo que verá el usuario; lo cierto es que es más productivo automatizar las pruebas, de esta forma a medida que nuestro sistema crece, lo tenemos atado y evitamos que al avanzar rompamos lo que ya teníamos.
OpenXava usa un sistema de pruebas basado en JUnit y HttpUnit. Las pruebas JUnit de OpenXava emulan el funcionamiento de un usuario real con un navegador, de esta forma podemos replicar de forma exacta las mismas pruebas que haríamos nosotros mismos con un navegador. La ventaja de este enfoque es que probamos de forma sencilla desde el interfaz gráfico al acceso a la base de datos.
Si probáramos el modulito manualmente normalmente crearíamos un registro nuevo, lo buscaríamos, lo modificaríamos y lo borraríamos. Vamos a hacer eso automáticamente.
En primer lugar crearemos un paquete en donde poner las pruebas,
org.openxava.gestion.pruebas, y en este paquete pondremos una clase llamada
PruebaAlmacen, y pegaremos en ella el siguiente código:
package org.openxava.gestion.pruebas;
import org.openxava.tests.*;
/**
* @author Javier Paniza
*/
public class PruebaAlmacen extends ModuleTestBase {
public PruebaAlmacen(String testName) {
super(testName, "Gestion", "Almacen"); // 1
}
public void testCrearLeerModificarBorrar() throws Exception {
// Creamos
execute("CRUD.new"); // 2
setValue("codigo", "7"); // 3
setValue("nombre", "Almacen JUNIT");
execute("CRUD.save");
assertNoErrors(); // 4
assertValue("codigo", ""); // 5
assertValue("nombre", "");
// Leeemos
setValue("codigo", "7");
execute("CRUD.search");
assertValue("codigo", "7");
assertValue("nombre", "Almacen JUNIT");
// Modificamos
setValue("nombre", "Almacen JUNIT MODIFICADO");
execute("CRUD.save");
assertNoErrors();
assertValue("codigo", "");
assertValue("nombre", "");
// Comprobamos modificado
setValue("codigo", "7");
execute("CRUD.search");
assertValue("codigo", "7");
assertValue("nombre", "Almacen JUNIT MODIFICADO");
// Borramos
execute("CRUD.delete");
assertMessage("Almacen borrado satisfactoriamente"); // 6
}
}
Podemos aprender de este ejemplo:
- Constructor: En el constructor indicamos el nombre de la aplicación y el nombre del módulo.
- execute: Permite simular la pulsación de un botón o vínculo. Como argumento se envía el nombre de la acción; los nombres de las acciones los podemos ver en OpenXava/xava/default-controllers.xml (los controladores predefinidos) y Gestion/xava/controladores.xml (los propios). También si paseamos el ratón sobre el vínculo el navegador nos mostrará la acción JavaScript a ejecutar, que contiene el nombre de acción OpenXava. Es decir execute(“CRUD.new”) es como pulsar el botón de nuevo en la interfaz gráfica.
- setValue: Para asignar valor a un control del formulario. Es decir, setValue(“nombre”, “Pepe”) tiene el mismo efecto que teclear en el campo de texto 'Pepe'. Los valores siempre son alfanuméricos, ya que se asignan a un formulario HTML.
- assertNoErrors: Comprueba que no se hayan producido errores. En la interfaz gráfica los errores son mensajes en color rojo, que son añadidos por la lógica de la aplicación.
- assertValue: Comprueba que el valor contenido en un elemento del formulario es el indicado.
- assertMessage: Verifica que la aplicación ha producido el mensaje informativo indicado.
Se puede ver como de forma sencilla podemos probar que el mantenimiento funciona, escribir un código como este puede costar 5 minutos, pero a la larga ahorra horas de trabajo, porque a partir de ahora podemos probarlo todo en 1 segundo, y porque nos va a avisar a tiempo cuando rompamos la gestión de Almacenes tocando otra cosa.
Para más detalle podemos ver el API JavaDoc de
org.openxava.tests.ModuleTestBase y examinar los ejemplos que hay en
org.openxava.test.tests de OpenXavaTest.
Por defecto la prueba se ejecuta contra el módulo en modo solitario (fuera del portal) (es decir desplegado con
desplegarWar). Pero si lo deseamos es posible testear contra la versión de portlet (es decir desplegado con
generarPortlets). Solo necesitamos editar el archivo
properties/xava-junit.properties y escribir:
liferay.url=web/guest
Esto para probar contra el portal Liferay. También es posible probar contra el portal JetSpeed2, mira en
OpenXavaTest/properties/xava-junit.properties para ver cómo.
Las etiquetas
Ya nos funciona, pero hay un pequeño detalle que se ha quedado suelto. Posiblemente queramos definir las etiquetas que se mostrarán al usuario. La forma de hacerlo es escribiendo un archivo con todas las etiquetas, y así podemos traducir nuestro producto a otro idioma con facilidad.
Para definir las etiqueta solo tenemos que editar el archivo
EtiquetasGestion_es.properties en la carpeta
i18n. Editar ese archivo y añadir:
Almacen=Almacén
No es necesario poner todas las propiedades, porque los casos más comunes (codigo, nombre, descripcion y un largo etc) ya los tiene OpenXava incluidos en Español, Inglés, Polaco, Alemán, Francés, Indonesio y Catalán.
Si queremos una versión en otro idioma (inglés, por ejemplo) solo tenemos que copiar y pegar con el sufijo apropiado. Por ejemplo, podemos tener un
EtiquetasGestion_en.properties con el siguiente contenido:
Almacen=Warehouse
Las etiquetas y mensaje por defecto de OpenXava están en
OpenXava/i18na/Labels.properties y
OpenXava/i18n/Messages.properties. Si queremos sobreescribir algunos de estos recursos no necesitamos editar estos archivos, sino que podemos usar los mismos nombres de clave en los archivos de recursos de nuestro proyecto, entonces nuestras etiqueta y mensajes seran usadas en vez de las estándar de OpenXava
(nuevo en v2.0.3). Por ejemplo, si queremos cambiar el mensaje estandar en modo lista '
'Hay 23663 registros en la lista” por otro, hemos de añadir a
MensajesGestion_es.properties esta entrada:
# list_count está en Messages_en.properties de OpenXava, este es un ejemplo
# de sobreescritura de un mensaje estándar de OpenXava
list_count=Hay {0} objetos en la lista
Ahora, nuestra aplicación mostrará
“Hay 23663 objetos en la lista” en vez del mensaje por defecto de OpenXava “
'Hay 23663 registros en la lista”.
Para saber más sobre como definir las etiquetas de nuestros elementos OpenXava podemos echar un vistazo a los archivos de
OpenXavaTest/i18n.