Saturday, November 20, 2010

Configuraciones Git

Esta es la lista de opciones de configuración que suelo utilizar en mis repositorios Git.

Información sobre el autor:
$ git config --global user.name 'Javier Martinez Canillas'
$ git config --global user.email martinez.javier@gmail.com


Agregar colores a la salida:
$ git config --global color.diff auto
$ git config --global color.status auto
$ git config --global color.branch auto
$ git config --global color.interactive auto


Cambiar el editor por defecto a vi:
$ git config --global core.editor vim

La opción --global establece la configuración de manera global y no por repositorio.

Algunos comandos útiles

Revertir el último commit
$ git reset --soft HEAD^

Borrar archivos no versionados
$ git clean -f

Establecer el repositorio al estado del último commit
$ git reset --hard

Generar parches firmados con los últimos n commits (ejemplo: los últimos 2)
$ git format-patch -s -2

Saturday, November 13, 2010

@caos.uab.es

Comencé este blog para tener un lugar donde ir documentando mis experiencias con la plataforma Java EE 6 en un proyecto grande. Como en ese entonces la plataforma acabada de salir y no existía mucha documentación al respecto, me pareció interesante escribir sobre lo que iba aprendiendo.

Como comente en mi ultima entrada, me mude a vivir a Barcelona y aunque me ofrecieron seguir en el proyecto como asesor remoto, decidí no continuar para poder dedicar todo mi tiempo y esfuerzo al Máster en Computación de Altas Prestaciones que empecé en la Universitat Autónoma de Barcelona.

Por lo tanto, ya no voy a escribir sobre desarrollo de aplicaciones web ni Java EE 6, lastimosamente no llegue a escribir ni el 10% de lo que quería, tengo una lista de +50 items sobre los que me hubiese gustado escribir.

De todas maneras, me pareció interesante y útil mantener un blog, además de tener un promedio de 600 visitas/mes. Así que voy a continuar con mi blog, solo que de ahora en más probablemente escriba sobre temas relacionados con mi máster, por ejemplo computación paralela, aplicaciones paralelas de pasos de mensajes, evaluación y predicción de rendimientos de aplicaciones paralelas, etc.

Sunday, July 18, 2010

mv /home/javier/ /espanya/barcelona/

Empecé este blog para tener un lugar donde escribir sobre los problemas y soluciones con los que me encontraba durante el desarrollo de un sistema empresarial utilizando la plataforma Java EE 6.

Ya que es una plataforma nueva y no hay tanta documentación, me pareció que a alguien le podría servir lo que escribo.

Tengo una lista de temas que me gustaría tocar en el blog y no encuentro el tiempo, mas que nada es sobre JPA 2.0, JSF 2.0, JCDI 1.0, Facelets y Jquery, aunque también hay varios temas que involucran a la plataforma de Liferay e incluso desarrollo para el kernel de Linux.

Lastimosamente no tengo (o no encontré) mucho tiempo para escribir todo lo que quiero. Ahora mismo estoy muy ocupado con la logística para mi próximo viaje a Barcelona e incluso estic estudiant Català (hasta ahora lo que más me gustó es que la ñ no forma parte de su alfabeto). Espero encontrar un poco de tiempo libre para seguir escribiendo sobre todo lo que tengo pendiente de publicar.

Fins la propera!

Tuesday, April 20, 2010

Convertir imagen VirtualBox .vdi a Qemu .raw

Me es mas sencillo montar las imágenes de QEMU que las de VirtualBox. Pero no me fue intuitivo como convertir una imagen VirtualBox .vdi en una imagen RAW.

En la mayoría de los blogs y tutoriales hablan de utilizar un binario llamada vditool, el problema es que aparentemente esta herramienta ya no esta soportada por VirtualBox.

Finalmente encontré como convertir la imagen en esta wiki http://en.wikibooks.org/wiki/QEMU/Images#Exchanging_images_with_VirtualBox.

Se utiliza el comando VboxManage


VBoxManage internalcommands converttoraw ubuntu.vdi ubuntu.raw


Ahora ya puedo montar mi imagen


mount -o loop,offset=32256 ubuntu.raw /mnt/diskimage/


y también iniciarla con QEMU


qemu -m 512 -hda ubuntu.raw -boot c

Thursday, March 25, 2010

CDI @ConversationScoped y JSF 2.0

En entradas anteriores hemos visto cuales son las ventajas de CDI 1.0 y como podemos utilizarlo para definir nuestros backing beans JSF 2.0.

En esta entrada vamos a ver que son las conversaciones en CDI y como podemos utilizarlas en aplicaciones JSF 2.0.

Siguiendo con la filosofía de este blog, el proyecto completo del ejemplo, puede ser descargado de http://kenai.com/projects/javiermartinezblog/downloads/download/JSFCDIConversations.zip.


Conversaciones y ámbito de conversación en CDI

Contexts and Dependency Injection (CDI) ofrece un conjunto de servicios que permiten que clases manejadas puedan existir durante el ciclo de vida de la aplicación en ámbitos bien definidos.

Uno de los ámbitos de CDI es el ámbito de conversación. En una entrada anterior, hablamos sobre los ámbitos de CDI, por lo que no voy a explicar cuales son en esta entrada.

El ámbito de conversación permite que las instancias existan durante mas de una petición. Una conversación puede estar compuesta de varias peticiones y pueden existir varias conversaciones por sesión.

Realmente, cada petición tiene asociada una conversación. Solamente que si la conversación no es marcada como "long-running" el contexto de conversación se libera al termino de la petición.

