Ejemplo. Uso de JSF en Netbeans

FJRP - CCIA-2011


Date: Septiembre-2011



Índice General

Crear el proyecto

  1. Crear un nuevo proyecto Java Web
    New Project -> Java Web -> Web Application
         	Project Name: EjemploJSF
         	Use dedicated folder for storing libraries: ./lib
    
         	Add to Enterprise Application: <none> 
         	Server: GlassFish 3.1.1
         	Java EE version: Java EE 6 web
         	Context path: EjemploJSF
    
         	Seleccionar en Frameworks "Java Server Faces"
         	Server Library: JSF 2.0
         	Configuration -> Prefered Page Language: Facelets
         	Components -> Components Suite: Primefaces (opcional, por si se quiere probar Primefaces)
    

    En Configuration Files se habrá creado un fichero web.xml, que es el descriptor de despliegue de la aplicación web Java EE.

Conexión con Base de Datos

  1. Configurar un pool de conexiones en GlassFish y un recurso JDBC

          
    New File -> Other -> GlassFish -> JDBC connection pool
         	Nombre: pool-ejemploJSF
         	New Configuration using Database: JavaDB(net) 
    
         	Datasource Classname: org.apache.derby.jdbc.ClientDataSource
         	URL: jdbc:derby://localhost:1527/sample
         	serverName: localhost
         	portNumber: 1527
         	databaseName: sample
         	user: app
         	password: app
    

    New File->GlassFish->JDBC resource
         	Use Existing JDBC Connection Pool: pool-ejemploJSF
         	JNDI name: jdbc/ejemploJSF-datasource
    

    En Server Resources se habrá creado un fichero glassfish-resources.xml con la definición del pool de conexiones y del Datasource.

  2. Crear una unidad de persistencia JPA (PersistenceUnit)

    New File -> Persitence -> PersistenceUnit
         	 PersistenceUnit name: EjemploJSF-PU
         	 Persistence Provider: EclipseLink
         	 Datasource: jdbc/ejemploJSF-datasource
         	 Marcar: Use Java Transaction API y Table generation strategy=Create
    

    En Configuration Files se habrá creado un fichero persistence.xml con la definición de la Persistence Unit

  3. Crear las entidades JPA a partir de la base de datos

    New File -> Persistence -> Entity Classes from Database
         	Datasource: jdbc/ejemploJSF-datasource
         	'Avalilable tables': seleccionarlas TODAS (auque sólo trabajaremos con CUSTOMER  y PURCHASE_ORDER)
    
         	Class Names: dejar como está (pueden traducirse los nombres de las clases, 
                                          pero habría que cambiar el código proporcionado más adelante)
         	Package:entidades
         	(puede desmarcarse ''Generate JAXB anotations'')
    
         	Collection type: java.util.List
         	Desmarcar 'Use Column Names in Relationships'
    

    En Configuration Files $ \to$ Source Packages $ \to$ entidades se habrán creado las entidades JPA con sus correspondientes anotaciones (se incluyen anotaciones JAXB para mapeo a XML).

