viernes, 27 de marzo de 2015

Ejemplo: Java EE JSF+JPA - X


Continuamos construyendo ManagedBeans:

UsuariosBean.java

@ManagedBean(name="usuario")
@RequestScoped
public class UsuariosBean {

    private String nombre;
    private String login;
    private String password;
    private String email;
    private String sector;
    private String profesion;
    private String antiguedad;    
    private int selectedSector;
    private String message;
    
    public UsuariosBean() {
        message="";
        nombre="";
        login="";
        password="";
        email="";
        sector="";
        profesion="";
        antiguedad="";
        selectedSector=0;                
    }
       
    public String nuevoUsuario() {
        // WARNING !! no hacemos ningun tipo de comprobacion para no alargar el codigo del ejemplo
        UsuariosDAO us=new UsuariosDAO();
        int ant=(int)Integer.parseInt(antiguedad);
        Usuarios nuevo=new Usuarios(nombre,login,password,email,sector,profesion,ant);
        if (us.createUser(nuevo)) {
            message="¡ Usuario grabado correctamente !";
            IndexBean.usuario=nuevo;
        } else {
            message="ERROR en grabación de usuario";
        }       
        return "alta.xhtml";
    }
    
    public String volver() {
        return "index.xhtml";
    }
    // GETTERS Y SETTERS NO INCLUIDOS PARA ABREVIAR CODIGO, PERO SON NECESARIOS
}

PersonalesBean.java

@ManagedBean(name="personales")
@RequestScoped
public class PersonalesBean {

    private String nombre;
    private String login;
    private String password;
    private String email;    
    private String message;
    
    public PersonalesBean() {        
        nombre=IndexBean.usuario.getNombre();
        login=IndexBean.usuario.getLogin();
        password=IndexBean.usuario.getPassword();
        email=IndexBean.usuario.getEmail();
    }

    public String modificarUsuario() {
        // intentamos modificar el usuario utilizando los datos del
        // usuario en SessionScoped combinados con los del formulario
        UsuariosDAO us=new UsuariosDAO();
        Usuarios modUser=new Usuarios();
        // WARNING !! no hacemos ningun tipo de comprobacion para no alargar el codigo
        modUser=IndexBean.usuario;
        modUser.setNombre(nombre);
        modUser.setLogin(login);
        modUser.setPassword(password);
        modUser.setEmail(email);
        if (us.changeUser(modUser)) {
            // modificado usuario, mostramos mensaje y permanecemos en la pagina
            IndexBean.usuario=modUser;
            message="Modificación del usuario realizada correctamente";
            return "personales.xhtml";
        }
        // no es posible modificar, mostramos mensaje y permanecemos en la pagina
        message="ERROR en modificación de usuario";
        // recuperamos los datos originales
        nombre=IndexBean.usuario.getNombre();
        login=IndexBean.usuario.getLogin();
        password=IndexBean.usuario.getPassword();
        email=IndexBean.usuario.getEmail();
        return "personales.xhtml";
    }
    
    public String borrarUsuario() {
        // intentamos borrar el usuario utilizando los datos del
        // usuario en SessionScoped
        UsuariosDAO us=new UsuariosDAO();
        if (us.deleteUser(IndexBean.usuario.getId())) {
            // borrado usuario, salimos de la aplicacion poniendo usuario a null
            IndexBean.usuario=null;
            // mensaje en index de confirmacion
            IndexBean.message="usuario borrado correctamente";
            return "index.xhtml";
        }
        // no es posible borrar, mostramos mensaje y permanecemos en la pagina
        message="ERROR en borrado de usuario";
        return "personales.xhtml";
    }
    
    public String goToProfesionales() {
        // vamos a la pagina de datos profesionales
        return "profesionales.xhtml";
    }
    
    public String goOut() {
        // salimos de la aplicacion, borrando los datos del usuario activo
        IndexBean.usuario=null;
        // borramos mensaje en index
        IndexBean.message="";
        return "index.xhtml";
   }
 // GETTERS Y SETTERS NO INCLUIDOS PARA ABREVIAR CODIGO, PERO SON NECESARIOS
 }

ProfesionalesBean.java

@ManagedBean(name="profesionales")
@RequestScoped
public class ProfesionalesBean {

    private String sector;
    private String profesion;
    private String antiguedad;
    private int selectedSector;
    private String message;
    
