Esto es una traducción al español del artículo publicado en java.net en junio del 2008
por Javier Paniza
Esta es una historia sobre cómo crear una interfaz de usuario fácilmente, o mejor aun, sobre como tener una buena interfaz de usuario sin esfuerzo.
El problema
Hubo un tiempo en que conseguiste crear una aplicación de facturación de verdad buena. Tu fantástica aplicación tenía una ágil interfaz de caracteres MS-DOS (o Unix, o AS/400, o HOST), pero tus usuarios te pedían una interfaz gráfica de Windows: más bonita, más fácil de usar. Por tanto, reescribiste tu aplicación para que tuviese una interfaz de usuario Windows. Ahora ya era todo perfecto, pero entonces empezó a ser interesante que tu aplicación fuera multiplataforma, y sin dudarlo, la reescribiste usando Java con AWT, pero la interfaz de usuario quedó un poco pobre, y la reescribiste una vez más usando Swing. Otra vez era todo perfecto, o casi. Los usuarios empezaron a pedir una aplicación web, por tanto ahora usaste JSP para crear una interfaz web, y entonces tus usuarios te pedían integración en portales, y tuviste que adaptar tu aplicación para correr dentro de portales JSR-168, y puede que empezaras a usar JSF. Ahora, tus usuarios continúan pidiendo una mejor interfaz de usuario; quieren una interfaz web más rica. ¡Glup! Ahora tienes que reescribir tu aplicación con AJAX, o quizás JavaFX, una vez más.
¿Cuántas veces has de reescribir tu aplicación para mejorar la interfaz de usuario?
La solución
La solución ideal, a primera vista, es tener técnicas para declarar tu interfaz de usuario de una manera abstracta, y contar con varios motores de visualización para representar la interfaz de usuario usando diferentes tecnologías de presentación. Esto no es del todo una mala idea, de hecho muchos intentos interesantes se han hechos en esta dirección; XSL/XML, XForms, XUL, y otros más buscan una forma abstracta de definir interfaces de usuario. Pero a la hora de la verdad estas técnica no son tan abstractas como parece. ¿Puedes crear una aplicación Windows con XSL/XML? ¿Puedes definir una aplicación Flash con XForm? ¿Puedes crear una aplicación HTML/AJAX con JavaFX? Quizás. Pero muchas veces, cada nuevo motor de presentación tiene su propia definición “abstracta” de interfaz de usuario. A pesar de decir esto, mi esperanza es que en un futuro cercano tengamos una forma universal de definir interfaces de usuario, al menos para aplicaciones de gestión, quizás una evolución de XForm, o ...
Por otra parte, yo propongo una solución alternativa: No definir “interfaz de usuario” en absoluto.
Sí, es posible crear aplicaciones de gestión complejas sin definir la interfaz de usuario. ¿Cómo? Sencillo: la interfaz de usuario se puede derivar del modelo, es decir, de las clases de tu sistema que definen la estructura de los datos y el comportamiento asociado a esos datos. Llevo ya siete años usando esta técnica, y lo primero que notas es que el tiempo de desarrollo se acorta bastante, porque no tienes que dibujar la interfaz gráfica, aunque lo más llamativo fue lo suave que fue migrar aplicaciones de Swing a Web.
Puede que pienses que esta técnica solo puede ser usada para prototipado o impactantes demos de desarrollo rápido, y cuando intentes crear una aplicación de gestión del mundo real, fallará. Si piensas así estás equivocado. El truco está en darle al modelo algunas pistas para que organice los datos de forma clara de cara al usuario, o para que lance eventos en ciertas circunstancias. Sin embargo tú no estás definiendo la interfaz de usuario, simplemente haces algunas indicaciones para que el generador de interfaces gráficas pueda hacer un trabajo más efectivo.
Como muestra un botón.
Un ejemplo simple
Estos ejemplos están basados en el marco de trabajo OpenXava, un proyecto de código abierto que es un proyecto federado de la comunidad Java Enterprise en java.net.
Como primer ejemplo, puedes tener una clase para cliente, como esta:
@Entity
public class Cliente {
private int codigo;
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;
}
}
Y con solo este código, obtienes una aplicación como la de la Figura 1 con una interfaz de usuario completa, más el mantenimiento y el modo lista para navegar, ordenar y filtrar; generar listados en PDF y exportar a Excel. Obtienes todo esto sin código adicional, solo con la clase Cliente de arriba.