Implementación de la lógica de la aplicación

  1. Crear los EJB locales que implementen los DAOs para Customer y PurchaseOrder

    New File -> Enterprise JavaBeans-> Session Bean
         	EJB name: CustomerDAO
         	Package: daos
         	Session type: Stateless
         	No indicar tipo de interfaz (será local por defecto)
    

    New File -> Enterprise JavaBeans -> Session Bean
         	EJB name: PurchaseOrderDAO
         	Package: daos
         	Session type: Stateless
         	No indicar tipo de interfaz (será local por defecto)
    

    En Configuration Files $ \to$ Source Packages $ \to$ daos se habrán creado las clases de los dos EJBs sin estado.

    Copiar las implementaciones de los métodos siguientes:

    package daos;
    
    import javax.ejb.LocalBean;
    import javax.ejb.Stateless;
    
    import entidades.Customer;
    import entidades.DiscountCode;
    import java.util.List;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.persistence.Query;
    
    
    @Stateless
    @LocalBean
    public class CustomerDAO {
    
        @PersistenceContext
        EntityManager em;
    
        public void crear(Customer cliente) {
            em.persist(cliente);
        }
    
        public void actualizar(Customer cliente) {
            em.merge(cliente);
        }
    
        public void borrar(Customer cliente) {
            em.remove(cliente);
        }
    
        public Customer buscarPorID(Long id) {
            return (em.find(Customer.class, id));
        }
    
        public List<Customer> buscarTodos() {
            Query q = em.createQuery("SELECT c FROM Customer c");
            return q.getResultList();
        }
    
        public List<Customer> buscarPorNombre(String nombre) {
            Query q = em.createQuery("SELECT c FROM Customer c WHERE c.name LIKE :patron");
    
            q.setParameter("patron", "%" + nombre + "%");
            return q.getResultList();
        }
    
    
        public List<DiscountCode> listaCodigosDescuento(){
             Query q = em.createQuery("SELECT cd FROM  DiscountCode cd");
            return q.getResultList();
        }
    }
    

    package daos;
    
    import javax.ejb.LocalBean;
    import javax.ejb.Stateless;
    
    import entidades.PurchaseOrder;
    import java.util.List;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.persistence.Query;
    
    
    @Stateless
    @LocalBean
    public class PurchaseOrderDAO {
        
        @PersistenceContext
        EntityManager em;
    
        public void crear(PurchaseOrder pedido) {
            em.persist(pedido);
        }
    
        public void actualizar(PurchaseOrder pedido) {
            em.merge(pedido);
        }
    
        public void borrar(PurchaseOrder pedido) {
            em.remove(pedido);
        }
    
        public PurchaseOrder buscarPorID(Long id) {
            return (em.find(PurchaseOrder.class, id));
        }
    
        public List<PurchaseOrder> buscarTodos() {
            Query q = em.createQuery("SELECT p FROM PurchaseOrder p");
            return q.getResultList();
        }
    
        public List<PurchaseOrder> buscarPorCliente(Integer idCliente) {
            Query q = em.createQuery("SELECT p FROM PurchaseOrder p WHERE p.customer.customerId = :idCliente");
    
            q.setParameter("idCliente", idCliente);
            return q.getResultList();
        }
     
    }
    

    Importante: Si se usa la opción Source $ \to$ Fix Imports para insertar los imports automáticamente, asegurar que los imports que se realizan son los correctos.

    En concreto, para la clase Query, debe ser import import javax.persistence.Query;

Ficheros resultantes:

Presentación con JSF

Se crearán 3 formularios.

Managed Beans

Se creará un único @ManagedBean para dar soporte a las vistas anteriores.

  1. Crear el @ManagedBean EjemploJSFController
    New File -> Java Server Faces -> JSF Managed Bean
         	Class Name: EjemploController
         	Package: controladores
         	Name: ejemploController
         	Scope: session
    

    En Configuration Files $ \to$ Source Packages $ \to$ controladores se habrá creado la clase del @ManagedBean con sus correspondientes anotaciones.

  2. Inyectar referencias a los EJBs que implementan los DAO.
    @ManagedBean
    @SessionScoped
    public class EjemploController {
        @EJB
        CustomerDAO customerDAO;
    
        @EJB
        PurchaseOrderDAO purchaseOrderDAO;
     
        ...
    }
    

  3. Incluir los atributos para almacenar los datos a mostrar en las vistas (y sus respectivos getter y setter)
    @ManagedBean
    @SessionScoped
    public class EjemploController { 
        ...
        String cadenaBusqueda;
        List<Customer> listaClientes;
        Customer clienteActual;
        List<PurchaseOrder> listaPedidosClienteActual;
        PurchaseOrder pedidoActual;
        ...
    
        // Getters y setters
        ...
    }
    

    Nota: Los métodos get() y set() pueden generarse automáticamente desde Source $ \to$ Insert Code

    Estrictamente sólo es necesario un método set() para el atributo cadenaBusqueda.

  4. Incluir un método de inicialziación marcado con la anotación @PostConstruct
     @ManagedBean
    @SessionScoped
    public class EjemploController { 
        ...
        // Inicializacion
    
        @PostConstruct
        public void inicializar(){
            listaClientes = customerDAO.buscarTodos();
            clienteActual = listaClientes.get(0);
            listaPedidosClienteActual = purchaseOrderDAO.buscarPorCliente(clienteActual.getCustomerId());
            pedidoActual = null;        
        }
        ...
    }
    

    Carga inicialmente la lista de clientes con todos los clientes de la BD (OJO: poco eficiente), establece el primero de ellos como clienteActual y carga su lista de pedidos.

  5. Implementar los métodos de acción (y de navegación)
    @ManagedBean
    @SessionScoped
    public class EjemploController { 
        ...
        // Metodos de acción
    
        public String doVerPedidos(Customer cliente) {
            clienteActual = cliente;
            listaPedidosClienteActual = purchaseOrderDAO.buscarPorCliente(cliente.getCustomerId());
            return "detalleCliente";
        }
    
        public String doBuscarCliente(){
            listaClientes = customerDAO.buscarPorNombre(cadenaBusqueda);
            clienteActual = listaClientes.get(0);
            return "index";
        }
    
        public String doNuevoCliente(){
            clienteActual = new Customer();
            listaPedidosClienteActual = null;
            return "nuevoCliente";
        }
    
        public String doGuardarCliente(){
            customerDAO.crear(clienteActual);
            return "index";
        }
        ...
    }
    

    Implementan las acciones a realizar como respuesta a las pulsaciones de los botones de los distintos formularios.