    public ProfesionalesBean() {    
        sector=IndexBean.usuario.getSector();
        profesion=IndexBean.usuario.getProfesion();
        antiguedad=String.valueOf(IndexBean.usuario.getAntiguedad());  
        switch (sector) {
            case "Industria":
                selectedSector=1;
                break;
            case "Comercio":
                selectedSector=2;
                break;
            case "Agricultura":
                selectedSector=3;
                break;                
            case "Servicios":
                selectedSector=4;
                break;
            default:
                selectedSector=5;
                break;                
        }     
    }
    
    public String modificarUsuario() {
        // intentamos modificar el usuario utilizando los datos del
        // usuario en SessionScoped combinados con los del formulario
        UsuariosDAO us=new UsuariosDAO();
        Usuarios modUser=new Usuarios();
        // WARNING !! no hacemos ningun tipo de comprobacion para no alargar el codigo
        modUser=IndexBean.usuario;
        modUser.setProfesion(profesion);
        modUser.setAntiguedad(Integer.parseInt(antiguedad));
        modUser.setSector(sector);
        if (us.changeUser(modUser)) {
            // modificado usuario, mostramos mensaje y permanecemos en la pagina
            IndexBean.usuario=modUser;
            message="Modificación del usuario realizada correctamente";
            return "profesionales.xhtml";
        }
        // no es posible modificar, mostramos mensaje y permanecemos en la pagina
        message="ERROR en modificación de usuario";
        // recuperamos los datos originales
        sector=IndexBean.usuario.getSector();
        profesion=IndexBean.usuario.getProfesion();
        antiguedad=String.valueOf(IndexBean.usuario.getAntiguedad());      
        switch (sector) {
            case "Industria":
                selectedSector=1;
                break;
            case "Comercio":
                selectedSector=2;
                break;
            case "Agricultura":
                selectedSector=3;
                break;                
            case "Servicios":
                selectedSector=4;
                break;
            default:
                selectedSector=5;
                break;                
        }        
        return "profesionales.xhtml";
    }
    
    public String borrarUsuario() {
        // intentamos borrar el usuario utilizando los datos del
        // usuario en SessionScoped
        UsuariosDAO us=new UsuariosDAO();
        if (us.deleteUser(IndexBean.usuario.getId())) {
            // borrado usuario, salimos de la aplicacion poniendo usuario a null
            IndexBean.usuario=null;
            // mensaje en index de confirmacion
            IndexBean.message="usuario borrado correctamente";            
            return "index.xhtml";
        }
        // no es posible borrar, mostramos mensaje y permanecemos en la pagina
        message="ERROR en borrado de usuario";
        return "profesionales.xhtml";
    }
    
    public String goToPersonales() {
        // vamos a la pagina de datos profesionales
        return "personales.xhtml";
    }
    
    public String goOut() {
        // salimos de la aplicacion, borrando los datos del usuario activo
        IndexBean.usuario=null;
        // borramos mensaje en index
        IndexBean.message="";
        return "index.xhtml";
    }
 // GETTERS Y SETTERS NO INCLUIDOS PARA ABREVIAR CODIGO, PERO SON NECESARIOS
// INCLUYO, SIN EMBARGO ESTE SETTER POR EL TEMA DE LA CONVERSION INT-STRING
    public void setSelectedSector(int selectedSector) {
        this.selectedSector = selectedSector;       
        switch (selectedSector) {
            case 1:
                setSector("Industria");
                break;
            case 2:
                setSector("Comercio");
                break;
            case 3:
                setSector("Agricultura");
                break;                
            case 4:
                setSector("Servicios");
                break;
            default:
                setSector("Otros");
                break;                
        }

    }
}


RESUMEN:

  • Los atributos serán relacionados con los campos de formularios. 
  • Los métodos serán relacionados con los botones del formulario. 
  • Hemos creado un atributo message para visualizar los mensajes de error o confirmación de operaciones.
  • En el caso del selector en profesionales.xhtml, hay que observar que en la base de datos se almacena un String con el texto de la selección, pero el selector opera con un int según el elemento seleccionado. Es por ello que debemos estar traduciendo del itemValue (int) al itemLabel (String). Por ello hemos empleado un switch case a título ejemplo, aunque podríamos haber empleado métodos más eficientes. 
  • No hacemos comprobaciones de tipos ni longitud ni las comprobaciones que siempre son necesarias al enviar un formulario. ¡No lo hacemos por negligencia! Al igual que con los getters y setters, lo hacemos por abreviar y aligerar el código del ejemplo, haciéndolo más legible.

