Welcome to my corner of the internet! I'm a Software Developer trying to improve my craft every day
Sunday, January 31, 2010
Qi4j y Programaci贸n Orientada a Compuestos
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
Sunday, January 10, 2010
Primeros Pasos con Spring Roo en Spring Source Tool Suite
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.


Saturday, November 14, 2009
Spring 3: Spring Expression Language (SpEL)
En la versi贸n 3 de Spring podemos encontrar una nueva caracter铆stica y es el SpEL (Spring Expression Language). Es una nueva forma para inyectar valores a las propiedades de los beans.
Por ejemplo, todo hijo hereda el apellido del padre:
Al ejecutar el siguiente codigo java:
ApplicationContext appContext =
new ClassPathXmlApplicationContext("classpath:spring3-config.xml");
Persona padre = (Persona) appContext.getBean("padre");
Persona hijo = (Persona) appContext.getBean("hijo");
System.out.println("Apellido del padre = " + padre.getApellido());
System.out.println("Apellido del hijo = " + hijo.getApellido());
El resultado es el siguiente:
Apellido del padre = Lara
Apellido del hijo = Lara
Spring eval煤a la expresi贸n "#{padre.apellido}" y la traduce a una llamada el m茅todo "getApellido" del bean "padre". El resultado es inyectado a la propiedad "apellido" del bean "hijo". Esta nueva caracter铆stica del Spring 3 es muy interesante ya que no solo permite acceder a propiedades de otros beans, tambi茅n llamar metodos de otros beans, obtener valores de propiedades del sistema y hasta llamar m茅todos est谩ticos.
Veamos algunos ejemplos:
- Acceder a propiedades del sistema: #{ systemProperties['valor.systema]}.
- Llamar m茅todos est谩ticos: #{ T(java.lang.Math).random() }.
- Acceder a elementos de un arreglo: #{ arreglo[1] }.
- Acceder a elementos de un mapa: #{ mapa['key'] }.
- Llamar a m茅todos (con todo y argumentos): #{ 'cadena'.substring(2, 3) }.
- Operaciones aritm茅ticas: #{ (2 + 2) * 5 }
- Crear objetos: #{ new String('Hola') }.
En fin, hay muchas otras cosas mas que se pueden hacer con esta nueva caracter铆stica que viene con Spring 3
Pueden leer mas en la documentaci贸n de referencia aqu铆.
Saturday, October 24, 2009
Instalacion de Jackbe Presto en Windows Vista
cscript //NoLogo setup_win.js
cscript //NoLogo setup_win.js //E:javascript
Monday, September 14, 2009
Muse - The Resistance
- Uprising. Gran rola y el primer single oficial del disco.
- Resistance.
- Undisclosed Desires. Muy buenos arreglos y coros.
- United States of Eurasia. Buenos coros, me recuerdan a Queen, y termina con un gran toque de musica clasica (Nocturna Op. 9 No. 2 de Chopin).
- Guiding Light. Un poco melosa y con falta de cambio de ritmos.
- Unnatural Selection. Otra buena rola, buena guitarra r铆tmica muy de Muse.
- MK Ultra.
- I Belong to You. Muy buen ritmo y termina excelentemente con un fragmento de la opera "Samson et Dalila" de Camille Saint-Sa锚ns.
- Exogenesis: Symphony, Pt. 1 (Overture).
- Exogenesis: Symphony, Pt. 2 (Cross-pollination).
- Exogenesis: Symphony, Pt. 3 (Redemption). Gran piano.
Tuesday, July 14, 2009
Ruby on Rails
Last.fm
Monday, May 11, 2009
Bamboo Fun

