domingo, 5 de enero de 2014

- JSF 2.2 con migración de anotaciones de managed beans a anotaciones con CDI

En este tutorial describiré los pasos necesarios para realizar un proyecto JSF 2.2 con anotaciones de managed beans y luego como migrarlo a las anotaciones con CDI que ya es posible desde la versión 2.0 de JSF puesto que CDI es parte integral de Java EE 6 todo esto sin la herramienta de gestión y construcción MAVEN, lo cual quiere decir que obtendremos nosotros mismos las librerías necesarias para nuestros proyecto así como configuraremos nuestro entorno de desarrollo para que todos los componentes sean tomadas correctamente en nuestra aplicación. Ademas estamos usando anotaciones lo cual quiere decir que no configuraremos el comportamiento de nuestra aplicación a través del fichero faces-config.xml el cual eliminaremos.

Introducción a JSF

Es un framework MVC que simplifica principalmente la interacción de las interfaces con un usuario de cualquier tipo: Ordenador, PDA, Movil, etc etc en aplicaciones con tecnología JEE.  A traves de los Managed Bean se podrá interactuar con los eventos de los controles de la interfaz del cliente y poder enviarlas a las clases que se encuentran en el servidor de aplicaciones.




  1. Se realiza una petición a través de un cliente (Ordenador, Movil, PDA, etc etc).
  2. La petición es recibida por Contrlador que en este caso es "Faces Servlet"
  3. El Faces Servlet según la petición del cliente invocara el JSP, JSF, XHTML (Vista) que visualizará posteriormente el cliente.
  4. El Faces Servlet o el JSF invocará al Managed Bean (Modelo) para realizar la lógica necesaria para mostrar los datos que se necesiten en el JSP, JSF, XHTML.
  5. El Managed Bean podrá realizar la lógica necesaria ya sea interactuando con EJB, Spring, Hibernate etc etc, y asi obtener los datos necesarios para poder realizar su trabajo que es el de obtener los datos para poder mostrarlos en la página.
  6. Posteriormente el JSP o JSF es devuelto al cliente con la data requerida para poder ser utilizado.

Proyecto en JSF 2.2

  1. Eclipse Kepler
  2. JBoss 7.1.1
Como indiqué anteriormente no explicaré como se realiza la instalación del Eclipse con su respectivo JDK ni el  JBOSS por lo que se asume que ya tenéis el entorno instalado.

Primero que todo creamos un proyecto WEB en el eclipse: File -> New -> Dynamic Web Project

  1. Project Name: ProyectoJSFTutorial
  2. Target runtime: JBoss 7.1 Runtime
  3. Dynamic web module version: 3.0
  4. Configuration: JavaServer Faces v2.2 Project
Tal como se muestra: 



Damos click en Finish y se habrá creado nuestro proyecto.
Por ahora como vamos a usar anotaciones en nuestros Managed Beans y no vamos a realizar ningun tipo de reglas en la navegación ya que nosotros controlaremos ello desde los ManagedBean eliminaremos el xml faces-config.xml:
eliminar /ProyectoJSFTutorial/WebContent/WEB-INF/faces-config.xml.
Ahora configuramos nuestro descriptor de despliegue que si lo abrís debe estar ya configurado con los Faces Servlet(Controlador) pero agregaremos una entrada para indicar que nuestra página inicial será index.xhtml que posteriormente crearemos.y deberá quedar de la siguiente forma.

/ProyectoJSFTutorial/WebContent/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>ProyectoJSFTutorial</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>faces/index.xhtml</welcome-file>
  </welcome-file-list>
</web-app>

Ahora creamos los componentes necesarios para nuestro proyecto:
En /ProyectoJSFTutorial/src creamos los paquetes

  1. com.victor.elliott.humala.controladores
  2. com.victor.elliott.humala.dao
  3. com.victor.elliott.humala.formulario