Anterior tema                                                                                         Siguiente tema

miércoles, 25 de marzo de 2015

Ejemplo: Java EE JSF+JPA - IX

Hola jabatos:

Comenzamos con la construcción de nuestra capa de negocio.

8 - Capa de negocio: construcción de ManagedBeans

La capa de negocio es donde se concentra la operativa de nuestra aplicación, consistente en procesar los requerimientos del cliente, realizar las distintas operaciones solicitadas y/o planificadas, y construir los objetos necesarios para poder finalmente procesar, suministrar y/o almacenar la información resultante.

Los ficheros de nuestra capa de negocio estarán ubicados en la carpeta "controllers".

Por otra parte, en JSF, los ficheros encargados de procesar la información son los denominados "ManagedBeans", que son ficheros java con anotaciones que los identifican como tales; éstos se encargan de interactuar tanto con la capa vista como con la capa de persistencia para la función que haya sido planificada.

Es buena práctica y conveniente, por diversas razones, construir un ManagedBean por cada fichero vista (página jsf) construido, aun cuando sea en algunos casos redundante. El mayor coste en términos de trabajo y mantenimiento es compensado por un  mejor control y claridad en el diseño, sin contar los errores que pueden ocasionarse por un inadecuado diseño.

Así pues, por cada vista, un ManagedBean, que en nuestro caso van a ser:

index.xhtml => IndexBean.java
alta.xhtml => UsuariosBean.java
personales.xhtml => PersonalesBean.java
profesionales.xhtml => ProfesionalesBean.java

Los ManagedBeans deben tener la anotación @ManagedBean para que puedan ser identificados como tales. Es posible (y nosotros lo vamos a hacer) darles un nombre diferente al del fichero, mediante la anotación "name". Ese nombre simbólico servirá para linkar con las páginas vista, y es el que emplearemos en ellas para referirnos al ManagedBean.

Por otra parte, utilizaremos la anotación "Scoped" para que el contenedor de aplicaciones controle la duración del ciclo de vida de los beans. Cada vez que se llama a una página web se crea un objeto ManagedBean. La anotación por defecto es @RequestScoped, que le dice al contenedor que la información contenida en el ManagedBean tiene que ser creado cuando es llamado, y al ser abandonado ese objeto es marcado para destruirlo, evitándose la acumulación de objetos sin utilidad que podrían hacer caer el sistema por saturación.

@SessionScoped mantiene un objeto ManagedBean "vivo" como copia única (Standalone) en el contenedor de aplicaciones. Cada vez que se llama al jsf, éste llamará al mismo objeto, el cual mantendrá el estado. Este scoped interesa solo a aquellos ManagedBean que contengan información a utilizar durante toda la sesión. Hay que entender que sesión del usuario empieza cuando se conecta al sistema, y termina cuando se desconecta.

UsuariosBean, PersonalesBean y ProfesionalesBean tendrán RequestScoped. Sin embargo, IndexBean tendrá SessionScoped. Esto es porque IndexBean va a contener los datos del usuario identificado mediante un objeto static, objeto al cual van a consultar, modificar y/o borrar el resto de las páginas de nuestra aplicación.

Y sin más palabras, he aquí el primero de nuestros managedBeans:

IndexBean.java

@ManagedBean(name="identificacion")
@SessionScoped
public class IndexBean {

    private String login;
    private String password;
    protected static Usuarios usuario;
    
    protected static String message;

    public IndexBean() {
        message="";
    }

    public String identifica() {     
        // comprobamos la identificacion
        UsuariosDAO us=new UsuariosDAO();
        usuario=us.identifyUser(login, password);
        // si esta identificado mostramos datos personales
        if (usuario!=null) return "personales.xhtml";
        // en caso contrario, mostramos el error
        message="ERROR en la identificación del usuario";
        return "index.xhtml";
    }
    
    public String nuevo(){
        return "alta.xhtml";
    }
   
   // GETTERS AND SETTERS 
}