En la medida de lo posible ire poniendo mas dibujos que haga con la Bamboo Fun de Wacom.
Monday, March 30, 2009
Tutorial Spring Batch - File Converter, Parte 2
La primera parte de este tutorial se enfoco mas a la teor铆a y los conceptos b谩sicos que maneja Spring Batch. Esta segunda parte sera mas practica y nos enfocaremos a crear el miniproyecto tutorial que demuestre un poco las funciones de este framework. Solo espero no extenderme tanto y no hacer una segunda parte de esta segunda parte :P.
Para este ejercicio vamos a suponer que tenemos que hacer un sistema que toma archivos de texto con informaci贸n de contactos donde los datos vienen separados por comas y que se tiene que transformar a otro archivo de texto donde la informaci贸n vendr谩 en registros de tama帽o fijo. Cada linea del archivo separado por comas representa la informaci贸n de un contacto en el siguiente estructura:
- Nombre
- Apellido
- e-mail personal
- e-mail del trabajo
- telefono
- pagina web
$> mvn archetype:create -DgroupId=<aqui-va-el-groupId> -DartifactId=<aqui-va-el-artifactId>Una vez ejecutado el comando tendremos una plantilla de proyecto simple en maven 2. Para poder hacer uso de Spring Batch tendremos que indicarle a nuestro proyecto en maven donde encontrar las librer铆as necesarias de Spring Batch para empezar a codificar. Como usaremos la versi贸n 2.0.0.RC2 hay que agregar a nuestro pom.xml el repositorio de spring-batch:
12: <repositories>
13: <repository>
14: <id>spring-s3</id>
15: <name>Spring Maven MILESTONE Repository</name>
16: <url>http://s3.amazonaws.com/maven.springframework.org/milestone</url>
17: </repository>
18: </repositories>20: <dependencies>
21: <!-- Para las pruebas unitarias -->
22: <dependency>
23: <groupId>junit</groupId>
24: <artifactId>junit</artifactId>
25: <version>3.8.1</version>
26: <scope>test</scope>
27: </dependency>
28:
29: <!-- Para las pruebas unitarias con Spring -->
30: <dependency>
31: <groupId>org.springframework</groupId>
32: <artifactId>spring-test</artifactId>
33: <version>2.5.5</version>
34: <scope>test</scope>
35: </dependency>
36:
37: <!-- Para el logging -->
38: <dependency>
39: <groupId>log4j</groupId>
40: <artifactId>log4j</artifactId>
41: <version>1.2.8</version>
42: </dependency>
43:
44: <!-- Spring batch -->
45: <dependency>
46: <groupId>org.springframework.batch</groupId>
47: <artifactId>spring-batch-core</artifactId>
48: <version>2.0.0.RC2</version>
49: </dependency>
50:
51: <!-- Spring batch -->
52: <dependency>
53: <groupId>org.springframework.batch</groupId>
54: <artifactId>spring-batch-execution</artifactId>
55: <version>1.0.0.m4</version>
56: </dependency>
57:
58: <!-- Para la conexion a la base de datos -->
59: <dependency>
60: <groupId>commons-dbcp</groupId>
61: <artifactId>commons-dbcp</artifactId>
62: <version>1.2</version>
63: </dependency>
64:
65: <!-- El driver jdbc para mysql -->
66: <dependency>
67: <groupId>mysql</groupId>
68: <artifactId>mysql-connector-java</artifactId>
69: <version>5.1.6</version>
70: </dependency>
71:
72: </dependencies>74: <build>
75: <plugins>
76: <plugin>
77: <groupId>org.apache.maven.plugins</groupId>
78: <artifactId>maven-compiler-plugin</artifactId>
79: <configuration>
80: <source>1.5</source>
81: <target>1.5</target>
82: <archive>
83: <manifest>
84: <addClasspath>true</addClasspath>
85: </manifest>
86: </archive>
87: </configuration>
88: </plugin>
89: </plugins>
90: </build>
66: <job id="process">
67: <step id="loadNWriteFile">
68: <tasklet reader="reader" writer="writer" commit-interval="1"/>
69: </step>
70: </job>
56: <beans:bean id="reader" scope="step" class="org.springframework.batch.item.file.FlatFileItemReader">
57: <beans:property name="resource" value="#{jobParameters[input.file.name]}" />
58: <beans:property name="lineMapper" ref="lineMapper" />
59: </beans:bean>51: <beans:bean id="lineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
52: <beans:property name="lineTokenizer"><beans:ref bean="tokenizer" /></beans:property>
53: <beans:property name="fieldSetMapper"><beans:ref bean="fieldSetMapper" /></beans:property>
54: </beans:bean>41: <beans:bean id="tokenizer"
42: class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
43: <beans:property name="delimiter"><beans:value>,</beans:value></beans:property>
44: <beans:property name="names" value="nombre,apellido,mailPersonal,mailTrabajo,telefono,paginaWeb" />
45: </beans:bean>
Este tokenizer tiene dos propiedades. La propiedad 'delimiter' indica el caracter por el cual vendra separada la informacion que en nuestro caso es una coma ','. La propiedad 'names' indica el nombre que le pondremos a cada uno de los valores en la linea de informacion en el archivo. 8: public Contacto mapFieldSet(FieldSet fieldset) {
9: Contacto newContacto = new Contacto();
10:
11: newContacto.setNombre(fieldset.readString("nombre"));
12: newContacto.setApellido(fieldset.readString("apellido"));
13: newContacto.setMailPersonal(fieldset.readString("mailPersonal"));
14: newContacto.setMailTrabajo(fieldset.readString("mailTrabajo"));
15: newContacto.setTelefono(fieldset.readString("telefono"));
16: newContacto.setPaginaWeb(fieldset.readString("paginaWeb"));
17:
18: return newContacto;
19: }
20:61: <beans:bean id="writer" scope="step"
62: class="com.jabaddon.tutorials.springbatch.fileconverter.ContactoItemWriter">
63: <beans:property name="archivoSalida" value="#{jobParameters[output.file.name]}" />
64: </beans:bean>26: public void write(List<? extends Contacto> items) throws Exception {
27: LOGGER.debug("### -> write() ###");
28: BufferedWriter out = null;
29: try {
30: new File(archivoSalida).createNewFile();
31: out = new BufferedWriter(new FileWriter(archivoSalida, true));
32: LOGGER.info("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
33: for (Contacto item : items) {
34: LOGGER.info("Escribiendo item : " + item);
35: out.write(item.toString());
36: out.write("\n");
37: }
38: LOGGER.info("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
39: }
40: finally {
41: if (out != null) {
42: out.close();
43: }
44: }
45: LOGGER.debug("### <- write() ###");
46: }32: <beans:bean id="jobRepository"
33: class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
34: p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager" />
35:13: <beans:bean id="dataSource"
14: class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
15: <beans:property name="driverClassName" value="com.mysql.jdbc.Driver"/>
16: <beans:property name="url" value="jdbc:mysql://localhost/springbatch_tutorial"/>
17: <beans:property name="username" value="root"/>
18: <beans:property name="password" value="admin"/>
19: <beans:property name="maxActive" value="5"/>
20: <beans:property name="initialSize" value="1"/>
21: </beans:bean>
22:
23: <beans:bean id="transactionManager"
24: class="org.springframework.jdbc.datasource.DataSourceTransactionManager" lazy-init="true">
25: <beans:property name="dataSource" ref="dataSource" />
26: </beans:bean>32: <beans:bean id="jobLauncher"
33: class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
34: <beans:property name="jobRepository" ref="jobRepository" />
35: </beans:bean> 51: public void testJob() throws Exception {
52: LOGGER.debug("### -> testJob() ###");
53: String userdir = System.getProperty("user.dir");
54: String inputFileName = "file:///" + userdir + "/src/test/files/datos-contactos.csv";
55: String outputFileName = userdir + "/target/datos-contactos.txt";
56: JobLauncher jobLauncher = (JobLauncher) this.getApplicationContext().getBean("jobLauncher");
57: JobParametersBuilder paramsBuilder = new JobParametersBuilder();
58: paramsBuilder.addLong("date.miliseconds", System.currentTimeMillis());
59: paramsBuilder.addString("input.file.name", inputFileName);
60: paramsBuilder.addString("output.file.name", outputFileName);
61: JobExecution jobExecution =
62: jobLauncher.run((Job) this.getApplicationContext().getBean("process"),
63: paramsBuilder.toJobParameters());
64:
65: LOGGER.debug("### <- testJob() ###");
66: }Friday, March 27, 2009
Stop dumping money into a giant hole!!!
A ustedes no?
http://www.theonion.com/content/video/in_the_know_should_the_government