Narciso Cerezo

Tecnología y emprendizaje

Java

Seminario sobre desarrollo móvil y OpenBaseMovil

Estos últimos meses han sido realmente una vorágine de acontecimientos, hemos (y seguimos) ampliado la plantilla, levantado fondos, planificado,... me ha quedado poco tiempo para publicar nada, la verdad.
Ahora seguimos con la misma actividad frenética, pero hay tanto que contar que empezaré hoy anunciando algo que es un orgullo:
Desde mañana, impartiremos un seminario en la Facultad de Informática de la Universidad Complutense de Madrid. Es un seminario para alumnos de últimos cursos de las tres carreras de Informática en el que abordaremos el desarrollo de aplicaciones móviles, fundamentalmente con JavaME y con un módulo específico sobre nuestra tecnología OpenBaseMovil.
El seminario ha despertado gran interés entre los alumnos: 40 tendrán la oportunidad de asistir, y más de 100 tendrán que esperar a la siguiente convocatoria del seminario.
Poder dar un seminario semejante es un orgullo, y que la acogida sea tan buena lo hace aún mayor.
Cuando acabemos el seminario publicaré también las conclusiones, con algunas fotos ilustrativas.

Sneak preview: desarrollo de aplicaciones móviles con BaseMovil

Este seguramente será el primero de una serie en la que quiero ir profundizando en cómo se pueden hacer aplicaciones móviles, realmente rápido, con BaseMovil.
Todavía no está abierto, de ahí lo de "sneak preview", pero lo estará dentro de poco. De hecho habrá dos fases: una primera para los "betatesters" que podrán empezar a trastear y hacer sus aplicaciones, y una segunda en la que se abrirá a cualquiera que quiera hacer aplicaciones con nuestros sistema e infraestructura.
Hoy voy a hablar simplemente de la creación de la interfaz de usuario.
El desarrollo es puramente conceptual, desapegado de la implementación final de la que se encarga el generador de vistas. De esta forma el código que hay que hacer está exclusivamente en el controlador y el modelo, ya que las vistas son sólo una definición vía XML.

El caso quizás más simple es un menú, implementado como una lista de selección, y al que se le pueden poner iconos a la izquierda de cada opción.
Cada opción del menú lleva asociado un código numérico que es el que permite al controlador saber que opción ha seleccionado el usuario.
Para crear un menú basta con definir la vista de esta forma:

<menu id="100" name="mainMenu" title="mainMenu.Title" >
    <menuItem title="mainMenu.Customers" action="100"/>
    <menuItem title="mainMenu.Options" action="101"/>
    <menuItem title="mainMenu.Exit" action="102"/>
</menu>

Para mostrar el menú necesitaríamos hacer esto desde el controlador:

final MenuView view = ViewFactory.getMenu( "mainMenu" );
view.show();

Y nos mostraría un menú de selección simple, con tres opciones.
Los campos title pueden ser un texto concreto, pero en este caso son una referencia a un recurso, de forma que el texto concreto dependerá del idioma seleccionado.

Otro caso típico es querer hacer un listado de una consulta (del motor de datos hablaré en el siguiente post de la serie). Digamos que queremos listar los clientes cuyo nombre contiene "bar".
Para definir el listado que mostrará el resultado sólo tenemos que definir la vista mediante el siguiente fragmento de XML (ya haremos un editor gráfico para los más vagos):

<listBrowser id="110" name="customerList" title="customerList.Title" pageSize="20">
    <field name="cust_name" />
    <field name="phone" />
</listBrowser>

Y para mostrarlo haría falta un pedazo de código Java similar a esto:

final RowSet result = CustomerModel.findCustomersByName( "bar" );
final ListBrowserView view = ViewFactory.getListBrowser( "customerList" );
view.bind( result );
view.show();

Con eso ya nos mostraría una pantalla de listado con los campos especificados, con paginación cada 20 elementos.
Si decidimos mostrar además del nombre y el teléfono la dirección sería tan sencillo como variar la definición por esto:

<listBrowser id="110" name="customerList" title="customerList.Title" pageSize="20">
    <field name="cust_name" />
    <field name="address" />
    <field name="phone" />
</listBrowser>

Y aunque los listados están muy bien como ejemplo de "data binding" sencillo, también se puede hacer un data binding más complejo con los formularios.
Una vez que hemos seleccionado el cliente queremos poder editar algunos datos de su ficha, y para eso nada mejor que un formulario de datos:

<form id="120" name="customerEditor" title="customerEditor.Title">
    <text name="name"
            
label="customer.CommercialName"
             bind="cust_name"
    />
    <text name="fiscalName"
            
label="customer.FiscalName"
             bind="company_name"
    />
    <integer name="code"
            
label="customer.CustomerCode"
             bind="custom_id"
             readOnly="true"
    />
</form>

Para mostrar el formulario, podríamos hacer algo similar a esto:

final ListBrowserView listView = ViewFactory.getListBrowser( "customerList" );
final
DataFormView form = ViewFactory.getDataForm( "customerSelector" );
form.bind( listView.getSelected() );
form.show();


Eso nos mostraría un formulario con una casilla de texto editable para el nombre comercial, otra para el nombre fiscal, y una no editable para el código de cliente. El formulario tiene automáticmente también una acción de aceptar y otra de cancelar, y si pulsamos en aceptar actualiza la fila de datos con los contenidos del formulario y los graba de nuevo en la tabla correspondiente.

¿Sencillo, no?

En próximos artículos exploraremos un poco más las posibilidades, sólo estamos arañando la superficie, pero como comienzo creo que está bien.
La enorme ventaja de esta forma de crear las pantallas, además de la rapidez, es que es algo completamente conceptual y que nos despega completamente de la implementación final de las pantallas y sus complejidades. Entre ellas, el discernir entre diferentes dispositivos para hacer la presentación más adecuada.
Y además brinda opciones adicionales, tales como que podemos hacer que cada cliente final de la aplicación pueda definir que campos quiere ver en cada pantalla, ya que la definición de las vistas es algo dinámico y que puede descargarse remotamente.


¿Qué te parece? ¿Alguna sugerencia? ¿Te gustaría hacer de beta tester para luego comercializar tus propias aplicaciones?

El próximo post será de tecnología

Bueno, o por lo menos uno de los próximos. Hace poco que he descubiero una herramienta open source (con dual licensing) que es muy buena. La estamos probando y parece claro que vamos a seguir en esa línea para la interfaz web de BaseMovil. Así que en uno de los próximos posts hablaré de nuevo de tecnología pura y dura :-)

Java sobre ruedas

Hace ya unos años que vi en un programa de televisión sobre coches que cierto fabricante estaba ya haciendo pruebas para poner sistemas basados en MS Windows CE (ahora PocketPC) dentro de sus coches. Y con dentro quiero decir controlando la electrónica del coche, desde temas como puede ser la inyección electrónica o la alarma hasta cosas más de entretenimiento como el GPS o DVD. Este "prodigio" sería capaz de hacer cosas como por ejemplo detectar componentes que pudieran estar a punto de fallar, de controlar cuando debemos llevar el coche a revisión, y lo que es mejor, concertar automáticamente una cita con el taller para ello. Aún hay más, también sería capaz de autoactualizarse sobre la marcha, con algo similar al Windows Update pero específico para esto. Para ello utilizaría el teléfono móvil integrado.
Aquello no llegó a salir (usaba Windows CE).
Pero ahora hay algo similar que va a salir ya a la calle, de momento sobre los BMW serie 5, 6 y 7, y que funciona con Java. Aunque no controla nada de electrónica del propio coche (mejor) y se dedica exclusivamente al tema de entretenimiento y comunicación. En los coches con navegador y pantalla a color vendrá este sistema, que permite controlar el navegador, la radio, el teléfono móvil, la climatización, la televisión, el dvd, el GPS, etc.
De momento funciona con Personal Java, que está siendo abandonado en favor de J2ME, pero ya están realizando la adaptación para que funcione con J2ME CDC (CDC es una versión de J2ME para dispositivos con más capacidad que los teléfonos móviles, que funcionan sobre CLDC).
Esto abre un mundo de posibilidades muy grande de cara a los desarrolladores de aplicaciones móviles, un campo en auge y con gran futuro y con el que tengo mucho que ver en estos últimos tiempos.
El sistema está pensado para montarlo en cualquier vehículo, no solo en BMW, y cuando empiecen a extenderse (cada vez son más los coches con navegador gps) serán muchas las posibilidades, no solo de aplicaciones de entretenimiento, sino tabmién de negocio.
Más información:

Hibernate y JBoss

Lo prometido es deuda, así que hoy voy a explicar cómo he integrado Hibernate y JBoss.
Lo primero que hay que tener en cuenta son las versiones, esto aplica a JBoss 3.2.x (en concreto estoy trabajando actualmente con la 3.2.5) y a Hibernate 2.1.6. La versión 2.1.4 de Hibernate tenía un fallo que impedía su uso con JBoss así que es imporante utilizar la 2.1.6 que ahora es la última disponible.
Al grano.
Con Hibernate creamos los denominados POJO (Plain Old Java Objects) o Java Beans, e Hibernate se encarga de manejar la persistencia de dichos objetos. Hibernate nos permite una flexibilidad increiblemente mayor que los Entity Beans a la hora de diseñar la estructura de clases, y eso significa que podemos hacer diseños de una granularidad muy fina, usar la herencia adecuadamente y crear componentes (otros POJOs) que actúen como campos de nuestras entidades.
Para hacer que Hibernate funcione con JBoss hemos de crear un archivo de servicio dentro de nuestra aplicación, es decir un archivo .SAR, pero como queremos poder llamar a nuestras clases desde el resto de la aplicación, en dicho .SAR sólo irá el archivo de servicio y los archivos descriptores de nuestras entidades (los .hbm.xml). Y algo más... también hemos de incluir el archivo de servicio que creará la fuente de datos (DataSource) uitilizado por Hibernate.
Yo utilizo XDoclet y Ant para la automatización de todo este proceso, aunque XDoclet introduce algunas limitaciones sigue siendo lo suficientemente interesante.
Por otro lado, en nuestro archivo de aplicación (.EAR) tenemos que hacer referencia a los diferentes servicios en el orden adecuado, así como incluir todas las librerías necesarias: las que necesita Hibernate, una con las clases que representan nuestras entidades y el resto que necesite nuestra aplicación.
En definitiva, nuestra aplicación debe tener la siguiente estructura:
aplicacion.EAR
|
|- hibernate.SAR
| |
| |- descriptores
| |- META-INF/
| |
| |- datasource.xml
| |- jboss-service.xml
|- lib/
| |- dependencias de Hibernate
| |- model.jar
| |- demás librerías que necesite la aplicación
|
|- META-INF/
| |
| |- application.xml
| |- jboss-app.xml

Dónde:

  • descriptores es la jerarquía de directorios paralela a nuestra jerearquía de clases persistentes con los ficheros .hbm.xml correspondientes

  • datasource.xml es el descriptor de nuestro origen de datos (más información en la documentación de JBoss)

  • jboss-service.xml es el descriptor del servicio Hibernate. Yo lo genero automáticamente con Ant y XDoclet, es lo más cómodo y seguro para no equivocarse. En cualquier caso os doy un ejemplo

  • model.jar es nuestro modelo, las clases persistentes que manejará Hibernate empaquetadas en un jar.

  • application.xml es el descriptor de aplicación J2EE (más información en la documentación de Java J2EE). Aquí lo importante es hacer referencia a todas las librerías y servicios de nuestra aplicación, así que también os pongo un ejemplo.

  • jboss-app.xml es el descriptor de aplicación específico de JBoss, en el se hace referencia al servicio de Hibernate y a otros que podamos tener en nuestra aplicación (más información en la documentación de JBoss). También os doy otro ejemplo


Ejemplos:
1. Archivo de servicio para hibernate.SAR






code="net.sf.hibernate.jmx.HibernateService"
name="jboss.jca:service=Model"
>
jboss.jca:service=RARDeployer

com/sample/app/model/Role.hbm.xml,
com/sample/app/model/common/Telephone.hbm.xml,
(other descriptors)

name="JndiName"
>java:/hibernate/DefaultSessionFactory

name="Datasource">java:/myDS
name="Dialect">net.sf.hibernate.dialect.MyDialect

name="ShowSql">false
name="UserTransactionName">UserTransaction

name="TransactionStrategy"
>net.sf.hibernate.transaction.JTATransactionFactory

name="TransactionManagerLookupStrategy"
>
net.sf.hibernate.transaction.JBossTransactionManagerLookup





2. Archivo de aplicación


PUBLIC '-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN'
'http://java.sun.com/dtd/application_1_3.dtd'>