En un ManagedBean, los atributos son la forma estandarizada de enviar/recibir la información proveniente de la capa vista. Esto se deberá realizar a traves de los getters/setters correspondientes. Ya sabemos que, por seguridad y buena práctica, los atributos deben ser declarados private y accederse a ellos mediante getters/setters publics (encapsulación).

 Los campos login y password del formulario contenido en index.xhtml enlazarán con los atributos login y password de este ManagedBean, ya veremos como.

Por otra parte, los métodos se enlazan con los botones y/o elementos a través de los actions de los elementos jsf del formulario. En concreto, el botón "Login" enlazará con el método identifica(), y el botón "Nuevo" enlazará con el método nuevo().

Observemos el detalle del tipo de retorno que tienen ambos métodos. Debemos entender como funciona este asunto:

Cuando un botón jsf es pulsado, se ejecutará el método correspondiente en el ManagedBean, ese método retornará un String entre otros datos. El formulario se reconstruirá con la respuesta del servidor y el String retornado se convertirá en el action (o sea, la redirección) del formulario. Por lo tanto, el String a retornar deberá ser la dirección de navegación a donde queramos redireccionar la página. Incluyendo permanecer en la página en donde estamos. Es por ello que, pulsando en "Nuevo", seremos redireccionados hacia alta.xhtml.

No obstante, recordemos que aún no hemos completado las vistas jsf con los links a los atributos y métodos de sus ManagedBean correspondientes.

En el siguiente post continuaremos con los siguientes ManagedBeans.

Anterior tema                                                                                         Siguiente tema

viernes, 20 de marzo de 2015

Ejemplo: Java EE JSF+JPA - VIII


Continuamos con la elaboración de nuestra capa vista.

Fichero alta.xhtml

Este es el fichero que trata de las altas de nuevos usuarios, grabando los datos del formulario en la base de datos:

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
     <h:head>        
        <style>
            body {
                width: 600px;
                margin: 0 auto 0 auto;
                background-color: #ffffff;
            }
            .indexBody {
                margin-top: 25px;
            }            
            table {
                margin-left: 60px;
            }            
            .buttonForm input {
                margin-left: 70px;
                margin-top: 20px;
                width: 100px;
            }                      
            .message{
                font-size: 1.5em;
                color: red;
            }
        </style>
        
        <title>Alta usuarios</title>
    </h:head>
    <h:body >
        <div class="indexBody">
        <h:form>
            <h1>Creación de nuevo usuario</h1>
            <h:panelGrid columns="2">
                <h:outputLabel>Nombre</h:outputLabel><h:inputText value=""></h:inputText>
                <h:outputLabel>Usuario</h:outputLabel><h:inputText value=""></h:inputText>       
                <h:outputLabel>Contraseña</h:outputLabel><h:inputText value=""></h:inputText> 
                <h:outputLabel>Email</h:outputLabel><h:inputText value=""></h:inputText>
                <h:outputLabel>Sector</h:outputLabel>
                <h:selectOneMenu value="">
                        <f:selectItem itemLabel="Industria" itemValue="1"></f:selectItem>
                        <f:selectItem itemLabel="Comercio" itemValue="2"></f:selectItem>
                        <f:selectItem itemLabel="Agricultura" itemValue="3"></f:selectItem>
                        <f:selectItem itemLabel="Servicios" itemValue="4"></f:selectItem>
                        <f:selectItem itemLabel="Otros" itemValue="5"></f:selectItem>
                    </h:selectOneMenu> 
                <h:outputLabel>Profesión</h:outputLabel><h:inputText value=""></h:inputText>
                <h:outputLabel>Antiguedad</h:outputLabel><h:inputText value=""></h:inputText>            
            </h:panelGrid>
            <div class="buttonForm">
                <h:commandButton value="Grabar" ></h:commandButton>
                <h:commandButton value="Volver" ></h:commandButton>
            </div>
            <div class="message">
                <h:outputText value=""></h:outputText>
            </div>
        </h:form>
        </div>
    </h:body>
</html>

El aspecto de la página de altas:



Fichero personales.xhtml