Luego creamos las siguientes clases en los paquetes respectivos

    1. com.victor.elliott.humala.controladores -> ComponenteControlador.java
    2. com.victor.elliott.humala.controladores -> UsuarioControlador.java
    3. com.victor.elliott.humala.dao -> ComponenteDAO.java
    4. com.victor.elliott.humala.dao -> ComponenteDAOImpl.java
    5. com.victor.elliott.humala.formulario -> ComponenteForm.java
    6. com.victor.elliott.humala.formulario -> UsuarioForm.java
    Una vez creadas las clases creamos las paginas y css respectivos.

    1. Creamos primero que todo las carpetas pages y resources en /ProyectoJSFTutorial/WebContent/
    2. Creamos la carpeta css en /ProyectoJSFTutorial/WebContent/resources
    3. Creamos index.xhtml en /ProyectoJSFTutorial/WebContent
    4. Creamos login.xhtml en /ProyectoJSFTutorial/WebContent/pages
    5. Creamos agregarComponentes.xhtml en /ProyectoJSFTutorial/WebContent/pages
    6. Creamos mostrarComponentes.xhtml en /ProyectoJSFTutorial/WebContent/pages
    7. Creamos estiloTabla.css en /ProyectoJSFTutorial/WebContent/resources/css
    Una vez creadas nuestras clases, paginas y componentes que usaremos, la estructura de proyecto debe de quedar de la siguiente manera:


    Ahora si podemos empezar a codificar nuestro proyecto, Hay que tener en cuenta que las librerías de JSF 2.2 ya están embebidas dentro del RunTime de JBoss asi que no sera necesario descargar ninguna librería. 

    Primero que todo modificamos com.victor.elliott.humala.formulario.UsuarioForm que básicamente contendrá los atributos nombre y clave sus getter y setter respectivos y dos constructores.

    /ProyectoJSFTutorial/src/com/victor/elliott/humala/formulario/UsuarioForm.java

    package com.victor.elliott.humala.formulario;
    
    public class UsuarioForm{
    
     private String nombre;
     private String clave;
     
     
     public UsuarioForm(){
      this.nombre = "";
      this.clave = "";
     }
     public UsuarioForm(String nombre, String clave){
      this.nombre = nombre;
      this.clave = clave;
     }
     public String getNombre() {
      return nombre;
     }
     public void setNombre(String nombre) {
      this.nombre = nombre;
     }
     public String getClave() {
      return clave;
     }
     public void setClave(String clave) {
      this.clave = clave;
     }
    }
    

    Ahora modificamos
    /ProyectoJSFTutorial/src/com/victor/elliott/humala/controladores/UsuarioControlador.java

    package com.victor.elliott.humala.controladores;
    
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.SessionScoped;
    import com.victor.elliott.humala.formulario.UsuarioForm;
    
    @ManagedBean
    @SessionScoped
    public class UsuarioControlador {
     private UsuarioForm usuario=new UsuarioForm("Victor", "Elliott");
     private UsuarioForm usuarioForm=new UsuarioForm();
     private String error;
     private String mensaje;
     
     public String verificarUsuario() {
      System.out.println("Entro a verificarUsuario");
      if(usuario.getNombre().equals(usuarioForm.getNombre())&&usuario.getClave().equals(usuarioForm.getClave())){
       mensaje= "Usuario Correcto: "+usuarioForm.getNombre();
       return "agregarComponentes";   
      }
      else if("".equals(usuarioForm.getNombre())||"".equals(usuarioForm.getClave())){
       error="Los datos del usuario no pueden estar vacios";
       return "login";
      }
      else{
       error="El usuario no está registrado en el sistema";
       return "login";
      }
     }
     public UsuarioForm getUsuarioForm() {
      return usuarioForm;
     }
     public void setUsuarioForm(UsuarioForm usuarioForm) {
      this.usuarioForm = usuarioForm;
     }
     public String getError() {
      return error;
     }
     public void setError(String error) {
      this.error = error;
     }
     public String getMensaje() {
      return mensaje;
     }
     public void setMensaje(String mensaje) {
      this.mensaje = mensaje;
     }
    }
    


    1. Todos los import javax.faces son necesarios para la implementacion del ManagedBean
    2. Indicamos la anotación @ManagedBean para hacerle saber a la aplicación que se trata de un elemento de modelo que se encargará de gestionar los datos de las paginas que lo necesiten. Tener en cuenta que normalmente se usaría @ManagedBean(name="nombredelBean") pero al no ponerle el nombre automáticamente coge el nombre de la clase y le coloca la minúscula inicialmente es decir que @ManagedBean = @ManagedBean(name="usuarioControlador")
    3. Indicamos la anotación @SessionScoped para indicarle a la aplicación que se trata de un ManagedBean de session es decir que persistirá hasta que se termine la sesión o se cierre el browser que está utilizando el cliente. Hacemos esto por que luego recuperaremos el nombre del usuario el cual necesitamos que persista. Existen otros tipos pero los mas importantes son @SessionScoped (persistencia en la sesión), @RequestScoped (persistencia durante el request), @ApplicationScoped (persistencia durante toda la aplicación, hasta que se para el servidor) y @Viewscoped (persistencia durante la vista, usada normalmente para peticiones AJAX)
    4. Declaramos UsuarioForm usuario para determinar cual será el único usuario con el que se podrá ingresar al sistema.
    5. Declaramos UsuarioForm usuarioForm=new UsuarioForm() con sus respectivos getter y setter puesto que será un objeto que interactuará con nuestras paginas y tenemos que inicializarlo con el constructor para que en un principio sus datos aparezcan vacíos y no haya errores de nullpointer.
    6. Los atributos error y mensaje con sus respectivos getter y setter son declarados para enviar el mensaje respectvio a la pagina en caso de error y/o éxito.
    7. Creamos el método verificarUsuario que validará los datos ingresados del usuario y en caso de exito retornare la página a la cual me dirigiré "agregarComponentes" que la aplicación interpretará como agregarComponentes.xhtml con su respectivo mensaje de éxito y en caso de error volveré a la misma página "login" que la aplicación interpretará como "login.xhtml" con su respectivo mensaje de error.
    Ahora modifiquemos las páginas:
    /ProyectoJSFTutorial/WebContent/index.xhtml

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <meta http-equiv="Refresh" content= "0; URL=faces/pages/login.xhtml"/>
    

    Donde básicamente le indicamos al index.xhtml que es nuestra página inicial que se dirija a la página principal login.xhtml a través de la etiqueta META.


    • /ProyectoJSFTutorial/WebContent/pages/login.xhtml


    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:h="http://java.sun.com/jsf/html"
     xmlns:f="http://java.sun.com/jsf/core">
    
    <h:head>
     <title>Tutorial JSF by Victor Elliott Humala</title>
    </h:head>
    <h:body>
     <h:outputText style="color:red" value="#{usuarioControlador.error}" />
     <h:form>
      <h:panelGrid columns="2">
       <h:outputLabel value="Nombre" for="nombre" />
       <h:inputText value="#{usuarioControlador.usuarioForm.nombre}" id="nombre" />
       <h:outputLabel value="Clave" for="clave" />
       <h:inputText value="#{usuarioControlador.usuarioForm.clave}" id="clave" />   
       <h:commandButton value="Ingresar" action="#{usuarioControlador.verificarUsuario}"/>
      </h:panelGrid>
     </h:form>
    </h:body>
    </html>
    

    1. Declaramos la librería para nuestros tags de jsf (:ui, :h y :f)
    2. Mostramos en rojo el error usuarioControlador.error en caso que exista.
    3. Finalmente agregamos un form con los tag de jsf para que puedas llenarse los datos necesarios del usuario (usuarioForm) y al hacer submit vaya al action respectivo usuarioControlador.verificarUsuario.

    • /ProyectoJSFTutorial/WebContent/pages/agregarComponentes.xhtml


    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:h="http://java.sun.com/jsf/html"
     xmlns:f="http://java.sun.com/jsf/core">
    
    <h:head>
     <title>Tutorial JSF by Victor Elliott Humala</title>
    </h:head>
    <h:body>
     <h4><h:outputText style="color:blue" value="#{usuarioControlador.mensaje}" /></h4>
    </h:body>
    </html>
    

    Ahora ya estamos listos para ejecutar nuestro proyecto en el servidor JBoss, antes de ello verificar que no haya ningún error de compilación y una vez ejecutado en el servidor ningún error de ejecución. Si todo esta bien podrán visualizar las siguientes páginas:




    Ahora continuo con la segunda parte del tutorial.
    Una vez que ya tenemos el login realizado, nos disponemos a crear una lista de componentes que cargaremos una a una para luego poder verlas todas juntas.

    /ProyectoJSFTutorial/src/com/victor/elliott/humala/formulario/ComponenteForm.java

    package com.victor.elliott.humala.formulario;
    
    public class ComponenteForm {
     private String nombre;
     private String version;
     private String tipo;
     private String extension;
     
     public String getNombre() {
      return nombre;
     }
     public void setNombre(String nombre) {
      this.nombre = nombre;
     }
     public String getVersion() {
      return version;
     }
     public void setVersion(String version) {
      this.version = version;
     }
     public String getTipo() {
      return tipo;
     }
     public void setTipo(String tipo) {
      this.tipo = tipo;
     }
     public String getExtension() {
      return extension;
     }
     public void setExtension(String extension) {
      this.extension = extension;
     }
    
    }
    
    Clase que contiene todos los datos que deseo guardar de un componente. Finalmente modifico los action:
    /ProyectoJSFTutorial/src/com/victor/elliott/humala/dao/ComponenteDAO.java

    package com.victor.elliott.humala.dao;
    
    import com.victor.elliott.humala.formulario.ComponenteForm;
    import java.util.List;
    
    public interface ComponenteDAO {
     public void addComponente(ComponenteForm componente);
     public List<ComponenteForm> getComponente();
    }
    

    Aqui simplemente estamos creando un DAO de tipo Interface donde solo declaramos dos métodos addComponente para agregar el componente y getComponente para recuperar todos los componentes.
    Ahora creamos su implementación respectiva modificando:

    /ProyectoJSFTutorial/src/com/victor/elliott/humala/dao/ComponenteDAOImpl.java

    package com.victor.elliott.humala.dao;
    
    import java.util.ArrayList;
    import java.util.List;
    import com.victor.elliott.humala.formulario.ComponenteForm;
    
    public class ComponenteDAOImpl implements ComponenteDAO {
     private static List<ComponenteForm> listaComponentes=new ArrayList<ComponenteForm>();
     @Override
     public void addComponente(ComponenteForm componente) {
      listaComponentes.add(componente);
     }
    
     @Override
     public List<ComponenteForm> getComponente() {
      return listaComponentes;
     }
    }
    

    De esta forma implementamos los métodos de la interface primero declarando un atributo estático List<ComponenteForm> listaComponentes que me guardará todos los datos que ingrese en mi lista y no se perderá y luego con los metodos addComponente agrego un componente a la lista y con getComponente recupero toda la lista estática.
    Modificamos:

    /ProyectoJSFTutorial/src/com/victor/elliott/humala/controladores/ComponenteControlador.java

    package com.victor.elliott.humala.controladores;
    
    import java.util.List;
    
    import javax.annotation.PostConstruct;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.ManagedProperty;
    import javax.faces.bean.RequestScoped;
    
    import com.victor.elliott.humala.dao.ComponenteDAO;
    import com.victor.elliott.humala.dao.ComponenteDAOImpl;
    import com.victor.elliott.humala.formulario.ComponenteForm;
    
    @ManagedBean
    @RequestScoped
    public class ComponenteControlador {
     private ComponenteForm componenteForm=new ComponenteForm();
     private ComponenteDAO componenteDAO= new ComponenteDAOImpl();
     private List<ComponenteForm> componenteLista;
     @ManagedProperty("#{usuarioControlador}")
     private UsuarioControlador usuarioControlador;
     private String error;
     private String mensaje;
     
     @PostConstruct
     public void init(){
      mensaje= usuarioControlador.getMensaje();
     }
     public String registrarComponente() {
      if("".equals(componenteForm.getNombre())||"".equals(componenteForm.getTipo())||"".equals(componenteForm.getVersion())||"".equals(componenteForm.getExtension())){
       error="Los datos del componente no pueden estar vacios";
       return "agregarComponentes";
      }
      else{
       componenteDAO.addComponente(componenteForm);
       System.out.println("Componente guardado");
       componenteLista=componenteDAO.getComponente();
       System.out.println("Obtiene la lista");
       return "mostrarComponentes";
      }
     }
     
     public String volverComponente() {
      System.out.println("Volver Componente");
      return "agregarComponentes";
     }
     public ComponenteForm getComponenteForm() {
      return componenteForm;
     }
     public void setComponenteForm(ComponenteForm componenteForm) {
      this.componenteForm = componenteForm;
     }
    
     public UsuarioControlador getUsuarioControlador() {
      return usuarioControlador;
     }
     public void setUsuarioControlador(UsuarioControlador usuarioControlador) {
      this.usuarioControlador = usuarioControlador;
     }
     public List<ComponenteForm> getComponenteLista() {
      return componenteLista;
     }
     public void setComponenteLista(List<ComponenteForm> componenteLista) {
      this.componenteLista = componenteLista;
     }
     public String getError() {
      return error;
     }
     public void setError(String error) {
      this.error = error;
     }
     public String getMensaje() {
      return mensaje;
     }
     public void setMensaje(String mensaje) {
      this.mensaje = mensaje;
     }
    }
    

    1. Todos los import javax.faces son necesarios para la implementacion del ManagedBean
    2. Indicamos la anotación @ManagedBean para hacerle saber a la aplicación que se trata de un elemento de modelo que se encargará de gestionar los datos de las paginas que lo necesiten. Tener en cuenta que normalmente se usaría @ManagedBean(name="nombredelBean") pero al no ponerle el nombre automáticamente coge el nombre de la clase y le coloca la minúscula inicialmente es decir que @ManagedBean = @ManagedBean(name="usuarioControlador")
    3. Indicamos la anotación @RequestScoped para indicarle a la aplicación que se trata de un ManagedBean de request es decir que persistirá hasta que se termine el request y ante un nuevo request se creará otro. Hacemos esto por que los datos del componente solo se utilizarán para guardarlos y luego no me interesa que persista. Existen otros tipos pero los mas importantes son @SessionScoped (persistencia en la sesión), @RequestScoped (persistencia durante el request), @ApplicationScoped (persistencia durante toda la aplicación, hasta que se para el servidor) y @Viewscoped (persistencia durante la vista, usada normalmente para peticiones AJAX)
    4. Declaramos ComponenteForm componenteForm=new ComponenteForm() con sus respectivos getter y setter puesto que será un objeto que interactuará con nuestras paginas y tenemos que inicializarlo con el constructor para que en un principio sus datos aparezcan vacíos y no haya errores de nullpointer.
    5. Declaramos ComponenteDAO componenteDAO que se encargará de gestionar mi lista de componentes y hacer que persista.
    6. Declaramos la lista private List<ComponenteForm> componenteLista con sus respectivos getter y setter para poder interactuar con la página que mostrará la lista de componentes.
    7. Con la anotación @ManagedProperty("#{usuarioControlador}") estamos indicando que vamos a recuperar el ManagedBean usuarioControlador (recordais que era de session por lo que las propiedades que contiene deberían persistir) y asignarselo a la propiedad usuarioControlador que deberá tener sus respectivos getter y setter, si no los ponen tendrán un error a la hora de deployar.
    8. Los atributos error y mensaje con sus respectivos getter y setter son declarados para enviar el mensaje respectivo a la pagina en caso de error y/o éxito.
    9. La anotación @PostConstruct me sirve para determinar algunos valores antes que se invoque a la clase a través del método init donde lo único que hacemos es llenar el mensaje que aparecerá al inicio de los componentes. Si no hacemos esto el mensaje aparecerá vacio puesto que no se habrá invocado a ningun metodo inicialmente para tener el mensaje definido.
    10. Creamos el método registrarComponente que validará los datos ingresados del componente y en caso de exito guardaré el componente en la lista y luego recuperare la lista con el DAO, luego retornare la página a la cual me dirigiré "mostrarComponentes" que la aplicación interpretará como mostrarComponentes.xhtml y en caso de error volveré a la misma página "agregarComponentes" que la aplicación interpretará como "agregarComponentes.xhtml" con su respectivo mensaje de error.
    11. Creamos el método volverComponente que lo único que hará será ir a la página agregarComponentes.xhtml a traves del return "agregarComponentes".
    Modificamos ahora las páginas:
    /ProyectoJSFTutorial/WebContent/pages/agregarComponentes.xhtml

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:h="http://java.sun.com/jsf/html"
     xmlns:f="http://java.sun.com/jsf/core">
    
    <h:head>
     <title>Tutorial JSF by Victor Elliott Humala</title>
    </h:head>
    <h:body>
     <h4><h:outputText style="color:blue" value="#{componenteControlador.mensaje}" /></h4> 
     <h2><h:outputText style="color:black" value="Agregar Componente" /></h2>
     <h4><h:outputText style="color:red" value="#{componenteControlador.error}" /></h4>
     <h:form>
      <h:panelGrid columns="2">
       <h:outputLabel value="Nombre" for="nombre" />
       <h:inputText value="#{componenteControlador.componenteForm.nombre}" id="nombre" />
       <h:outputLabel value="Version" for="version" />
       <h:inputText value="#{componenteControlador.componenteForm.version}" id="version" /> 
       <h:outputLabel value="Tipo" for="tipo" />
       <h:inputText value="#{componenteControlador.componenteForm.tipo}" id="tipo" />   
       <h:outputLabel value="Extension" for="extension" />
       <h:inputText value="#{componenteControlador.componenteForm.extension}" id="extension" />    
      </h:panelGrid>
      <h:commandButton value="Agregar" action="#{componenteControlador.registrarComponente}"/>
     </h:form>
    </h:body>
    </html>
    

    1. En esta página mostraremos la bienvenida al usuario donde al hacer #{componenteControlador.mensaje} con sus respectivos tags de jsf 
    2. Con #{componenteControlador.error} mostramos los errores en el caso que existan de color rojo.
    3. Finalmente agregamos un formulario para que puedan llenarse los datos necesarios del componente a registrar (componenteForm) y al hacer submit vaya al action respectivo #{componenteControlador.registrarComponente que posteriormente me enviará a la página respectiva de error o éxito según los datos ingresados.
    Modificamos:
    /ProyectoJSFTutorial/WebContent/resources/css/estiloTabla.css

    .componenteTable{   
     border-collapse:collapse;
     border:1px solid #000000;
    }
     
    .componenteTableHeader{
     text-align:center;
     background:none repeat scroll 0 0 orange;
     border-bottom:1px solid #BBBBBB;
     padding:16px;
    }
     
    .componenteTableOddRow{
     text-align:center;
     background:none repeat scroll 0 0 #FFFFFFF;
     border-top:1px solid #BBBBBB;
    }
     
    .componenteTableEvenRow{
     text-align:center;
     background:none repeat scroll 0 0 #F9F9F9;
     border-top:1px solid #BBBBBB;
    }
    

    Que nos servirá para darle formato a nuestras tablas. Tener en cuenta que con los tags de jsf es mas facil definir css's para dar formato a algunos objeto como las tablas que darles formato directamente con el style.
    Normalmente los ficheros css que definamos en las páginas se buscarán dentro de la carpeta WebContent/resource/css motivo por el cual las incluimos en la estructura del proyecto.

    Finalmente creamos nuestra página para visualizar la lista de componentes:

    /ProyectoJSFTutorial/WebContent/pages/mostrarComponentes.xhtml

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:h="http://java.sun.com/jsf/html"
     xmlns:f="http://java.sun.com/jsf/core">
    
    <h:head>
     <h:outputStylesheet library="css" name="estiloTabla.css"  />
     <title>Tutorial JSF by Victor Elliott Humala</title>
    </h:head>
    <h:body>
    <h2>Lista de componentes</h2>
     <h:dataTable value="#{componenteControlador.componenteLista}" var="componente" 
      styleClass="componenteTable"
           headerClass="componenteTableHeader"
           rowClasses="componenteTableOddRow,componenteTableEvenRow">
    
      <h:column>
       <!-- column header -->
       <f:facet name="header">Nombre</f:facet>
            #{componente.nombre}
         </h:column>
      <h:column>
       <f:facet name="header">Tipo</f:facet>
            #{componente.tipo}
         </h:column>
      <h:column>
       <f:facet name="header">Version</f:facet>
            #{componente.version}
         </h:column>
      <h:column>
       <f:facet name="header">Extensión</f:facet>
            #{componente.extension}
         </h:column>
     </h:dataTable>
     <h:form><h:commandLink value="Agregar otro componente" action="#{componenteControlador.volverComponente}" /></h:form>
    </h:body>
    </html>
    

    1. Indicamos que vamos a usar los estilos del css: estiloTabla.css que como indiqué tienen que ser ubicados en: WebContent/resource/css
    2. Definimos la tabla a usar con sus respectivos estilos.
    3. Nos recorremos la lista #{componenteControlador.componenteLista} y pintamos los datos respectivos
    4. Creamos una referencia h:commandLink para poder volver al Action: #{componenteControlador.volverComponente}. Tener en cuenta que que solo nos redirigirá a una página y debe estar dentro de un form asi no haya datos para ingresar. Existen otras opciones para poder hacer esto si utilizar h:commandLink pero lo uso por que me resulta interesante este tipo de botón por que si quisiera podría hacer otras cosas antes de ir a la página que deseo, por lo pronto servirá para nuestro objetivo final.
    Si has compilado todo bien y no hay problemas de ejecución te deberían salir las siguientes páginas después del Login y después de haber agregado varios componentes.




    Ahora migraremos nuestra aplicación JSF 2.2 creada con anotaciones de ManageBean por anotaciones e inyecciones de CDI (Contexts and Dependency Injection).

    Proyecto en JSF 2.2 con CDI

    Primero que todo creamos un proyecto WEB en el eclipse: File -> New -> Dynamic Web Project
    1. Project Name: ProyectoJSF-CDI-Tutorial
    2. Target runtime: JBoss 7.1 Runtime
    3. Dynamic web module version: 3.0
    4. Configuration: JavaServer Faces v2.2 Project
    Tal como se muestra:


    Damos click en Modify en Configuration: y seleccionamos CDI 1.0 tal como se muestra en la pantalla:


    Damos click en Ok y en Finish

    Veremos que a diferencia del proyecto anterior se ha creado un nuevo fichero de configuración en WEB-INF llamado beans.xml, este fichero a pesar de que no lo vamos a utilizar en este tutorial no podemos borrarlo por que es un componente imprescindible en CDI, sin embargo faces-config.xml si lo eliminaremos por que no crearemos reglas de navegación ya que lo haremos manualmente y con anotaciones dentro de nuestros ManagedBeans.

    Ahora como el propósito es migrar la aplicación a CDI, primero que todo copiamos todas las clases con sus paquetes respectivos y páginas xhtml, asi como el css asociado en nuestro nuevo proyecto. Ademas no olviden modificar el descriptor de depliegue para indicar que nuestra página inicial será index.xhtml y deberá de quedar de la siguiente manera:

    /ProyectoJSFTutorial/WebContent/WEB-INF/web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
      <display-name>ProyectoJSF-CDI-Tutorial</display-name>
      <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
      </servlet-mapping>
      <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
      </welcome-file-list>
    </web-app>
    


     Finalmente la estructura del proyecto deberá quedar de la siguiente forma:


    Para verificar que vamos a empezar bien la migración ejecutemos nuestra aplicación y debe de funcionar exactamente como la anterior. Una vez hayan comprobado que todo va correctamente nos dispondremos a modificar los controladores (ManagedBean) que finalmente será lo único que que modificaremos para este tipo de migración:

    La clase UsuarioControlador:

    1. Tendremos que reemplazar import javax.faces.bean.SessionScoped; por import javax.enterprise.context.SessionScoped;
    2. Reemplazar @ManagedBean por @Named eliminando import javax.faces.bean.ManagedBean; e importando: import javax.inject.Named;
    3. Como ahora la anotación @SessionScoped proviene de javax.enterprise ese necesita que la clase sea serializable por lo que hacemos el implement respectivo UsuarioControlador implements Serializable.
    Para este controlador es lo único que necesitamos cambiar, al final deberá quedar:

    /ProyectoJSF-CDI-Tutorial/src/com/victor/elliott/humala/controladores/UsuarioControlador.java

    package com.victor.elliott.humala.controladores;
    
    import java.io.Serializable;
    import javax.enterprise.context.SessionScoped;
    import javax.inject.Named;
    
    import com.victor.elliott.humala.formulario.UsuarioForm;
    
    @Named
    @SessionScoped
    public class UsuarioControlador implements Serializable{
     private static final long serialVersionUID = 1L;
     private UsuarioForm usuario=new UsuarioForm("Victor", "Elliott");
     private UsuarioForm usuarioForm=new UsuarioForm();
     private String error;
     private String mensaje;
     
     public String verificarUsuario() {
      System.out.println("Entro a verificarUsuario");
      if(usuario.getNombre().equals(usuarioForm.getNombre())&&usuario.getClave().equals(usuarioForm.getClave())){
       mensaje= "Usuario Correcto: "+usuarioForm.getNombre();
       return "agregarComponentes";   
      }
      else if("".equals(usuarioForm.getNombre())||"".equals(usuarioForm.getClave())){
       error="Los datos del usuario no pueden estar vacios";
       return "login";
      }
      else{
       error="El usuario no está registrado en el sistema";
       return "login";
      }
     }
     public UsuarioForm getUsuarioForm() {
      return usuarioForm;
     }
     public void setUsuarioForm(UsuarioForm usuarioForm) {
      this.usuarioForm = usuarioForm;
     }
     public String getError() {
      return error;
     }
     public void setError(String error) {
      this.error = error;
     }
     public String getMensaje() {
      return mensaje;
     }
     public void setMensaje(String mensaje) {
      this.mensaje = mensaje;
     }
    }
    

    Modificamos la clase ComponenteControlador
    1. Tendremos que reemplazar import javax.faces.bean.RequestScoped; por import javax.enterprise.context.RequestScoped;
    2. Reemplazar @ManagedBean por @Named eliminando import javax.faces.bean.ManagedBean; e importando: import javax.inject.Named;
    3. Reemplazar @ManagedProperty("#{usuarioControlador}") por simplemente @Inject eliminando los getter y setter de private UsuarioControlador usuarioControlador que ya no serán necesarios para esta aplicación. En consecuencia eliminar el import import javax.faces.bean.ManagedProperty; e importar import javax.inject.Inject;
    Al final deberá quedar:
    /ProyectoJSF-CDI-Tutorial/src/com/victor/elliott/humala/controladores/ComponenteControlador.java


    package com.victor.elliott.humala.controladores;
    
    import java.util.List;
    
    import javax.annotation.PostConstruct;
    import javax.enterprise.context.RequestScoped;
    
    import javax.inject.Inject;
    import javax.inject.Named;
    
    import com.victor.elliott.humala.dao.ComponenteDAO;
    import com.victor.elliott.humala.dao.ComponenteDAOImpl;
    import com.victor.elliott.humala.formulario.ComponenteForm;
    
    @Named
    @RequestScoped
    public class ComponenteControlador {
     private ComponenteForm componenteForm=new ComponenteForm();
     private ComponenteDAO componenteDAO= new ComponenteDAOImpl();
     private List<ComponenteForm> componenteLista;
     @Inject
     private UsuarioControlador usuarioControlador;
     private String error;
     private String mensaje;
     
     @PostConstruct
     public void init(){
      mensaje= usuarioControlador.getMensaje();
     }
     public String registrarComponente() {
      if("".equals(componenteForm.getNombre())||"".equals(componenteForm.getTipo())||"".equals(componenteForm.getVersion())||"".equals(componenteForm.getExtension())){
       error="Los datos del componente no pueden estar vacios";
       return "agregarComponentes";
      }
      else{
       componenteDAO.addComponente(componenteForm);
       System.out.println("Componente guardado");
       componenteLista=componenteDAO.getComponente();
       System.out.println("Obtiene la lista");
       return "mostrarComponentes";
      }
     }
     
     public String volverComponente() {
      System.out.println("Volver Componente");
      return "agregarComponentes";
     }
     public ComponenteForm getComponenteForm() {
      return componenteForm;
     }
     public void setComponenteForm(ComponenteForm componenteForm) {
      this.componenteForm = componenteForm;
     }
     public List<ComponenteForm> getComponenteLista() {
      return componenteLista;
     }
     public void setComponenteLista(List<ComponenteForm> componenteLista) {
      this.componenteLista = componenteLista;
     }
     public String getError() {
      return error;
     }
     public void setError(String error) {
      this.error = error;
     }
     public String getMensaje() {
      return mensaje;
     }
     public void setMensaje(String mensaje) {
      this.mensaje = mensaje;
     }
    }
    

    Ahora cuando deployen el proyecto verán en los log que a diferencia del anterior proyecto sin CDI aparecerá: Starting Services for CDI deployment: ProyectoJSF-CDI-Tutorial.war

    Ahora cuando ejecutemos el proyecto deberá funcionar perfectamente como en el caso anterior.

    El código de los proyecto os lo podéis bajar del siguiente link

    ProyectosJSFTutorial

    2 comentarios:

    1. Hola. En caso de en jsf2 estar usando la anotación "ViewScoped". Cuando hago la migración a CDI ¿Cuál sería el import que debo usar? Pues, en el paquete "javax.enterprise.context" no la encontré.

      Muchas gracias por el tutorial, está muy completo y bien explicado :D

      ResponderEliminar
    2. import javax.faces.bean.ViewScoped;

      ResponderEliminar