Por el contrario si la conversación fue marcada como "long-running" en alguna petición, el contexto de conversación se propaga a las siguientes peticiones hasta que este contexto sea destruido explícitamente.

Vemos que todas las peticiones tienen asociada una conversación, y esta puede estar en uno de estados:
  • Transient: La conversación no fue iniciada explícitamente y de manera implícita existe durante el tiempo de vida de la petición.
  • Long running: La conversación fue marcada como long running y existe hasta que sea finalizada explícitamente. Todas las demás peticiones van a estar dentro del ámbito de la conversación

Por lo tanto, las conversaciones se utilizan para mantener mantener un estado entre distintas peticiones. Para esto se tiene que establecer dos cosas:

1- Que el managed bean CDI tiene un ámbito de conversación.

2- Se tiene que marcar la conversación como "long-running".

A continuación vamos a ver como se realizan ambas cosas en CDI.

1 - Especificar que el ámbito de un managed bean CDI es de conversación:

CDI tiene varias anotaciones que definen tipos de ámbito, la anotacion para definir que una clase tiene un ámbito de conversación es:


@javax.enterprise.context.ConversationScoped


2- Marcar la conversación como long-running:

CDI cuenta con un bean para controlar el ciclo de vida de las conversaciones, esta clase es:


javax.enterprise.context.Conversation


Para que una conversación se propague a las demás peticiones, hay que marcarla como long-running.

Esto se hace primero obteniendo el bean que controla la conversación a través de inyección:


@Inject Conversation conversation;


y luego ejecutando el método begin() que marca la conversación como long-running:


converstaion.begin();


Para que la conversación se destruya al termino de la petición actual se ejecuta el método end():


converstaion.end();


Aplicación de ejemplo

Como se comento anteriormente, se ilustra el uso de conversaciones CDI en aplicaciones JSF 2.0, a través de un ejemplo.

La aplicacion de ejemplo es muy sencilla, solamente cuenta con dos paginas y lo único que hace es incrementar un contador cada vez que se ejecuta un botón. Además, cuenta con una segunda pagina que muestra el valor del contador.

El backing bean Controller tiene un ámbito de conversación, por lo que la clase tiene que ser decorada con la anotacion @SessionScoped y ademas tiene que implementar la interfaz Serializable (esto es requerido para cualquier managed bean CDI con un ámbito mayor que petición). A continuacion podemos ver las porciones relevantes de la clase Controller:


@javax.inject.Named
@javax.enterprise.context.ConversationScoped
public class Controller implements Serializable {
private int number = 0;

@Inject
private Conversation conversation;

/* getters, setters y metodos omitidos */
}


La clase tiene dos campos, number que representa el contador y es donde se guarda el estado de la cantidad de veces que se presiono el botón y conversation que es el bean que controla el ciclo de vida de la conversación y se obtiene a través de inyección.

La pagina principal index.html tiene un botón que al presionarlo ejecuta el método count() del backing bean Controller. Este método lo único que hace es incrementar el valor del campo number en uno. Además, un tag JSF esta asociado al campo number del backing bean.

A continuación se pueden ver las porciones relevantes del código fuente de la pagina index.xhtml, así como los métodos del backing bean utilizados:


<h:commandButton action="#{controller.count}" value="Set count"/>
<h:outputLabel value="Count:"/>
<h:outputText value="#{controller.number}"/>



public void count()
{
number++;
}

public int getNumber()
{
return number;
}


Si la conversación no fue propagada a long-running, al termino de cada petición la conversación implícita asociada a la petición es destruida y se pierde el estado del backing bean. Por lo tanto también se pierde el contador y cada vez que se realice una solicitud, el contador tendra el mismo valor=1.

Por otro lado si marcamos la conversación como long-running, el estado del backing bean existe entre peticiones por lo que cada vez que se presiona el botón, el contador se incrementara en uno y la pagina va a desplegar el nuevo valor.

Por lo tanto la pagina index.html tambien cuenta con dos botones que permiten iniciar y terminar la conversacion, estos botones tienen asociados metodos en el backing bean que realizan estas funciones.

A continuacion se ilustra el codigo fuente de los botones, asi como los metodos en el backing bean que inician y terminan la conversacion:


<h:commandButton action="#{controller.beginConversation}" value="Begin Conversation"/>
<h:commandButton action="#{controller.endConversation}" value="End Conversation"/>



public void beginConversation()
{
if(conversation.isTransient())
conversation.begin();
}

public void endConversation()
{
if(!conversation.isTransient())
conversation.end();
}


Algo importante de destacar es que solamente se puede marcar una conversación como long-running si esta es transient. El querer marcar como long-running una conversación que ya lo es, se levanta una excepción. De igual manera solamente se puede terminar una conversación que es long-running.

Por este motivo primero se pregunta si la conversación isTransiente() o no, antes de tomar cualquier acción.


Además, la pagina principal cuenta con otro botón que permite ver el valor del contador en otra pagina result.xhtml. Esta pagina hace referencia a un backing bean (ResultController) CDI con ámbito de petición.

Como la conversación se propaga a las demás peticiones, el backing bean ResultController utiliza inyección para obtener la instancia del backing bean Controller que existe en su ámbito de petición.

A continuación se muestra el código fuente del backing bean ResultController:


@Named
@RequestScoped
public class ResultController {

private @Inject Controller controller;

public int getCount()
{
return controller.getNumber();
}
}


Eso es todo, en próximas entradas vamos a seguir viendo otras características de JSF 2.0, CDI 1.0 y Java EE 6 en general.

Wednesday, February 24, 2010

Validar formularios JSF 2.0 con Bean Validation 1.0