Este es el fichero que muestra en pantalla, una vez identificado, los datos personales del usuario:

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"     xmlns:f="http://java.sun.com/jsf/core">
    <h:head>    
        <style>
            body {
                width: 600px;
                margin: 0 auto 0 auto;
                background-color: #ffffff;
            }
            .indexBody {
                margin-top: 25px;
            }            
            table {
                margin-left: 60px;
            }            
            .buttonForm input {
                margin-left: 20px;
                margin-top: 20px;
                width: 100px;
            }                      
            .buttonExit {
                margin-left: 400px;
            }        
            .message{
                font-size: 1.5em;
                color: red;
            }
        </style>        
        <title>Datos usuario</title>
    </h:head>
    <h:body >
        <div class="indexBody">
            <h:form>
                <h:commandButton class="buttonExit" value="Salir" ></h:commandButton>
                <h1>Datos personales</h1>
                <h:panelGrid columns="2">
                    <h:outputLabel>Nombre</h:outputLabel><h:inputText  value=""></h:inputText>
                    <h:outputLabel>Usuario</h:outputLabel><h:inputText  value=""></h:inputText>       
                    <h:outputLabel>Contraseña</h:outputLabel><h:inputText  value=""></h:inputText> 
                    <h:outputLabel>Email</h:outputLabel><h:inputText  value=""></h:inputText>          
                </h:panelGrid>
                <div class="buttonForm">
                    <h:commandButton  value="Modificación" ></h:commandButton>
                    <h:commandButton  value="Borrar" ></h:commandButton>
                    <h:commandButton  value="Profesionales" ></h:commandButton>
                </div>
            <div class="message">
                <h:outputText value=""></h:outputText>
            </div>  
            </h:form>
        </div>
    </h:body>
</html>





Mediante los correspondientes botones, se puede modificar los datos, borrar el usuario completo, pasar a los datos profesionales, o salir de forma segura de la aplicación. Los errores y/o advertencias se mostrarán en rojo debajo de los botones, al igual que el resto de las páginas de la vista.

Fichero profesionales.xhtml

Al igual que el anterior, muestra los datos profesionales del usuario identificado.

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <style>
            body {
                width: 600px;
                margin: 0 auto 0 auto;
                background-color: #ffffff;
            }
            .indexBody {
                margin-top: 25px;
            }            
            table {
                margin-left: 60px;
            }            
            .buttonForm input {
                margin-left: 20px;
                margin-top: 20px;
                width: 100px;
            }           
            .buttonExit {
                margin-left: 400px;
            }       
            .message{
                font-size: 1.5em;
                color: red;
            }    
        </style>      
        <title>Datos usuario</title>
    </h:head>
    <h:body >
        <div class="indexBody">
        <h:form>
            <h:commandButton class="buttonExit" value="Salir" ></h:commandButton>
            <h1>Datos profesionales</h1>            
            <h:panelGrid columns="2">
                <h:outputLabel>Sector</h:outputLabel>
                <h:selectOneMenu value="">
                    <f:selectItem itemLabel="Industria" itemValue="1"></f:selectItem>
                    <f:selectItem itemLabel="Comercio" itemValue="2"></f:selectItem>
                    <f:selectItem itemLabel="Agricultura" itemValue="3"></f:selectItem>
                    <f:selectItem itemLabel="Servicios" itemValue="4"></f:selectItem>
                    <f:selectItem itemLabel="Otros" itemValue="5"></f:selectItem>
                </h:selectOneMenu>               
                <h:outputLabel>Profesión</h:outputLabel><h:inputText  value=""></h:inputText>
                <h:outputLabel>Antiguedad</h:outputLabel><h:inputText  value=""></h:inputText>            
            </h:panelGrid>
            <div class="buttonForm">
                <h:commandButton  value="Modificación" ></h:commandButton>
                <h:commandButton  value="Borrar" ></h:commandButton>
                <h:commandButton  value="Personales" ></h:commandButton>
            </div>
            <div class="message">
                <h:outputText value=""></h:outputText>
            </div>  
        </h:form>
        </div>
    </h:body>
</html>

Este es el aspecto de la pantalla:



Al igual que la pantalla de datos personales, permite modificar, borrar el usuario, navegar hacia datos personales y salir de la aplicación de forma segura.

RESUMEN:
Hemos creado las páginas de nuestra capa vista. En estos momentos son básicamente vistas html, porque no reciben ni transmiten información hacia la capa de negocio, pero cuando hayamos construido la capa de negocios volveremos a modificar estos ficheros, inyectaremos el código correspondiente en campos de texto y/o botones, y le daremos plena funcionalidad a nuestra aplicación.

