Un poco más sobre openxava

Ya hemos hablado anteriormente de Openxava, ahora vamos a intentar dar un acercamiento a como funciona Openxava y de que va eso del desarrollo dirigido por modelos(MDD), Model Driven Architecture,…

Partamos de los siguientes conceptos:

  • MDA es el acrónimo de Model Driven Architecture (Arquitectura Dirigida por Modelos), un concepto promovido (pero no creado) por la OMG, que propone basar el desarrollo de software en modelos especificados utilizando UML, para que, a partir de esos modelos, se realicen trasformaciones que generen código u otro modelo, con características de una tecnología particular (o con menor nivel de abstracción). MDA define un framework para procesar y relacionar modelos. 
  • Un modelos es una descripción de todo o parte de un sistema escrito en un lenguaje bien definido. El hecho que un modelo este escrito en un lenguaje bien definido tiene una gran importancia para MDA, ya que supone que el modelo tienen asociadas una sintaxis y semántica bien definidas. Esto permite la interpretación automática de transformadores o compiladores de modelos, fundamentales en MDA.
  • Un Componente de Negocio consiste en todos los artefactos de software relacionados con un concepto de negocio. Componente de Negocio es tan solo una forma de organizar el software.

Según Javier Paniza en su libro “Aprende Openxava con ejemplos” básicamente, MDD establece que únicamente se ha de desarrollar la parte del modelo de una aplicación, y el resto se generará a partir de este modelo.

Desafortunadamente, el uso de MDD es muy complejo. Requiere de una gran cantidad de tiempo, pericia y herramientas. Aun así la idea tras MDD sigue siendo muy buena, por lo tanto OpenXava toma esa idea de una manera simplificada. Usa simples clases de Java con anotaciones para definir el modelo, y no usa generación de código, en vez de eso toda la funcionalidad de la aplicación es generada  dinámicamente en tiempo de ejecución.

Ya sabemos de que va esto, pero vamos a entrar en el dominio de OpenXava:

  • Componentes de negocio: Clases de Java que describen los conceptos de negocio en todos sus aspectos. Estas son las únicas piezas requeridas en una aplicación OpenXava.
  • Módulos: Un módulo es lo que el usuario final ve. Es la unión de un componente de negocio y varios controladores. Puedes omitir la definición de los módulos, en ese caso se asume un módulo por cada componente de negocio.
  • Controladores: Un controlador es una colección de acciones. Para el usuario, las acciones son botones o vínculos que el puede pulsar; para el desarrollador clases con lógica a hacer cuando el usuario pulsa en esos botones. Los controladores definen el comportamiento de la aplicación, y normalmente son reutilizables. OpenXava incluye a conjunto de controladores predefinidos, y, por supuesto, puedes definir los tuyos propios.

  • Editores: Componentes de la interfaz de usuario para definir la forma en que los miembros de un componente de negocio son visualizados y editados. Es una manera de personalizar la generación de la interfaz de usuario.
  • Validadores: Lógica de validación reutilizable que puedes usar en cualquier componente de negocio.

  • Calculadores: Lógica de negocio reutilizable que puedes usar en algunos puntos de los componentes de negocio.

Finalmente esto es lo que ve el usuario:

Ya tenemos el entorno configurado, ya sabemos crear entidades, ya hemos superado el actualizar el esquema con Ant. Entonces ya podemos empezar a modelar.

Este es el modelo que vamos a crear:

Aquí tenemos Categoría. Solo tenemos que crear una clase java y listo (no nos debemos preocupar, dará un error por la clase “Identifiable”, más adelante lo explicaremos):

package org.openxava.invoicing.model;
import javax.persistence.*;
@Entity
public class Category extends Identifiable{
 @Column(length=50)
 private String description;
...
//Metodos Getter y Setter
}}

ADVERTENCIA
Si Eclipse nos pregunta por la notacion @Entity, debemos elegir javax.persistence.Entity y no org.hibernate.annotations.Entity Visto aquí

Ahora vamos con Producto. Pero antes la entidad Product necesita tener al menos <<precio>> y quizás algún campo más. Para ello vamos a usar estereotipos.

Los estereotipos añaden propiedades a la entidad Product, estas propiedades pueden ser el precio o incluso una foto. Sólo tenemos que utilizar la anotación @Stereotype. Así que allá vamos. Esta es la clase Product:

package org.openxava.invoicing.model;
import java.math.*;
import javax.persistence.*;
import org.openxava.annotations.*;
@Entity
public class Product {

 @Id @Column(length=9)
 private int number;
 @Column(length=50) @Required
 private String description;
 @ManyToOne( // The reference is persisted as a database relationship
 fetch=FetchType.LAZY, // The reference is loaded on demand
 optional=false) // The reference must have value always
 @DescriptionsList // Thus the reference is displayed using a combo
 private Category category; // A regular Java reference

