Hace unas semanas un amigo me recomend贸 esta pagina de un nuevo framework Qi4j que se centra en el desarrollo del modelo de dominio y usa conceptos de AOP, DI (Dependency Injection) y DDD (Domain Driven Design).
El framework es una implementaci贸n de un nuevo paradigma de programaci贸n que es la Programaci贸n Orientada a Compuestos (Composites) (COP - por sus siglas en Ingles) usando Java 5 puro.
Los principios de la COP son:
- El comportamiento de un objeto depende del contexto.
- El desacoplamiento es una virtud.
- Las reglas de negocio importan mas.
- Las Clases han muerto, larga vida a las Interfaces.
Ellos argumentan que la Programaci贸n Orientada a Objetos (OOP) tiene ciertos problemas para realmente modelar el ciclo de vida de los objetos. Por ejemplo, un objeto no siempre tiene los mismos atributos y estos pueden variar (tener menos o mas atributos) en el tiempo, incluso el comportamiento de un objeto no es el mismo siempre ya que puede variar seg煤n el contexto donde se encuentre ejecutando.
Este tipo de cosas ha sido muy dif铆cil implementarlas usando OOP y aunque se pueden implementar deber铆a ser mas "natural".
A todos nos ha pasado que empezamos un sistema haciendo el an谩lisis de los conceptos y reglas de negocio y buscamos hacer un dise帽o que represente y cumpla con todos esos requisitos lo mejor posible. Pero cuando llega la hora de codificar terminamos enfocando mas nuestros esfuerzos en la infraestructura y terminamos teniendo un modelo de dominio an茅mico (Martin Fowler explica esto aqu铆).
La Programaci贸n Orientada a Compuestos esta muy influenciada por el libro de Erick Evans (Domain Driven Design) donde propone conceptos y patrones de dise帽o para dise帽ar sistemas mas enfocados al modelo de dominio.
En la COP existen dos niveles de composici贸n:
- Un nivel de composici贸n para ensamblar objetos compuestos a partir de piezas mas peque帽as llamadas Fragmentos.
- Y un segundo nivel de composici贸n para ensamblar M贸dulos a partir de compuestos (objetos del primer nivel de composici贸n), Capas a partir de M贸dulos y terminar con una Aplicaci贸n compuesta de Capas.
Los Fragmentos a partir de los cuales se puede formar un objeto compuesto son:
- Mixins. Representan el estado de un objeto compuesto.
- Restricciones (Constraints). Reglas de validaci贸n tanto de entrada como de salida para los argumentos.
- Intereses (Concerns). Interceptan llamadas de m茅todos. Su uso se aplica generalmente a comportamientos que aplican a todo el sistema (cross-cutting behaviours).
- Efectos Secundarios (Side Effects). Se ejecutan despu茅s de la ejecuci贸n de un m茅todo pero no influyen en los datos de salida que entregan los m茅todos.
En fin, el framework Qi4j se ve muy interesante y vale la pena echarle un ojo para ver la forma en que trabaja.
Links de inter茅s:
- Resumen del libro de Erick Evans DDD. http://www.infoq.com/minibooks/domain-driven-design-quickly
Welcome to my corner of the internet! I'm a Software Developer trying to improve my craft every day
Sunday, January 31, 2010
Sunday, January 10, 2010
Primeros Pasos con Spring Roo en Spring Source Tool Suite
Este ejemplo de primeros pasos esta hecho con el SpringSource Tool Suite, sin embargo, es posible hacerlo tambi茅n desde la consola de Roo.
Vamos a crear una peque帽a aplicacion de libreta de direcciones para este ejemplo.
Lo primero es crear el proyecto del tipo "Roo Project" con el nombre "PrimerosPasos" (el nombre puede ser de su eleccion solo recuerden que con ese nombre tendr谩 el contexto web).

Esto crea un proyecto con la estructura:

Para aquellos que usan maven se dar谩n inmediatamente cuenta que es una estructura de un proyecto maven.
Para crear/configurar las cosas en Spring Roo se corren comandos desde la consola Roo, la cual desde el SpringSource Tool Suite se puede ejecutar con click derecho sobre el proyecto luego la opcion Spring Tools -> Open Roo Shell.
Ya en la vista de la consola Roo existe un campo de texto donde tecleamos los comandos que pueden ir creando el c贸digo de la aplicaci贸n. Si teclean "hint" el mismo Roo les dar谩 pistas sobre que comandos teclear seg煤n lo ya creado dentro del proyecto.
Lo primero que hay que configurar el proveedor y la base de datos de la aplicaci贸n, y de hecho este es el primer punto que pide Roo crear si teclean "hint".
Esto imprime como salida en la consola de roo:
Dentro de los archivos que fueron creados esta el "database.properties" en el cual hay que configurar los par谩metros para conectarnos a nuestra base de datos en mysql.
Ya configurados los parametros para conectarnos a la base de datos es necesario empezar a crear las entidades de nuestra aplicacion. Dado que nuestra aplicacion sera una libreta de direcciones empezaremos con la entidad "Persona".
Una vez mas podemos teclear "hint" en la consola de roo para que nos ayude.
Para crear una entidad hay que teclear el comando "entity" el cual recibe un argumento obligatorio y es el nombre de la clase de la entidad que vamos a crear.
Sin embargo el comando "entity" puede recibir mas argumentos los cuales nos puede mostrar la consola de roo si tecleamos "--" y luego CRTL+SPACE.
Una vez ejecutado el comando "entity" esta es la salida en la consola de roo:
Notaran que la 煤nica clase java creada fue "Persona.java" y que si abren el c贸digo solo ver谩n lo siguiente:
Los otros archivos "*.aj" son Aspectos agregados a la clase Persona.
En este punto si volvemos a teclear "hint" en la consola de roo nos dar谩 consejos para crearle atributos a nuestra clase.
Agregaremos el atributo nombre a nuestra clase Persona ejecutando el siguientes comando en la consola:
Ok, en este punto del ejemplo me gustar铆a recalcar algo y para lograrlo primero hay que crear una clase de prueba de la clase Persona con el siguiente c贸digo:
Lo siguiente es crear un archivo "log4j.propeties" en src/test/resources y configurarlo para que imprima el nivel debug de la siguiente forma: (si quieren pueden copiar el log4j.properties que se genero en src/main/resources/META-INF/spring/log4j.properties, pero hay que cambiarle el nivel a debug).
Una vez creada la prueba unitaria y el archivo log4j.properties, hay que ejecutar las pruebas del proyecto dando click derecho sobre el archivo pom.xml y ejecutar la opcion "Run As -> Maven Test". Con esto ejecutaremos las pruebas unitarias del proyecto y la salida de ejecutar esta acci贸n es la siguiente (o pueden ejectuar las pruebas corriendo el comando "mvn test" en una consola normal):
Ok, todo fue bien el nombre Jimmy se imprimi贸 bien. Ahora miremos de nuevo el c贸digo de la clase Persona.java:
Alguien puede explicarme porque al crear la prueba unitaria la clase Persona conten铆a los m茅todos setNombre y getNombre si el c贸digo java no lo tiene?!??!?!?!. La respuesta son dos palabras: Aspectos y Addons.
Recuerdan que al crear la entidad Persona Spring Roo creo unos archivos .aj? estos son los Aspectos. V铆a aspectos y anotaciones Spring Roo agrega funcionalidad a las clases. Estos aspectos agregados por anotaciones a las clases son los llamados "Addons".
Los "Addons" son una caracter铆stica que propone Spring Roo y es muy interesante ya que as铆 podemos agregar funcionalidad a las clases de acuerdo a las necesidades y circunstancias. En algun post siguiente en el blog veremos mas a detalle acerca de los aspectos y addons de Spring Roo incluso para crear uno propio, por ahora continuemos con el ejemplo.
Ok, nuestra clase Persona ya tienen un atributo y es el nombre. Ahora vamos a agregarle otros atributos como: apellido y numero telefonico con los comandos siguientes:
Ahora crearemos la parte web de la aplicaci贸n creando los controllers. Para que roo nos ayude hay que teclean "hint controllers" en la consola de roo.
Para crear un controller que contenga las operaciones clasicas de altas, bajas y modificaciones (CRUD) ejecutamos el comando:
La salida de la ejecucion de este comando es la siguiente:
Como ver谩n, Spring Roo ha creado todos los archivos necesarios para tener una aplicaci贸n b谩sica de altas, bajas y modificaciones sobre nuestra entidad Persona.
Para correr la aplicaci贸n bien podemos dar click derecho sobre el proyecto de Spring Source Tool Suite y darle "Run As -> Run on Server" o en una consola normal "mvn jetty:run".
Una vez que ha levantado el servidor vayan a la direccion http://localhost:8080/PrimerosPasos y listo!
Notaran que en la base de datos ya existe una tabla llamada "persona" con los atributos iguales a los que tiene nuestra entidad Persona.
NOTA: Yo tuve problemas ejecutando este ejemplo con Java 1.5 en una Mac pero todo corri贸 bien con Java 1.6.