Pero ahora toca construir la capa de negocio.

Anterior tema                                                                                         Siguiente tema

miércoles, 18 de marzo de 2015

Ejemplo: Java EE JSF+JPA - VII

Hola jabatos:

Ahora vamos a generar nuestra capa vista.

La capa vista, en una aplicación JSF, tiene como objetivo generar las respuestas a las solicitudes del usuario, y más concretamente, a través del procesamiento de la información que se llevará a cabo en la capa de negocio, elaborar los html hacia el navegador del usuario-cliente.

Lógicamente, esta capa vista debe estar construida con un lenguaje dinámico, en nuestro caso JSF y nuestro servidor de aplicaciones se ocupará de procesar los JSF y construir los HTML que serán enviados al cliente.

7 - Fichero Web.xml y capa vista

Debido a la sencillez del ejemplo que estamos manejando, nuestra capa vista se compondrá solamente de cuatro ficheros, la pantalla de identificación, la pantalla de alta de usuarios, la pantalla de datos personales y la pantalla de datos profesionales.

Pero previamente debemos construir el fichero web.xml. Hasta la versión 3.0, el fichero web.xml era un fichero imprescinble para el mapeo de la aplicación javaEE. A partir de esta versión, el uso es opcional.

Web.xml 

Desde el fichero de configuración web.xml se pueden configurar muchos parámetros de la aplicación, así como configurar su funcionamiento. Uno de los puntos más interesantes y útiles consiste en indicar las direcciones de navegación hacia los ficheros o servlets correspondientes, así como el punto de entrada en la aplicación.

<?xml version = '1.0' encoding = "UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

<welcome-file-list>
    <welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
  <servlet>

  <display-name>ejemploJSF</display-name>
  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
    <param-value>*.xhtml</param-value>
  </context-param>

  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
  </servlet-mapping>
  
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
</web-app>

Este fichero web.xml, entre otras cosas, lo que hace es:
  • Redireccionar las peticiones a nuestra web hacia el fichero index.xhtml
  • Mapear peticiones de ficheros hacia extensiones xhtml.
Por lo tanto, nuestros ficheros van a llevar extensiones xhtml durante la navegación, y nuestro fichero de entrada e identificación, se llamará index.xhtml.

Fichero index.xhtml 

Ahora procedemos a construir el fichero index.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html">
    <h:head>
              <style>
            body {
                width: 600px;
                margin: 0 auto 0 auto;
                background-color: #ffffff;
            }
            .indexBody {
                margin-top: 25px;
            }          
            table {
                margin-left: 60px;
            }         
            .buttonForm input {
                margin-left: 70px;
                margin-top: 20px;
                width: 100px;
            }     
            .message{
                font-size: 1.5em;
                color: red;
            }
        </style>
        
        <title>Identificación</title>
    </h:head>
    <h:body >
        <div class="indexBody">
        <h:form>
            <h1>Identificación de usuario</h1>
            <h:panelGrid columns="2">
                <h:outputLabel>Usuario</h:outputLabel><h:inputText value=""></h:inputText>
                <h:outputLabel>Contraseña</h:outputLabel><h:inputSecret value=""></h:inputSecret>        
            </h:panelGrid>
            <div class="buttonForm">
                <h:commandButton  value="Login" ></h:commandButton>
                <h:commandButton  value="Nuevo"  ></h:commandButton>
            </div>
            <div class="message">
                <h:outputText value=""></h:outputText>
            </div>            
        </h:form>
        </div>
    </h:body>
</html>

Y este es el aspecto de la página...




Comento un poco el código...

Bueno, nos olvidamos del código css, ya que nos centraremos en JSF.
Lo primero, observar que hemos declarado un espacio de nombres arriba en <html xmlns="http://www.w3.org/1999/xhtml"      xmlns:h="http://java.sun.com/jsf/html"> Esta etiqueta nos permitirá acceder a las etiquetas especiales de jsf. Estas etiquetas nos aparecen, cuando estamos en modo edición, empezando por una h, que es con la letra que la que la hemos designado en xmlns:h="http://java.sun.com/jsf/html". Si hubieramos puesto j, pues las etiquetas empezarían por <j:

Bueno, declarado el espacio de etiquetas de JSF, pues lo primero que hemos de hacer, cuando programamos una página JSF, es declarar el head y el body con las etiquetas JSF <h:head> y <h:body>.