 @Stereotype("MONEY") // The price property is used to store money
 private BigDecimal price; // BigDecimal is typically used for money
 @Stereotype("PHOTO") // The user can view and change a photo
 private byte [] photo;
 @Stereotype("IMAGES_GALLERY") // A complete image gallery is available
 @Column(length=32) // The 32 length string is for storing the key of the gallery
 private String morePhotos;
 @Stereotype("MEMO") // This is for a big text, a text area or equivalent will be used
 private String remarks;
// Métodos getter y setter

Hemos creado 3 esteretipos, uno de ellos para el precio, otro para añadir una imagen y otro para ver una galería de imágenes.

Ahora vamos a por los elementos del Customer, en primer lugar vamos a modelar la dirección (Address):

package org.openxava.invoicing.model;
import javax.persistence.*;
@Embeddable // We use @Embeddable instead of @Entity
public class Address {
 @Required
 @Column(length = 30) // The members are annotated as in entity case
 private String street;
 @Required
 @Column(length = 5)
 private int zipCode;
 @Required
 @Column(length = 20)
 private String city;
 @Required
 @Column(length = 30)
 private String state;
...
//Métodos Getter y Setter

Ahora solamente nos queda modificar la clase Customer que creamos en un post anterior. Aquí os dejo el Customer completo que tenemos hasta ahora.

package org.openxava.invoicing.model;

import javax.persistence.*;
import org.openxava.annotations.*;

@Entity
// This mark Customer class as an entity
public class Customer {
 @Id
 // The number property is the key property. Keys are required by default
 @Column(length = 6)
 // The column length is use at UI level and DB level
 private int number;
 @Column(length = 50)
 // The column length is use at UI level and DB level
 @Required
 // A validation error will be show if name property is left empty
 private String name;
 @Embedded
 private Address address;

Por último la clase que falta por modelar es Invoice:

package org.openxava.invoicing.model;
import java.util.*;
import javax.persistence.*;
import org.openxava.annotations.*;
import org.openxava.calculators.*;
import org.openxava.invoicing.calculators.*;

@Entity
public class Invoice extends Identifiable {
@Column (length=4)
 @DefaultValueCalculator(CurrentYearCalculator.class)
 private int year;

 @Column(length = 6)
 @DefaultValueCalculator(value=NextNumberForYearCalculator.class, properties=@PropertyValue(name = "year"))
 private int number;

 @Required
 @DefaultValueCalculator(CurrentDateCalculator.class)
 private Date date;

 @Stereotype("MEMO")
 private String remarks;

 @ManyToOne(fetch=FetchType.LAZY, optional=false)
 private Customer customer;

 @OneToMany(
 mappedBy="parent",
 cascade=CascadeType.ALL)
 @ListProperties("product.number, product.description, quantity")
 private Collection<Detail> details = new ArrayList<Detail>();

Si habéis sido observadores, os daréis cuenta que solo nos falta la clase Details.

package org.openxava.invoicing.model;
import javax.persistence.*;
@Entity
public class Detail extends Identifiable{
@ManyToOne
 private Invoice parent; 

 private int quantity; 

 @ManyToOne(fetch=FetchType.LAZY, optional=false)
 private Product product;

Y ahora  a explicar Identifiable.

Como sabemos, es necesario tener las facturas (Invoice) identificadas de manera única, así como las Categorías de los productos (Category) y también las lineas de una factura. Por ello debemos de ser capaces de generar claves únicas para nuestras tablas, de eso se encarga nuestra clase identifiable.

package org.openxava.invoicing.model;
import javax.persistence.*;
import org.hibernate.annotations.*;
import org.openxava.annotations.*;
@MappedSuperclass 
public class Identifiable {

 @Id @GeneratedValue(generator="system-uuid") @Hidden 
 @GenericGenerator(name="system-uuid", strategy = "uuid")
 @Column(length=32)
 private String oid;
public String getOid() {
 return oid;
 }
public void setOid(String oid) {
 this.oid = oid;
 }
}

Ahora solo nos queda probarlo, de momento está cada parte por separado, así que habrá que probarla una a una.

http://localhost:8080/Invoicing/modules/Category

http://localhost:8080/Invoicing/modules/Product

http://localhost:8080/Invoicing/modules/Invoice

http://localhost:8080/Invoicing/modules/Customer

Se que nos han faltado un montón de cosillas sin explicar, pero esto es solo una aproximación. La mayor parte de este post se encuentra en el Libro “Aprende Openxava con Ejemplos”.

También me he ayudado del código publicado aquí.

Anuncios

Comenta la entrada

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s