Vamos a crear una peque帽a aplicacion de libreta de direcciones para este ejemplo.
Lo primero es crear el proyecto del tipo "Roo Project" con el nombre "PrimerosPasos" (el nombre puede ser de su eleccion solo recuerden que con ese nombre tendr谩 el contexto web).

Esto crea un proyecto con la estructura:

Para aquellos que usan maven se dar谩n inmediatamente cuenta que es una estructura de un proyecto maven.
Para crear/configurar las cosas en Spring Roo se corren comandos desde la consola Roo, la cual desde el SpringSource Tool Suite se puede ejecutar con click derecho sobre el proyecto luego la opcion Spring Tools -> Open Roo Shell.
Ya en la vista de la consola Roo existe un campo de texto donde tecleamos los comandos que pueden ir creando el c贸digo de la aplicaci贸n. Si teclean "hint" el mismo Roo les dar谩 pistas sobre que comandos teclear seg煤n lo ya creado dentro del proyecto.
Lo primero que hay que configurar el proveedor y la base de datos de la aplicaci贸n, y de hecho este es el primer punto que pide Roo crear si teclean "hint".
persistence setup --database MYSQL --provider HIBERNATE
Esto imprime como salida en la consola de roo:
roo> persistence setup --database MYSQL --provider HIBERNATE
Created SRC_MAIN_RESOURCES/META-INF/persistence.xml
Created SRC_MAIN_RESOURCES/META-INF/spring/database.properties
please enter your database details in src/main/resources/database.properties
Managed SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Dentro de los archivos que fueron creados esta el "database.properties" en el cual hay que configurar los par谩metros para conectarnos a nuestra base de datos en mysql.
Ya configurados los parametros para conectarnos a la base de datos es necesario empezar a crear las entidades de nuestra aplicacion. Dado que nuestra aplicacion sera una libreta de direcciones empezaremos con la entidad "Persona".
Una vez mas podemos teclear "hint" en la consola de roo para que nos ayude.
Para crear una entidad hay que teclear el comando "entity" el cual recibe un argumento obligatorio y es el nombre de la clase de la entidad que vamos a crear.
entity --class com.jabaddon.roo.libretadirecciones.dominio.Persona
Sin embargo el comando "entity" puede recibir mas argumentos los cuales nos puede mostrar la consola de roo si tecleamos "--" y luego CRTL+SPACE.
Una vez ejecutado el comando "entity" esta es la salida en la consola de roo:
roo> entity --class com.jabaddon.roo.libretadirecciones.dominio.Persona
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/dominio
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/dominio/Persona.java
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/dominio/Persona_Roo_Entity.aj
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/dominio/Persona_Roo_ToString.aj
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/dominio/Persona_Roo_Configurable.aj
Notaran que la 煤nica clase java creada fue "Persona.java" y que si abren el c贸digo solo ver谩n lo siguiente:
@Entity
@RooJavaBean
@RooToString
@RooEntity
public class Persona {
}
Los otros archivos "*.aj" son Aspectos agregados a la clase Persona.
En este punto si volvemos a teclear "hint" en la consola de roo nos dar谩 consejos para crearle atributos a nuestra clase.
Agregaremos el atributo nombre a nuestra clase Persona ejecutando el siguientes comando en la consola:
field string --fieldName nombre
roo> field string --fieldName nombre
Managed SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/dominio/Persona.java
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/dominio/Persona_Roo_JavaBean.aj
Managed SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/dominio/Persona_Roo_ToString.aj
Ok, en este punto del ejemplo me gustar铆a recalcar algo y para lograrlo primero hay que crear una clase de prueba de la clase Persona con el siguiente c贸digo:
package com.jabaddon.roo.libretadirecciones.dominio;
import org.apache.log4j.Logger;
import org.junit.Test;
public class PersonaTest {
private static final Logger LOGGER = Logger.getLogger(PersonaTest.class);
@Test
public void imprimirNombrePersona() {
Persona persona = new Persona();
persona.setNombre("Jimmy");
LOGGER.debug("El nombre es = " + persona.getNombre());
}
}
Lo siguiente es crear un archivo "log4j.propeties" en src/test/resources y configurarlo para que imprima el nivel debug de la siguiente forma: (si quieren pueden copiar el log4j.properties que se genero en src/main/resources/META-INF/spring/log4j.properties, pero hay que cambiarle el nivel a debug).
log4j.rootLogger=debug, consola
log4j.appender.consola=org.apache.log4j.ConsoleAppender
log4j.appender.consola.layout=org.apache.log4j.PatternLayout
log4j.appender.consola.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
Una vez creada la prueba unitaria y el archivo log4j.properties, hay que ejecutar las pruebas del proyecto dando click derecho sobre el archivo pom.xml y ejecutar la opcion "Run As -> Maven Test". Con esto ejecutaremos las pruebas unitarias del proyecto y la salida de ejecutar esta acci贸n es la siguiente (o pueden ejectuar las pruebas corriendo el comando "mvn test" en una consola normal):
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.jabaddon.roo.libretadirecciones.dominio.PersonaTest
2010-01-10 21:52:35,441 [main] DEBUG org.springframework.beans.factory.wiring.BeanConfigurerSupport - BeanFactory has not been set on BeanConfigurerSupport: Make sure this configurer runs in a Spring container. Unable to configure bean of type [com.jabaddon.roo.libretadirecciones.dominio.Persona]. Proceeding without injection.
2010-01-10 21:52:35,444 [main] DEBUG com.jabaddon.roo.libretadirecciones.dominio.PersonaTest - El nombre es = Jimmy
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.931 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
...
Ok, todo fue bien el nombre Jimmy se imprimi贸 bien. Ahora miremos de nuevo el c贸digo de la clase Persona.java:
package com.jabaddon.roo.libretadirecciones.dominio;
import javax.persistence.Entity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import org.springframework.roo.addon.entity.RooEntity;
@Entity
@RooJavaBean
@RooToString
@RooEntity
public class Persona {
private String nombre;
}
Alguien puede explicarme porque al crear la prueba unitaria la clase Persona conten铆a los m茅todos setNombre y getNombre si el c贸digo java no lo tiene?!??!?!?!. La respuesta son dos palabras: Aspectos y Addons.
Recuerdan que al crear la entidad Persona Spring Roo creo unos archivos .aj? estos son los Aspectos. V铆a aspectos y anotaciones Spring Roo agrega funcionalidad a las clases. Estos aspectos agregados por anotaciones a las clases son los llamados "Addons".
Los "Addons" son una caracter铆stica que propone Spring Roo y es muy interesante ya que as铆 podemos agregar funcionalidad a las clases de acuerdo a las necesidades y circunstancias. En algun post siguiente en el blog veremos mas a detalle acerca de los aspectos y addons de Spring Roo incluso para crear uno propio, por ahora continuemos con el ejemplo.
Ok, nuestra clase Persona ya tienen un atributo y es el nombre. Ahora vamos a agregarle otros atributos como: apellido y numero telefonico con los comandos siguientes:
field string --fieldName apellido
field string --fieldName numeroTelefonico
Ahora crearemos la parte web de la aplicaci贸n creando los controllers. Para que roo nos ayude hay que teclean "hint controllers" en la consola de roo.
Para crear un controller que contenga las operaciones clasicas de altas, bajas y modificaciones (CRUD) ejecutamos el comando:
controller scaffold --class com.jabaddon.roo.libretadirecciones.web.PersonaController --entity com.jabaddon.roo.libretadirecciones.dominio.Persona
La salida de la ejecucion de este comando es la siguiente:
roo> controller scaffold --class com.jabaddon.roo.libretadirecciones.web.PersonaController --entity com.jabaddon.roo.libretadirecciones.dominio.Persona
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/web
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/web/PersonaController.java
Created SRC_MAIN_WEBAPP/WEB-INF/spring
Created SRC_MAIN_WEBAPP/WEB-INF/spring/webmvc-config.xml
Created SRC_MAIN_JAVA/com/jabaddon/roo/libretadirecciones/web/PersonaController_Roo_Controller.aj
Created SRC_MAIN_WEBAPP/images
Created SRC_MAIN_WEBAPP/images/nl.png
Created SRC_MAIN_WEBAPP/images/update.png
Created SRC_MAIN_WEBAPP/images/es.png
Created SRC_MAIN_WEBAPP/images/delete.png
Created SRC_MAIN_WEBAPP/images/add.png
Created SRC_MAIN_WEBAPP/images/resultset_previous.png
Created SRC_MAIN_WEBAPP/images/resultset_next.png
Created SRC_MAIN_WEBAPP/images/favicon.ico
Created SRC_MAIN_WEBAPP/images/banner-graphic.png
Created SRC_MAIN_WEBAPP/images/resultset_last.png
Created SRC_MAIN_WEBAPP/images/gb.png
Created SRC_MAIN_WEBAPP/images/springsource-logo.png
Created SRC_MAIN_WEBAPP/images/it.png
Created SRC_MAIN_WEBAPP/images/show.png
Created SRC_MAIN_WEBAPP/images/sv.png
Created SRC_MAIN_WEBAPP/images/list.png
Created SRC_MAIN_WEBAPP/images/resultset_first.png
Created SRC_MAIN_WEBAPP/images/de.png
Created SRC_MAIN_WEBAPP/styles
Created SRC_MAIN_WEBAPP/styles/standard.css
Created SRC_MAIN_WEBAPP/styles/alt.css
Created SRC_MAIN_WEBAPP/WEB-INF/classes
Created SRC_MAIN_WEBAPP/WEB-INF/classes/standard.properties
Created SRC_MAIN_WEBAPP/WEB-INF/classes/alt.properties
Created SRC_MAIN_WEBAPP/WEB-INF/layouts
Created SRC_MAIN_WEBAPP/WEB-INF/layouts/default.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/layouts/layouts.xml
Created SRC_MAIN_WEBAPP/WEB-INF/views
Created SRC_MAIN_WEBAPP/WEB-INF/views/views.xml
Created SRC_MAIN_WEBAPP/WEB-INF/views/resourceNotFound.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/index.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/uncaughtException.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/dataAccessFailure.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/controller-index.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/tags
Created SRC_MAIN_WEBAPP/WEB-INF/tags/language.tagx
Created SRC_MAIN_WEBAPP/WEB-INF/tags/theme.tagx
Created SRC_MAIN_WEBAPP/WEB-INF/tags/pagination.tagx
Created SRC_MAIN_WEBAPP/WEB-INF/i18n
Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_sv.properties
Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages.properties
Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_nl.properties
Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_it.properties
Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_es.properties
Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_de.properties
Created SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
Created SRC_MAIN_WEBAPP/WEB-INF/views/persona
Created SRC_MAIN_WEBAPP/WEB-INF/views/persona/list.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/persona/show.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/persona/create.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx
Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/persona/update.jspx
Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx
Created SRC_MAIN_WEBAPP/WEB-INF/views/persona/views.xml
Created SRC_MAIN_WEBAPP/WEB-INF/urlrewrite.xml
Created SRC_MAIN_WEBAPP/WEB-INF/web.xml
Managed SRC_MAIN_WEBAPP/WEB-INF/web.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Managed ROOT/pom.xml
Como ver谩n, Spring Roo ha creado todos los archivos necesarios para tener una aplicaci贸n b谩sica de altas, bajas y modificaciones sobre nuestra entidad Persona.
Para correr la aplicaci贸n bien podemos dar click derecho sobre el proyecto de Spring Source Tool Suite y darle "Run As -> Run on Server" o en una consola normal "mvn jetty:run".
Una vez que ha levantado el servidor vayan a la direccion http://localhost:8080/PrimerosPasos y listo!
Notaran que en la base de datos ya existe una tabla llamada "persona" con los atributos iguales a los que tiene nuestra entidad Persona.
NOTA: Yo tuve problemas ejecutando este ejemplo con Java 1.5 en una Mac pero todo corri贸 bien con Java 1.6.


Subscribe to:
Comments (Atom)