Los elementos de la página JSF también son elementos especiales, empezando por <h:form>. Esta etiqueta, al contrario que su correspondiente de html, no contiene la redirección de la página que se producirá cuando se envíe el formulario. Esa información irá en los botones.

<h:PanelGrid> es el equivalente al elemento table de html. En PanelGrid definiremos el número de columnas, y el propio PanelGrid irá creando filas de ese número de columnas, por lo que nos ahorramos muchos de los tediosos tr y td.

Aparecen   <h:outputLabel> <h:inputText ><h:inputSecret value=""> que equivalen a label, input type="text" e input type="password".

<h:commandButton> equivale a input type="submit", o sea, es un botón que lanza el formulario; además contendrá un elemento llamado "action" donde alojaremos, en su momento, la dirección (el método en el ManagedBean) hacia donde se enviará la información de la página.

Tanto commandButton, inputText como inputSecret quedan DE MOMENTO EN BLANCO, en los aspectos fundamentales, en espera de construir las clases java de negocio. Entonces volveremos sobre nuestras páginas y añadiremos el código necesario.

Debajo de los botones, hemos creado un contenedor div para mostrar los mensajes de error, advertencia, etc.etc. No es que esto sea un excelente diseño, claro, pero no quiero complicar el código con advertencias javascript, ni tampoco es mi intención aproximarme al uso de mensajes en JSF. Nos bastará con una simple línea de advertencia, si procede.

Por lo tanto, aunque son páginas JSF, ahora mismo son meras cáscaras huecas sin funcionamiento, hasta que las rellenemos con el código EL de JSF que permitirá interactuar con los ManagedBeans.

Anterior tema                                                                                         Siguiente tema

sábado, 14 de marzo de 2015

Ejemplo: Java EE JSF+JPA - VI

Hola Jabatos:

Una vez implementada la capa de persistencia procedemos al siguiente paso.

Vamos a implementar la capa de negocio; para empezar, dentro del directorio controllers construiremos la EntityManagerFactory, el fichero DAO para acceso a capa de persistencia y el interface correspondiente:

6 - Creación del fichero DAO y de EntityManagerFactory

Primero vamos a construir la EntityManagerFactory. Una entityManagerFactory es un objeto que tiene como misión crear una "factoría" de sesiones, es decir que fabrica objetos session. Un objeto session es un objeto utilizado para cada operación de base de datos, y tiene un periodo de vida más bien limitado, de usar y tirar ;-)

La clase se llamará ConnectionFactory. En JPA, este objeto es bastante "pesado", por lo que es conveniente crear solo uno por sesión de usuario. A partir del entityManagerFactory se crearán los objetos session, que en JPA se llaman entityManager.

public class ConnectionFactory {
    private static EntityManagerFactory emf;
    static {
        emf=Persistence.createEntityManagerFactory("ejemploJSF");
    }
    public static EntityManagerFactory getEmf() {
       if (emf==null) {
        emf=Persistence.createEntityManagerFactory("ejemploJSF");
      }
        return emf;
    }
}

En createEntityManagerFactory le suministramos el nombre que suministramos en Persistence-unit, cuando creamos el objeto Persistence.xml. Esto relaciona, por tanto, a la EntityManagerFactory con la Persistence-unit y la base de datos que éste administra. Es conveniente poner nombre a la Persistence-unit, aunque solo tengamos una.

El acceso al objeto estático será a través de getEmf(). Cada vez que accedamos a este objeto, nos habilitará la posibilidad de crear un nuevo objeto session simplemente instanciándolo.

El siguiente paso va a consistir en la creación del fichero interface que va a implementar el DAO. Llamaremos al interface UsuariosInterface:

public interface UsuariosInterface {
    public Usuarios identifyUser (String login, String password);
    public boolean createUser(Usuarios usuario);
    public Usuarios getUser (long idUser);
    public boolean changeUser(Usuarios usuario);
    public boolean deleteUser(long idToDelete);
}

Este fichero tiene la finalidad de controlar que el modelo DAO y sus posible modificaciones mantengan la coherencia con el diseño y la arquitectura del proyecto, y que los cambios realizados en la capa de persistencia no afecten, o afecten mínimamente al resto de capas de la aplicación.