Mi Aplicación



lib/my-jdbc-driver.jar




lib/model.jar




lib/c3p0-0.8.4.5.jar


lib/cglib-full-2.0.2.jar


lib/commons-collections-2.1.1.jar


lib/commons-lang-1.0.1.jar


lib/concurrent-1.3.3.jar


lib/dom4j-1.4.jar


lib/ehcache-0.9.jar


lib/hibernate2.jar


lib/jaas.jar


lib/jcs-1.0-dev.jar


lib/odmg-3.0.jar


lib/oscache-2.0.jar


lib/swarmcache-1.0rc2.jar




ejbs/01-model.jar





my.war
/my




3. Archivo de aplicación de JBoss




model.sar





Y con esto terminamos por hoy. Con estas instrucciones no deberías tener problemas para empezar rápidamente con Hibernate y JBoss, sobretodo si utilizais Ant y XDoclet, lo cual os aconsejo.

Consideraciones de diseño con JUnit

Hace tiempo que no escribo en el blog, pero es que mi actual proyecto consume todo mi tiempo. No obstante, merece la pena, porque es el más importante que he emprendido profesionalmente hablando.
Pero vamos al grano...
Aunque todavía no he terminado de entrar en la dinámica del desarrollo guiado por pruebas, al estilo de XP, hace ya tiempo que estoy "infectado por los tests". No hay duda de que el tiempo que "pierdes" escribiendo los test con JUnit es un tiempo bien empleado, puesto que luego puedes tener la tranquilidad de que si los test funcionan es más que probable que todo funcione. De hecho es la única manera de poder hacer test de regresión sin apenas esfuerzo y estar totalmente seguro de que no has introducido un bug, ni siquiera uno inducido en un módulo que no has tocado.
Sin embargo, hay algunos tipos de componente sobre los que es más complicado hacer pruebas con JUnit, sin ir más lejos los EJB (sean del tipo que sean). En general todo lo que se ejecuta sobre un contenedor es complicado de probar puesto que no es sencillo emular en nuestros juegos de pruebas las situaciones reales a las que se enfrenta el código en el contenedor.
Actualmente estoy desarrollando una aplicacion J2EE, preparando el camino para que todo pueda funcionar con WebServices, que sea muy rápida, estable y segura (como todos ;-) ).
Como servidor de aplicaciones estoy utilizando JBoss, aunque cuando el tiempo me deje y esté más maduro probaré Geronimo.
En el dilema que me planteé incialmente sobre que utilizar de J2EE estaban los Entity Beans CMP e Hibernate. Al final ha ganado Hibernate por ser más fácil de probar con JUnit, más fácil de generar y distribuir, y mucho más cercano al verdadero desarrollo orientado a objetos. Podría utilizar Entity Beans BMP que a su vez utilizaran Hibernate, pero me parece rizar el rizo e introducir complejidad innecesaria.
Sin embargo, si he decidido utilizar Stateless Session Beans, pues permiten distribuir la carga entre varios servidores de aplicaciones facilmente, pero sobre todo porque me permiten dejar el trabajo transaccional al contenedor y estar seguro de que se hace bien.
En este punto es donde de nuevo entra JUnit. Probar EJB, incluso Session Beans, es complicado. Así que al final, usar JUnit ha inducido una decisión de diseño importante, que puede implicar un pequeño coste adicional en tiempo de ejecución, pero cuyas ventajas creo que son superiores. Lo que estoy haciendo es que los Session Beans sean meros proxies de POJOs (que llamaré Business Objects) que son los que realmente tienen la lógica de negocio. Los BOs utilizan sessiones de Hibernate para realizar su trabajo, pero no realizan ningún tipo de asunción con respecto a las transacciones. De esta forma es sencillo realizar pruebas sobre los BOs fuera del contenedor, dejando que sean las clases de prueba las que manejen las transacciones de forma simple, y estar razonablemente seguros de que todo funcionará correctamente sobre el contenedor.
¿Te parece una buena solución? ¿Crees que hay una mejor?

En el próximo post detallaré el proceso de trabajo con Hibernate sobre JBoss, ya que a pesar del artículo al respecto que hay en la web de Hibernate, la realidad es algo diferente y además creo que sería muy conveniente detallar la integración del proceso con Ant, cosa que está explicada en varios sitios pero parcialmente en todos ellos.