En la entrada anterior se ilustro a través de un ejemplo las ventajas de implementar los backing beans JSF 2.0 como clases manejadas por CDI 1.0.

En esta entrada vamos a ver como integrar una tercera tecnología que forma parte de mi pila tecnológica ideal para desarrollo de aplicaciones web Java EE. Esta tecnología se define en el JSR 303 y se conoce como Bean Validation 1.0.

Bean Validation define un modelo de meta-datos basado en anotaciones y una API para realizar validaciones de JavaBeans.

Siguiendo la misma temática que en las entradas anteriores, voy a utilizar un pequeño ejemplo para demostrar las ventajas de Bean Validation.

El código fuente completo del ejemplo JSF-BeanValidation.zip, esta disponible en la plataforma kenai.com. Se creo un proyecto exclusivamente para albergar todos los ejemplos utilizados en este blog.

Aplicación de Ejemplo

La aplicación de ejemplo esta compuesta de tan solo una pantalla. Esta pantalla es un formulario que se utiliza para ingresar usuarios. El usuario solamente tiene dos campos, username y mail.

La aplicacion tiene tres componentes, el primero es una pagina Facelets que es la que presenta el formulario, los otros dos componentes son clases Java. Una representa al backing bean JSF y la otra es el modelo del usuario.

A continuación se ilustra la sección relevante del código fuente de la pagina


<h:form>
<h:panelGrid columns="3">
<h:outputLabel value="Username:" for="username"/>
<h:inputText id="username" value="#{userController.user.username}"/>
<h:message for="username" errorStyle="color: red" infoStyle="color: green"/>
<h:outputLabel value="E-mail:" for="email"/>
<h:inputText id="email" value="#{userController.user.email}"/>
<h:message for="email" errorStyle="color: red" infoStyle="color: green"/>
<h:commandLink action="#{userController.saveUser}" value="Save"/>
</h:panelGrid>
</h:form>
<h:panelGrid>
<h:messages globalOnly="true" errorStyle="color: red" infoStyle="color: green"/>
</h:panelGrid>


Como se puede ver, las cajas de texto están asociadas a campos de una instancia de la clase User.
Se accede a esta instancia a través de un campo del backing bean JSF userController.

El formulario cuenta con un botón que permite dar de alta al usuario. Para mantener a la aplicación lo mas simple posible, realmente no se van a almacenar los usuarios en ningún repositorio de datos, solamente se va a validar el modelo utilizando Bean Validation 1.0.

En una aplicación real, probablemente se utilizaría Java Persistence API 2.0 para realizar la persistencia, en entradas posteriores vamos a ver ejemplos de como integrar JPA con el resto de las tecnologías que vimos hasta ahora.

Validaciones con Bean Validation 1.0

La mayoría de las aplicaciones requieren validar la entrada de datos para permitir que el modelo de datos sea consistente.

Por ejemplo, si tenemos un formulario de alta de usuario en una aplicacion web, deberíamos validar que los datos ingresados sean los correctos. Además, tendríamos que notificar cuando un dato es incorrecto para que este pueda volver a ser ingresado correctamente.

En la practica, varios programadores forman parte del grupo encargado del desarrollo de una aplicación.

El desarrollador encargado de la lógica de negocios de un ingreso de usuario, no puede suponer que el desarrollador del formulario de alta de usuario realizó la validación de los campos en la capa de presentación.
Suponer esto puede hacer que la aplicación no sea robusta, ya que los datos ingresados podrían no ser correctos.
Por lo tanto el desarrollador de la lógica de negocios tiene que volver a validar que los campos sean correctos y este mismo escenario se repite para el desarrollador encargado de la capa de acceso a datos.

Es así como uno termina teniendo validaciones en cada capa de la aplicación como muestra la siguiente figura:



Este proceso no solo es propenso a errores, sino que duplica código y hace que la manutención del software sea mas difícil.

Por lo tanto, Bean Validation 1.0 es un esfuerzo por tener un único esquema de validación que se propague por todas las capas de la aplicacion.

La validación se realiza a nivel de modelo y se especifica de manera declarativa.

Bean Validation 1.0 tiene dos componentes:


  • Un modelo declarativo y extensible de validación basado en anotaciones

  • API estándar de consulta de meta-datos y validación en tiempo de ejecución



Como se comento anteriormente, para definir las restricciones de los campos se utilizan anotaciones, Bean Validation incluye varias anotaciones estándar que se encuentran en el paquete javax.validation.constraints. Las anotaciones estándar son:

  • @AssertFalse: El campo Boolean tiene que ser false.
  • @AssertTrue: El campo Boolean tiene que ser true.
  • @DecimalMax: El campo tiene que ser un numero cuyo valor sea menor o igual a un máximo especificado.
  • @DecimalMin: El campo tiene que ser un numero cuyo valor sea mayor o igual a un mínimo especificado.
  • @Digits: El campo tiene que ser un numero cuyo valor se encuentre en un rango definido.
  • @Future: El campo tiene que ser una fecha en un futuro.
  • @Max: El campo tiene que ser un numero cuyo valor sea menor o igual a un máximo especificado.
  • @Min: El campo tiene que ser un numero cuyo valor sea mayor o igual a un mínimo especificado.
  • @NotNull: El campo no puede tener valor null.
  • @Null: El campo tiene que tener valor null.
  • @Past: El campo tiene que ser una fecha en el pasado.
  • @Pattern: La cadena tiene que coincidir con el patrón de expresión regular especificado.
  • @Size: El tamaño del campo tiene que estar dentro de un limite especificado (incluyente).