Una vez construido el interface, procederemos a implementar el DAO, con todos los métodos del interface desarrollados. El fichero se llamará UsuariosDAO:

public class UsuariosDAO implements UsuariosInterface {
    
 public UsuariosDAO() {

 } 

 /**
  * Este metodo sirve para identificar a un usuario determinado.
  * @param login - login del usuario a recuperar la informacion.
  * @param password - password del usuario a recuperar la informacion.
  * @return Devuelve como parametros objeto Usuario con los datos del usuario o null
  * si el usuario no existe o si hay errores. 
  */
 @Override
 public Usuarios identifyUser (String login, String password) {
     EntityManager em=ConnectionFactory.getEmf().createEntityManager();
     em.getTransaction().begin();
     String sql="SELECT u FROM Usuarios u WHERE login LIKE '"+login+"' AND password LIKE '"+password+"'";   
     Query q=em.createQuery(sql);
     Usuarios user=null;
     try {
         user=(Usuarios)q.getSingleResult();
     } catch (NoResultException nr) {
         return null;
     } catch (NonUniqueResultException nu) {
         // devuelve el primer usuario
         user=(Usuarios)q.getResultList().get(0);
     } catch (Exception ex) {
         return null;
     } finally {
         em.close();
     }     
     return user;


 /**
  * Este metodo crea un usuario nuevo, grabando los datos correspondientes en el fichero de usuarios.
  * @param usuario - Objeto Usuarios, conteniendo el usuario a grabar. 
  * @return boolean con el resultado de la operación.
  */
 @Override
 public boolean createUser(Usuarios usuario) {
     EntityManager em=ConnectionFactory.getEmf().createEntityManager();
     em.getTransaction().begin();   
     try {
         em.persist(usuario);
         em.getTransaction().commit();
     } catch (Exception ex) {
         em.getTransaction().rollback();
         return false;
     } finally {
         em.close();
     }    
   return true;           
 } 

 /**
  * Este metodo sirve para recuperar los datos relativos a un usuario determinado. 
  * @param idUser - Id del usuario a recuperar la informacion.
  * @return Devuelve como parametros objeto Usuario con los datos del usuario o null si errores. 
  */
 @Override
 public Usuarios getUser (long idUser) {
     EntityManager em=ConnectionFactory.getEmf().createEntityManager();
     em.getTransaction().begin();
     Usuarios user=null;
     try {
        user=em.find(Usuarios.class, idUser);
     } catch (IllegalArgumentException il) {
         return null;
     } finally {
         em.close();
     }     
     return user;
 } 

 /**
  * Este método modifica los datos del usuario grabados en ddbb, sustituyéndolos
  * por los datos del objeto suministrado. 
  * @param usuario - Objeto Usuarios, correspondiente a los nuevos datos a grabar.
  * @return boolean con el resultado de la operación.
  */
 @Override
 public boolean changeUser(Usuarios usuario) {
     EntityManager em=ConnectionFactory.getEmf().createEntityManager();
     em.getTransaction().begin();
     try {
         Usuarios us=em.merge(usuario);
         em.persist(us);
         em.getTransaction().commit();
     } catch (Exception ex) {
         em.getTransaction().rollback();
         return false;
     } finally {
         em.close();
     }
   return true;
 }

 /**
  * Este método elimina del fichero de usuarios al usuario con el id del parámetro suministrado 
  * @param usuario - long, con el id del usuario a eliminar
  * @return boolean con el resultado de la operación.
  */
 @Override
 public boolean deleteUser(long idToDelete) {  
     EntityManager em=ConnectionFactory.getEmf().createEntityManager();
     em.getTransaction().begin();
     String sql="DELETE FROM Usuarios u WHERE id='"+idToDelete+"'";
     Query q=em.createQuery(sql);
     try {
         q.executeUpdate();
         em.getTransaction().commit();
     } catch (Exception ex) {
         em.getTransaction().rollback();
         return false;
     } finally {
         em.close();
     }  
   return true;
 }
  
} // *****  END OF CLASS

Teniendo el fichero DAO, la capa de negocio podrá interactuar eficientemente con la capa de persistencia abstrayéndose de los cambios que se realicen en esta última, lo cual minimiza la posibilidad de errores y el trabajo correspondiente a la adaptación a los cambios.

Anterior tema                                                                                         Siguiente tema