Figura 1. Módulo de mantenimiento OpenXava para clientes
Solo necesitas escribir el Cliente.java de arriba, añadirlo a una aplicación OpenXava existente, redesplegarla en tu servidor de aplicaciones Java, abrir tu navegador e ir a http://localhost:8080/Facturacion/xava/module.jsp?application=Facturacion&module=Cliente para ver el resultado funcionando.
Crear una aplicación OpenXava desde cero es coser y cantar. Descarga la última versión de OpenXava y descomprimela. Ve a la carpeta openxava-3.0.x/workspace/OpenXavaPlantilla, y ejecuta la siguiente tarea ant:
/java/openxava-3.0.3/workspace/OpenXavaPlantilla> ant -f CrearNuevoProyecto.xml
Buildfile: CrearNuevoProyecto.xml
[input] ¿Cuál es el nombre de tu proyecto?
Facturacion
[input] ¿Cuál es tu fuente de datos?
FacturacionDS
Como puedes ver, el build te pregunta por el nombre del proyecto y la fuente de datos. Simplemente teclea Facturacion y FacturacionDS. Ahora tienes un nuevo proyecto OpenXava llamado Facturacion en tu workspace. Ve a la carpeta src y crear el paquete com.miempresa.facturacion.modelo allí. Dentro de él pon el código de la clase Cliente de arriba. Puedes desplegar esta aplicación en un contenedor de servlets usando la tarea Ant desplegarWar o generarPortlets si prefieres usar un portal JSR-168, como Liferay, JetSpeed o WebSphere Portal. Por supuesto, has de definir una fuente de datos llamada FacturacionDS en tu servidor de aplicaciones. Si no hay tablas para tus clases en tu base de datos usa la tarea Ant actualizarEsquema para crearlas.
Para una guía pasa a paso de como crear un proyecto OpenXava nuevo, ver el Capítulo 2 de la guía de referencia de OpenXava.
Un ejemplo más complejo
Pero que ocurre en el caso de un ejemplo más complejo, como una factura, ¿sigue dando buen resultado generar la GUI automáticamente? Por supuesto. Vamos a dar al sistema algunas pistas, y dejar que siga siendo él quien siga generando la interfaz de usuario. Lo haremos añadiendo anotaciones a tu clase Factura. Creemosla con año, número, fecha, observaciones, suma de importes, porcentaje de IVA, IVA, referencia a su cliente, una colección de líneas, y una colección de albaranes. Para poder conseguir esto, necesitamos las siguientes clases: Factura, Cliente, LineaFactura y Albaran. Ya hemos visto el código de Cliente, y ahora vamos a ver el de Factura:
@Entity // 1
@View( // 2
members=
"año, numero, fecha;" +
"observaciones;" +
"cliente { cliente }" +
"lineas { lineas }" +
"importes { sumaImportes; porcentajeIVA; iva }" +
"albaranes { albaranes }"
)
public class Factura {
@Column(length=4) // 3
private int año;
@Column(length=6) // 3
private int numero;
private Date fecha;
@Column(length=80) // 3
private String observaciones;
@ManyToOne // 4
private Cliente cliente;
@OneToMany(mappedBy="factura") // 5
@ListProperties( // 6
"tipoServicio, producto.descripcion," +
"producto.precioUnitarioEnPesetas, cantidad," +
"precioUnitario, cantidad")
private Collection lineas;
@OneToMany(mappedBy="factura") // 5
private Collection albaranes;
// Getters y setters
...
// Propiedades calculadas
@Digits(integerDigits=12, fractionalDigits=2) // 7
public BigDecimal getSumaImportes() { ... }
@Digits(integerDigits=12, fractionalDigits=2) // 7
public BigDecimal getIva() { ... }
@Digits(integerDigits=12, fractionalDigits=2) // 7
public BigDecimal getTotal() { ... }
}
Esta clase no define la interfaz de usuario (como sería el caso con XUL o XForm); en lugar de ello, solo da alguna información sobre la forma preferida de disponer los datos. Esto lo hace mediante anotaciones JPA y OpenXava. Examinemos estas anotaciones:
@Entity (JPA): Marca esta clase como persistente, diciendo que hay una tabla en la base de datos que guarda la información de las facturas.
@View (OX): Con la anotación @View defines los miembros (propiedades, referencias o colecciones) de modelo a mostrar, y la distribución de los datos en la interfaz de usuario; usando {} indicas la forma en que prefieres que se clasifiquen los datos.
@Column (JPA): @Column se usa por el motor JPA para obtener información sobre la columna de la base de datos y así hacer el mapeo objeto-relacional, generando el DDL si fuese necesario. OpenXava, por su parte, usa length de @Column para calcular el tamaño del editor en la interfaz de usuario.
@ManyToOne (JPA): Esta es la forma estándar de definir una relación de muchos a uno para una entidad. Es decir, una simple referencia de una entidad a otra. OpenXava lo usa para crear una interfaz de usuario para visualizar, buscar, modificar y crear nuevos objetos de la entidad referenciada.
@OneToMany (JPA): Esta anotación es la forma estándar de definir una relación de uno a muchos para una entidad. Es decir, un colección de otras entidades. OpenXava lo usa para crear una interfaz de usuario para manejar la colección; esto incluye visualizar elementos, añadir nuevos; borrar, editar, ordenar y buscar en las colecciones; generar listados PDF de los elementos de la colección; exportar a Excel; y así por el estilo.
@ListProperties (OX): Puedes usar esta anotación para definir las propiedades a mostrar en la interfaz de usuario para colecciones.
@Digits: Esta anotación es del marco de trabajo Hibernate Validator. OpenXava reconoce las anotaciones de Hibernate Validator, y en este caso usa integerDigits y fractionalDigits para calcular el tamaño del editor en la interfaz de usuario.
Con estas pistas, OpenXava produce una interfaz de usuario como la que se muestra en la Figura 2. Solo necesitas escribir las clases, desplegar la aplicación, e ir a http://localhost:8080/Facturacion/xava/module.jsp?application=Facturacion&module=Factura. Nada más.

