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.