Fichero resultante: EjemploController.java

Formularios JSF

  1. Sobre Web Pages $ \to$ index.xhtml se incluyen los componentes que formarán la página principal (cuadro de búsqueda, botón de búsqueda y tabla con la lista de clientes)

       <h:body>
            <h:form>
                <h:panelGrid columns="2">
                    <h:inputText value="#{ejemploController.cadenaBusqueda}"/>
                    <h:commandButton value="Buscar" action="#{ejemploController.doBuscarCliente}" />
                    <h:commandLink value="Nuevo cliente" action="#{ejemploController.doNuevoCliente}" />
                </h:panelGrid>
    
                <h1><h:outputText value="Listado"/></h1>
                
                <h:dataTable value="#{ejemploController.listaClientes}" var="cliente"
                             border="0" cellpadding="4" cellspacing="0" rules="all" >
                ....
                </h:dataTable>
    
            </h:form>        
        </h:body>
    

    Debe incluirse el namespace xmlns:f="http://java.sun.com/jsf/core" en la cabecera de la página JSF.

    Nota: Se puede automatizar parcialmente la creación del <h:datatable> usando un asistente de Netbeans.

    Fichero resultante: index_xhtml (ajustar extensión)

  2. Crear página JSF para mostar el detalle del cliente seleccionado.
    New File -> Java Server Faces -> JSF Page
         	File Name: detalleCliente
         	Location: Web Pages
         	Folder: <vacio>
         	Options: facelets
    

    En Web Pages se habrá creado el fichero detalleCliente.xhtml sobre el que se insertarán los componentes (dentro de un <h:form> en <h:body>).

         <h:body>
            <h:form>
                <h1><h:outputText value="Datos cliente"/></h1>
                <h:panelGrid columns="2">
                   <!-- detalle del cliente -->
                 </h:panelGrid>
    
                <h1><h:outputText value="Lista compras"/></h1>
                <h:dataTable value="#{ejemploController.listaPedidosClienteActual}" var="item"
                             border="0" cellpadding="4" cellspacing="0" rules="all" >
                   ...
                </h:dataTable>
            </h:form>
        </h:body>
    

    Nota: pueden volver a usarse los asistentes JSF de Netbeans para crear el panel con los datos del cliente y la tabla con su lista de pedidos.

    Fichero resultante: detalleCliente_xhtml (ajustar extensión)

  3. Crear página JSF para dar de alta un nuevo.

    Fichero resultante: nuevoCliente_xhtml (ajustar extensión)

Ejecución y pruebas

  1. Ejecutar: sobre el proyecto $ \to$ [botón derecho] $ \to$ run
  2. Comprobar la estructura de fichero .war generado
     
    cp /home/alumno/NetBeansProjects/EjemploJSF/dist/EjemploJSF.war /tmp
    cd /tmp
    jar -xvf EjemploJSF.war
    ls -lR EjemploJSF
    



ribadas 2011-09-27