Figure 2. Módulo OpenXava para Factura
Puedes ver como esta interfaz todavía es generada desde el modelo, mientras que las anotaciones OpenXava son solo un grupo de sencillos consejos abstractos. Por ejemplo, las secciones (los miembros entre llaves) indican como se clasifica la información al visualizarse. En este caso, cada sección corresponde a una pestaña en la interfaz de usuario, pero otros generadores de UI podrían escoger usar un árbol, un acordeón, u otro tipo de control UI, para acceder a los datos de las secciones, incluso podrían optar por mostrar todos los datos en la misma ventana. Un generador UI potente podría incluso permitir al usuario escoger la forma exacta de mostrar las secciones (pestañas, árboles, acordeón u otro).
¿Qué ocurre cuando la estructura de datos cambia? En este caso solo necesitas añadir las propiedades, referencias o colecciones que necesites, y ejecutar la tarea Ant actualizarEsquema para actualizar la base de datos, desplegar tu aplicación (con desplegarWar), y refrescar tu navegador. Si usas el Tomcat dentro del Eclipse para JEE puedes omitir el paso de desplegar.
Conclusión
La generación automática de la interfaz de usuario desde el modelo no es una solución universal; a veces diseñar una interfaz de usuario manualmente puede ser mejor. Pero, en muchos casos, (como en el caso de las aplicaciones de gestión) un alto porcentaje de la interfaz de usuario de la aplicación puede ser creada automáticamente, con un resultado muy bueno.
La generación automática de la UI tiene las siguientes ventajas:
Evolución de la interfaz: Al no escribir la interfaz de usuario usando una tecnología específica, la migración de la aplicación a otro tecnología de presentación es fácil (por ejemplo, migrar una aplicación pura HTML a una AJAX).
Productividad: Liberas a tus desarrolladores de un trabajo que consume mucho tiempo. Al final, los marco de trabajo MVC se quedan en MC.
Y lo más importante; esto no es una aproximación teórica, sino práctica. En mi empresa estamos usando estas técnicas por más de siete años con gran satisfacción. Primero, los programadores con menos experiencia son productivos con Java desde el principio, sin tener que aprender todos los trucos de la Swing, y estos mismos programadores puede desarrollar aplicaciones para portales Web sin tener que aprender JSP, JSF, JSR-168, etc.
¿Piensas que usar Swing o JSP o JSF o AJAX es necesario para la felicidad de tus programadores? Yo creo que no. Cuando los programadores se acostumbran a usar la generación automática de la UI, empiezan a odiar el desarrollo a mano (incluso usando un diseñador gráfico para GUIs) de las interfaces de usuario.
Referencias
Los siguientes marcos de trabajo y tecnologías tienen el espíritu de este artículo:
OpenXava: Este marco de trabajo genera automáticamente aplicaciones de gestión desde simples clases Java con anotaciones, incluyendo interfaces de usuario complejas. Los ejemplos de este artículo usan la sintaxis de OpenXava. Si tienes interés en la sintaxis completa para la generación de UI puedes ver la documentación de OpenXava.
Trails genera aplicaciones Web desde POJOs anotados.
JMatter construye aplicaciones Swing de gestión para trabajo en grupo basándose en clases de modelo.
NakedObjects genera una UI desde objetos Java; las clases tienen que seguir ciertas normas.
RomaFramework genera aplicaciones desde POJOs usando archivos XML files para personalizar la vista.
MDA: La esencia de MDA es generar una aplicación completa (por tanto una UI también) desde un modelo UML. EL principal elemento del diseño de software es el modelo, y la interfaz de usuario es generada. (Quizás la excesiva orientación a la generación de código de MDA produce herramientas que no son demasiado ágiles desde la perspectiva de un desarrollador)