En la aplicación de ejemplo, la clase User utiliza Bean Validation para validar los campos, en el siguiente cuadro se ilustra el código fuente de la clase User:


public class User {

@NotNull
@Size(min=1,max=30)
private String username;

@Size(max=100)
@Pattern(regexp=".+@.+\\.[a-z]+")
private String email;

/*
getters y setters
omitidos
*/
}


La clase tiene dos campos username y email. Las validaciones especifican las siguientes restricciones para cada campo:

  • username: El campo no puede ser nulo (@NotNull) y su tamaño tiene que estar dentro del limite 1 a 30 (@Size(min=1,max=30).
    En el caso de una cadena, el tamaño se evalúa como longitud de la cadena, aunque tiene semántica distinta para otros tipos de datos (Collection, Array, Map, etc).
  • email: El tamaño del campo no puede ser mayor a 100 (@Size(max=100). Además, la cadena tiene que coincidir con el patrón definido por una expresión regular (@Pattern(regexp=".+@.+\\.[a-z]+")). Esta expresión regular especifica el formato válido para las direcciones de correo electrónico.


Como se comento anteriormente, Bean Validation esta compuesto de dos elementos. El primero es un modelo de meta-datos basado en anotaciones que se utiliza para decorar las clases y definir restricciones en los campos. Esto es lo que acabamos de ver.

El segundo componente es la API de consulta de meta-datos y validación. Esta API es la que se utiliza para verificar si una instancia de una clase cumple con todos los requisitos definidos con las anotaciones de Bean Validation.

Para validar las instancias de los JavaBeans se utiliza una implementación que implemente la interfaz:


javax.validation.Validator


La interfaz tiene un método validate() que es el que se utiliza para validar las instancias. Se obtiene una instancia de la implementación a través de un método factory:


Validator validator = Validation.buildDefaultValidatorFactory().getValidator();


A continuación, mostramos un ejemplo de como verificar si un usuario cumple con todas las restricciones. De no cumplir con alguna restricción, imprime en la salida estándar el nombre del campo que no cumple con la restricción y su respectivo mensaje de error.


Set<constraintviolation><user>> constraintViolations = Validation.buildDefaultValidatorFactory().getValidator().validate(this.user);

for(ConstraintViolation<user> constraintViolation : constraintViolations){
System.out.println(constraintViolation.getPropertyPath());
System.out.println(constraintViolation.getMessage());
}


Invocar explícitamente el método validate() debería ser la excepción y no la regla, ya que la idea es definir la validación en el modelo y utilizarla en todas las capas. Por lo tanto la mayoría de los frameworks de capa de presentación, tendrían que integrar automáticamente el mecanismo de validación de Bean Validation.

JavaServer Faces 2.0 lo integra automáticamente. Lo único que uno tiene que hacer es definir la validación en el JavaBean que contiene los campos asociados a los componentes GUI JSF y definir tags <message> o <messages> que procesen los mensajes de error.

Por ejemplo, en el formulario de alta de usuarios, hay una caja de texto asociada al campo username de la clase User:


<h:inputText id="username" value="#{userController.user.username}"/>
<h:message for="username" errorStyle="color: red" infoStyle="color: green"/>


Además, hay un tag <message> que esta asociado al <inputText> asociado al campo username.

Por lo tanto, si ocurre un error de validación en ese campo, JSF actualiza automáticamente el componente UI JSF correcto con el mensaje de error correspondiente.

Si queremos que los mensajes de error sean globales, entonces tenemos que definir un tag <messages> que no este asociado a ningún componente GUI.


<h:messages globalOnly="true" errorStyle="color: red" infoStyle="color: green"/>


Entonces, todos los mensajes de error de validación van a ser agregados a este componente UI, sin importar cual campo es el que no cumple con sus restricciones de validación.

Eso es todo lo que necesitamos para implementar validaciones de modelo en nuestras paginas JavaServer Faces 2.0.

Al hacer clic en el botón:


<h:commandLink action="#{userController.saveUser}" value="Save"/>


Primero se va a realizar la validación del modelo y si algún campo no cumple con sus restricciones de validación, se va a notificar mostrando los mensajes de error en los tags de mensajes.
Solamente si se cumplen todos los requisitos de validación, se va a ejecutar el método saveUser().

En esta entrada vimos un uso básico de Bean Validation, en próximas entradas vamos a ver conceptos mas avanzados como tener varios grupos de validación, crear restricciones de validación propias y el uso de Bean Validation para validar clases persistibles a través de JPA 2.0.

Thursday, February 18, 2010

Ejemplo Aplicación JSF 2.0 con CDI 1.0

Como había comentado en una entrada anterior, Java EE 6 nos ofrece varias opciones para guardar el estado de los componentes UI cuando utilizamos JavaServer Faces.

Mi opción preferida es utilizar Contexts and Dependency Injection (CDI) para los backing beans JSF. Por lo tanto, en esta entrada voy a presentar un pequeño ejemplo de como utilizar JSF + CDI y voy a ilustrar algunas de las bondades de CDI.
No voy a explicar como configurar el proyecto para que utilice CDI, eso pueden verlo en esta entrada del blog.

El código fuente del ejemplo completo JSF-CDI.zip se encuentra en el proyecto creado, para los ejemplos del blog, en la plataforma kenai.com.

Aplicación de Ejemplo

La aplicacion de ejemplo es sumamente sencilla, esta compuesta solamente de dos paginas. La primera pagina tiene una caja de texto en el que se puede definir una entrada. Al presionar un botón se muestra en una etiqueta el texto ingresado. La segunda pagina permite ver el texto ingresado en la primera pagina y su función es ilustrar como se puede guardar el estado entre peticiones de distintas paginas.

JSF 2.0 utiliza como tecnología de vista Facelets ya que se integra mejor con JSF que JSP, por lo tanto las paginas del ejemplo son Facelets. A continuación se muestra la porción relevante del código fuente de ambas paginas:


<h:form>
<h:panelGrid columns="3">
<h:outputLabel value="Please enter an input:"/>
<h:inputText value="#{controller.input}"/>
<h:commandButton action="#{controller.setOutputAction}"
value="Set Output"/>
<h:outputLabel value="You entered: "/>
<h:outputText value="#{controller.output}"/>
</h:panelGrid>
<br/>
<h:commandButton action="/result" value="See output in another page"/>
</h:form>



<h:form>
<h:panelGrid columns="3">
<h:outputLabel value="You entered: "/>
<h:outputText value="#{resultController.output}"/>
</h:panelGrid>
<br/>
<h:commandButton action="/index" value="Go to main page"/>
</h:form>


No hay grandes cambios aquí, las paginas Facelets lucen igual que en JSF 1.2, están compuesta de componentes UI JSF y utilizan expresiones EL (Expression Language) para referirse a instancias de las clases que se utilizan como backing beans.

El cambio está en los backing beans, que son clases manejadas por CDI.

CDI como Backing Bean JSF

CDI ofrece un conjunto de servicios que permiten que clases manejadas puedan existir durante el ciclo de vida de la aplicación en ámbitos bien definidos.

Cuando un jar cuenta con un archivo beans.xml el contenedor registra todas las clases del jar con el motor CDI automáticamente. No es necesaria ninguna anotación para especificar que una clase tiene que ser manejada por CDI.

De todas maneras, si queremos que las instancias de las clases sean accesibles a través de expresiones EL, tenemos que decorar las clases con la anotación


@javax.inject.Named


De esta manera podemos acceder a los miembros de las clases manejadas a través de expresiones EL.
Por defecto el nombre de la instancia va a ser el nombre de la clase con su primera letra en minúscula, aunque podemos especificar otro nombre para referirnos a la instancia de la clase manejada. Ej:


@javax.inject.Named
public class Controller { ... }

#{controller.input}

@javax.inject.Named("testController")
public class Controller { ... }

#{testController.input}


CDI permite que las instancias existan en ámbitos bien definidos. Para marcar el ámbito de una clase manejada CDI, se utilizan anotaciones que se encuentran en el paquete javax.enterprise.context. Los ámbitos soportados por CDI son los siguientes:


  • @ApplicationScoped (Ámbito de Aplicación): Las instancias existen durante todo el ciclo de vida de la aplicacion. Estas instancias son globales y accesibles desde cualquier sesión HTTP.

  • @SessionScoped (Ámbito de Sesión): Las instancias son accesibles por todas las peticiones que ocurren durante una sesión HTTP.

  • @ConverstationScoped (Ámbito de Conversación): Las instancias existen durante una conversación. Una conversación esta compuesta de varias peticiones y pueden existir varias conversaciones por sesión.
    Realmente, cada petición tiene asociada una conversación. Solamente que si la conversación no es marcada como "long-running" el contexto de conversación se libera al termino de la petición.
    Por el contrario si la conversación fue marcada como "long-running" en alguna petición, el contexto de conversación se propaga a las siguientes peticiones hasta que este contexto sea destruido explícitamente.

  • @RequestScoped (Ámbito de Petición): Las instancias solamente existen durante la peticion HTTP. Una vez que termina el ciclo de vida de la petición, también termina su contexto.


El ámbito de petición (@RequestScoped) es muy común, por lo que existe una anotación que incluye las anotaciones @Named y @RequestScoped, esta anotación es:


@javax.enterprise.inject.Model


En el ejemplo, queremos que la aplicacion tenga el siguiente comportamiento: cuando se presione el botón, se establezca el valor del campo asociado con la caja de texto, a la etiqueta de salida. Además, queremos que ese valor sea accesible desde otra pagina.

Con estos requerimientos, el valor tendría que poder existir durante varias peticiones HTTP. Por lo tanto la instancia del backing bean de la pagina principal tiene que ser anotada con una de las anotaciones @SessionScoped o @ConversationScoped, para que sea accesible durante varias peticiones.

Para este ejemplo se usa @SessionScoped para hacer mas claro el ejemplo y en próximas entradas se utilizara otro ejemplo para mostrar como funcionan las conversaciones en CDI.

Por lo tanto la clase backing bean de la pagina principal se llama Controller y esta definida de la siguiente manera:


@javax.inject.Named
@javax.enterprise.context.SessionScoped
public class Controller implements Serializable {
private String input;
private String output;

@EJB UpperCaseEJB testEJB;

/*
Resto de la declaración de la clase omitida.
*/
}


Implementa la interfaz Serializable porque CDI exige que las clases que se definen en un ámbito que no sea @RequestScoped, implementen esta interfaz.
Los campos input y output están asociados a los controles UI inputText y outputText respectivamente.
Las clases manejadas por CDI cuentan con varios servicios, la inyección es una de ellas y por eso utilizamos un EJB (UpperCaseEJB) para demostrar eso.
La instancia testEJB va a ser inyectada por el contenedor cuando se instancie la clase Controller.

Cuando hacemos click en el botón:


<h:commandButton action="#{controller.setOutputAction}"
value="Set Output"/>


se ejecuta el método setOutputAction() de la clase Controller, el método es el encargado de establecer el valor de la leyenda para mostrar en pantalla:


this.output = testEJB.toUpper(this.input);


El método toUpper() del EJB TestEJB convierte la cadena a mayúsculas, esto se utilizo solamente con fines académicos para demostrar lo sencillo que es utilizar un EJB desde una clase CDI.

Eso es todo, cuando se visualice la pagina nuevamente se va a ver el valor del campo output:


<h:outputLabel value="You entered: "/>
<h:outputText value="#{controller.output}"/>


Contextos e Inyección en CDI

La verdad que hasta ahora no vimos nada tan novedoso, después de todo los @ManagedBean JSF 2.0 también utilizan anotaciones para registrarse y definir su ámbito, son accesibles desde expresiones EL y también pueden inyectar instancias de EJBs.

Una de las novedades de CDI es su mecanismo de biyeccion, es decir la capacidad de publicar una instancia de una clase en algún ámbito y poder referirse a esa instancia desde otra clase.

En el ejemplo, queremos que se pueda ver el valor ingresado en la caja de texto, pero desde otra pagina.
Para esto, el backing bean de la pagina result.xhtml tiene que poder acceder a este valor.

Entonces, lo que queremos es publicar la instancia de la clase Controller que tiene este valor en un ámbito y que luego sea inyectado en la clase ResultController. Cuando se crea una instancia de la clase ResulController, automáticamente el contenedor deberia asignar la referencia a la instancia de la clase publicada.

La clase Controller tiene un ámbito de Sesión ya que fue decorada con la anotacion @SessionScoped.
Además, todas las clases son manejadas por CDI automáticamente, recordemos que la anotacion @Named es tan solo para hacer que la clase sea visible por las expresiones EL.
Por lo tanto, lo único que tenemos que hacer en la clase ResultController es inyectar una instancia de la clase Controller con la anotacion:


@javax.inject.Inject


Ej:


@Named
public class ResultController {

private @Inject Controller controller;

public String getOutput()
{
return controller.getOutput();
}
}
Eso es todo! El contenedor automáticamente inyecta una instancia de la clase Controller.

Por ultimo obtenemos el valor de output con el método getOutput().

Puede darse el caso de que tengamos mas de una instancia de una clase en particular. Por ejemplo, podríamos tener un sistema de control de versiones que tenga que comparar la diferencia entre dos archivos.

En estos casos tenemos que tener una manera para discriminar cual es la instancia que queremos inyectar.

Otros frameworks como Jboss Seam utilizan cadenas de texto como identificadores, pero esto es propenso a errores y los problemas se identifican recien en fase de ejecución.

Por el contrario, CDI utiliza un esquema de discriminación fuertemente tipado. Se utilizan anotaciones para especificar cual es la instancia que queremos inyectar.

En el ejemplo de los archivos tendríamos dos anotaciones, una que se podría llamar @Modificado y otra que podría llamarse @Base.

No solo tenemos que utilizar la anotacion a la hora de inyectar una instancia, sino que la publicación de una instancia ya no puede ser automática.
Tenemos que declarar explícitamente que tipo de instancia estamos publicando.

Por lo tanto, modificamos un poco la aplicacion de ejemplo para utilizar inyección fuertemente tipada. Lo primero que tenemos que hacer es definir una anotacion para discriminar a nuestra instancia que queremos publicar.

La anotacion que creamos se llama @SetupController, esta anotacion nos dice que el Controller que queremos inyectar es el utilizado para establecer el valor del input.

La manera de publicar instancias en CDI es definiendo un método cuyo valor de retorno este decorado con la anotacion:


@javax.enterprise.inject.Produces


Por ejemplo si quisiéramos publicar explícitamente nuestra instancia de la clase Controller podemos definir el siguiente método en la misma clase Controller:


public @Produces @SetupController Controller getController()
{
return this;
}


La semántica del método es que esta produciendo una instancia de una clase Controller con tipo @SetupController.

Cuando uno quiere inyectar una instancia de un tipo en particular, el contenedor busca en todas las instancias que existen en algún ámbito, aquella que cuenta con un método que produce el tipo de instancia que nosotros queremos inyectar.
Una vez que encuentra el método, lo ejecuta, obtiene el valor y lo inyecta en la instancia definida en nuestra clase.

Entonces, si quisiéramos inyectar la instancia de tipo @SetupController en nuestra clase ResultController, tendríamos que cambiar la declaración del campo a la siguiente:


private @Inject @SetupController Controller controller;


También podríamos haber publicado e inyectado tan solo el String que representaba nuestro output, pero me pareció mas interesante ver como se publicaba la propia clase Controller.

Eso es todo, en las siguientes entradas veremos como funcionan las conversaciones en CDI y otras cuestiones como agregar validaciones a nivel de modelo utilizando Bean Validation 1.0.

Monday, February 15, 2010

Utilizar Contexts and Dependency Injection (CDI) en proyectos JSF 2.0

En la entrada anterior se explicaron cuales eran las distintas maneras de implementar un JavaServer Faces (JSF) 2.0 backing bean. En esta entrada vamos a ver como crear un proyecto web JSF 2.0 en Netbeans 6.8 que soporte Context and Dependency Injection (CDI) Managed Beans.

Lo primero que tenemos que hacer es crear un proyecto web:



En el paso de elegir Frameworks, seleccionar JavaServer Faces. En la pestaña de Libraries seleccionar la librería JSF que viene por defecto (JSF 2.0) y en la pestaña de Configuration, seleccionar el lenguaje de pagina preferido como Facelets.



A diferencia de otros motores de manejo de beans, CDI no necesita de ninguna anotación para que una clase se registre y sea manejada. Por defecto todas las clases de un archivo (jar) son manejadas por CDI. La anotación @Named tan solo hace que los atributos de la clase sean accesible desde expresiones EL.

La búsqueda de clases y el registro de las mismas en el motor de CDI hace que el deploy de una aplicación sea mas lento. Por lo tanto, necesitamos de una manera de decirle al container si queremos o no usar CDI. La manera de especificar esto es creando un archivo xml vacío (beans.xml) en los directorios WEB-INF o META-INF.

La sola existencia del archivo WEB-INF/beans.xml o MET-INF/beans.xml ya activa CDI.

Por lo tanto, el ultimo paso consiste en crear el archivo WEB-INF/beans.xml.



Se puede por ejemplo tener varios jar, donde uno solo contiene un archivo beans.xml. De esta manera, el contenedor solo registraría las clases de este jar y no de los otros, haciendo que el deploy de la aplicacion sea mas rápido. Gavin King en su blog explica el porque de la necesidad del archivo beans.xml.

En la Figura podemos ver como queda la jerarquía de directorios del proyecto y como el archivo beans.xml esta vacío, la sola presencia del archivo ya es suficiente para activar el motor CDI.


Esto es todo, ahora lo único que tenemos que hacer es agregar clases y estas ya van a ser manejadas por CDI.

Si deployamos la aplicación, vamos a ver en el log del glassfish que se esta utilizando CDI, cuales son las clases manejadas y el ámbito de cada una.

En la siguiente entrada voy a explicar como utilizar las clases manejadas por CDI como backing beans JSF y como estas pueden ser accesibles desde expresiones EL en paginas Facelets. Para esto voy a utilizar un ejemplo que va a ilustrar las facilidades que nos brinda CDI.

Para hacer mas útil el blog, cree un proyecto en la plataforma Kenai donde voy a ir subiendo los ejemplos de las entradas que vaya publicando.

El primer ejemplo (JSF-CDI) es una pequeña aplicación que utiliza CDI Managed Beans para persistir el estado de los componentes UI de paginas JSF 2.0 con Facelets.

Actualización:

Si se realiza una actualizacion del Netbeans 6.8, ahora al crear un proyecto web, hay una opcion para habilitar CDI en el proyecto.



En la siguiente imagen podemos ver que en la sección de configuraciones, hay un checkbox para elegir si activar o no activar CDI. Por lo tanto lo único que se tiene que hacer es seleccionar esa opción y automáticamente se crea el archivo WEB-INF/beans.xml.

Thursday, February 11, 2010

JSF 2.0 Backing Bean: @ManagedBean o @Named

Dos de los cambios de Java EE 5 y EJB 3.0 que mejoraron la productividad de los desarrolladores, fueron el uso de anotaciones y la configuración por excepción.

Antes de la llegada de Java EE 6 y JSF 2.0, la capa de presentación web no contaba con estas facilidades. Se tenia que editar varios XMLs para definir cuales eran las clases que tenían que ser manejadas por el motor de JavaServer Faces, las clases que se iban a utilizar para realizar conversiones, validaciones y la navegación entre paginas.

JSF 2.0 tiene varias mejores sobre JSF 1.x y entre la mas importante esta la posibilidad de decorar las clases que van a ser manejadas con anotaciones en vez de definirlas en archivos XML.

Lastimosamente no existe una sola manera de definir una clase (Bean) que va a ser manejada (Managed). De hecho Java EE 6 cuenta con tres maneras de definir una clase como un Managed Bean (cuatro de hecho, si tomamos en cuenta faces-config.xml).

Las tres maneras están definidas por distintas especificaciones, se utilizan distintas anotaciones, las prestaciones de cada manera son diferentes e incluso se manejan las clases por distintos contextos de ejecución.

El hecho de tener varias maneras de definir una misma cosa (Backing Bean JSF) hace que la curva de aprendizaje sea mas pronunciada para nuevos desarrolladores e puede incluso hacer mas complicado el desarrollo para programadores con experiencia (Dos anotaciones tienen el mismo nombre @ManagedBean).

A continuación analizamos cada una de las anotaciones:

JSF 2.0 Managed Bean (JSR 314)

JavaServer Faces 2.0 define sus propias anotaciones para registrar las clases que van a ser Managed Beans. La anotación es @javax.faces.bean.ManagedBean y nos libra de tener que especificar esta información en el archivo XML faces-config.xml.

También permite definir el ámbito de las clases manejadas y las hace accesibles desde expresiones EL.

Ej:


@javax.faces.bean.ManagedBean
@javax.faces.bean.SessionScoped
public class Bean implements Serializable{ ... }


También existe otra anotación que permite inyectar en una referencia una instancia de una clase que este siendo manejada en algún ámbito.

Ej:


@javax.faces.bean.ManagedProperty(value="#{bean}")
private Bean bean;

public void setBean(Bean bean)
{
this.bean = bean;
}


Cuando se instancia la clase que contiene el campo bean, se evalúa la expresión y se llama al método setBean().

Managed Bean 1.0 (JSR 316)

Debido a que existían muchos modelos de componentes para definir clases manejadas (JSF Managed Beans, EJB, CDI, etc), el grupo de trabajo de EJB 3.1 definio un modelo de componentes general. Se definió una anotación (@javax.annotation.ManagedBean) que marca a una clase como un "ManagedBean". Estas clases automáticamente cuentan con un conjunto de servicios básicos (inyección de recursos, callbacks del ciclo de vida e interceptores).

Lastimosamente se eligió el mismo nombre para definir ambos tipos de clases manejadas (Managed Bean 1.0 y JavaServer Faces 2.0).

Otro problema de los ManagedBeans es que no son accesibles desde expresiones EL. La única razón por la que se incluyo en esta lista es para evitar que uno se confunda y utilice la anotación:


@javax.annotation.ManagedBean


en vez de


@javax.faces.bean.ManagedBean


Context and Dependency Injection 1.0 (JSR 299)

Context and Dependency Injection (CDI) es un conjunto de servicios que permiten que clases manejadas puedan existir durante el ciclo de vida de la aplicación en contextos bien definidos.

Es otra manera de registrar POJOs como clases manejadas. CDI tiene dos ventajas sobre los otros enfoques:

  1. JSF 2.0 Managed Beans esta muy orientado a un entorno de ejecución web. Al igual que los ManagedBean de JSF 316, CDI pretende ser mas general por lo que ofrece mas prestaciones que los JSF Managed Beans.
  2. CDI permite crear objetos (outjection) e inyectar recursos (injection) en varios ámbitos y utiliza tipos en vez de expresiones, además las clases manejadas por CDI pueden ser accedidas desde expresiones EL (a diferencia de los ManagedBeans JSR 316).
Varias de las ideas de CDI fueron tomadas de frameworks pragmáticos como Jboss Seam, Spring y Google Guice.

La anotación que se utiliza para registrar una clase en CDI es @javax.inject.Named.

Ej:


@javax.inject.Named
@javax.enterprise.context.SessionScoped
public class Controller implements Serializable {...}


Para inyectar una instancia de algún ámbito en una referencia se utiliza el tipo.

Ej:


@Inject private Controller controller;


La inyección es fuertemente tipada y se verifica en tiempo de compilación, no en tiempo de ejecución.

Personalmente creo que CDI es la mejor manera de utilizar clases manejadas en Java EE 6, en próximas entradas veremos cuales son los requisitos para utilizar CDI Managed Beans con el stack de Sun y cuales son sus ventajas.

Tuesday, February 2, 2010

Pila de Tecnologías para proyecto Web Java EE 6

Leí una vez en algún lugar, que decir que uno es programador de "Java" no dice realmente mucho. Es lo mismo que uno diga que sabe "programación". Esto es porque Java es mucho mas que un lenguaje de programación, de hecho la plataforma Java es un universo aparte, con cientos de estándares, especificaciones, plataformas, frameworks, librerías y convenciones.

Mientras mas complejo es el universo de Java, mas se necesita de especialización. El principal problema cuando uno inicia un proyecto Java es el seleccionar frameworks, IDE, build tool y librerías que se van a utilizar.

JSF o Seam?
Spring o EJB3?
JPA o Hibernate?
Eclipse o Netbeans?
Glassfish o Jboss?
Ant o Maven?

Nos encontramos con estas preguntas y necesitamos las respuestas. No creo que exista una respuesta correcta, ya que siempre va a depender de varios factores (requerimientos del software a desarrollar, conocimiento previo del equipo de desarrollo, imposición de cierta plataforma, etc).

De todas maneras, las opciones que uno elija van a tener incidencia en el proceso de desarrollo.

A continuación voy a detallar la pila tecnológica que yo creo es la mas adecuada para un proyecto nuevo en el que se va a desarrollar una aplicación Java web empresarial.

  • Capa de presentación: JSF 2.0 + Facelets + CDI 1.0 + PrimeFaces
  • Capa de lógica de negocios: EJB 3.1
  • Capa de persistencia: JPA 2.0
  • Validaciones: Bean Validation 1.0
  • Web Services: JAX-WS + JAX-RS
  • Reportes: JasperReports
  • Servidor de Aplicaciones: Glassfish V3
  • IDE: Netbeans 6.8
  • Build tool: Ant


La mayoría de estas tecnologías son estándares y forman parte de la plataforma Java EE 6.

Esta decisión es básicamente por dos motivos:

  1. Al utilizar una pila tecnológica de un mismo vendor, uno no pierde el tiempo en integrar varias tecnologías. Es el vendor el que se encarga de que todo se integre de la mejor manera y que la experiencia del desarrollador sea lo mas placentera posible.

  2. El uso de estándares maximiza las probabilidades de que el framework utilizado tenga una comunidad, vaya creciendo, mejorando y no se vuelva obsoleto. Además, nos da cierta garantía para migrar a otro vendor en el caso que necesitemos.


En los próximas entradas, voy a explicar el porque de cada tecnología, por ejemplo CDI Managed Beans y no JSF Managed Beans, etc.



Monday, January 4, 2010

La travesía de mil millas...

El gran filosofo y pensador chino Lao Tse dijo que una travesía de mil millas comienza con un paso. Hoy estamos dando el primer paso en el desarrollo de un sistema informático y para el mismo elegimos como plataforma Java Enterprise Edition 6.

Debido a que el proyecto es bastante grande y teniendo en cuenta que Java EE 6 es una plataforma relativamente nueva (Glassfish V3, la implementación de referencia y primera implementación fue lanzado el 10 de diciembre del 2009), me pareció interesante crear un blog para publicar mis experiencias, dudas, problemas y soluciones que surjan a partir de este desarrollo. Siempre respetando los acuerdos de confidencialidad con el cliente.

Las entradas voy a escribirlas en español debido a que es mi lengua materna. Como me dijo mi gran amigo Miguel, voy a sacrificar publico por claridad de ideas. Quizás si veo que a la gente le interesa lo que escribo, puedo mas adelante tener una versión en ingles.

Espero poder escribir con frecuencia y ojala que el contenido de este blog pueda servirle alguien que se encuentre en situaciones similares a las mías.