viernes, 19 de junio de 2020

Relaciones entre clases

Cuando se diseña un programa se realizan diversos artefactos que nos permiten identificar sus componentes y funcionamiento. Entre ellos tenemos a los diagramas de clases y objetos.

En los lenguajes orientados a objetos como JAVA es fundamental comprender como las clases existentes se relacionan. UML permite definir tres tipos de relaciones fundamentales que son:
  • Asociación
  • Agregación
  • Composición
  • Herencia

Notación de las relaciones entre clases

Tienen las siguientes partes:
  • Nombre de la relación (un verbo).
  • La ocurrencia de cada clase (rangos ubicados en los extremos).
  • El rol de cada clase en la relación.

La multiplicidad es el número de instancias de una clase que se relacionan con una instancia de otra clase.
Multiplicidad Simbología
Uno y solo uno 1
Cero o uno 0 .. 1
Desde "N" hasta "M" N .. M
Varios *
Cero a varios 0 .. *
Uno a varios 1 .. *

Asociación

Es una relación entre dos clases que requieren relacionarse (como una orden y un cliente), mediante UML y el diagrama de clases de representa mediante una línea y en algunos casos incluye una flecha siguiendo la estructura de una oración. Esta flecha apunta al objeto y el otro extremo representa al sujeto.


Relación unidireccional

Código ejemplo

package com.asociacionSimple;

public class Moneda {
    private Integer idMoneda;
    private String nombre;
    private String simbolo;

    public Moneda(Integer idMoneda, String nombre, String simbolo) {
        this.idMoneda = idMoneda;
        this.nombre = nombre;
        this.simbolo = simbolo;
    }

    public String getSimbolo() {return simbolo;}

    public void setSimbolo(String simbolo) {
        this.simbolo = simbolo;
    }

    public Integer getIdMoneda() {return idMoneda;}

    public void setIdMoneda(Integer idMoneda) {
        this.idMoneda = idMoneda;
    }

    public String getNombre() {return nombre;}

    public void setNombre(String nombre) {
        this.nombre = nombre;
    } 
}

package com.asociacionSimple;

public class Producto {
    private Integer idProducto;
    private String codigo;
    private Float precio;
    private Integer stock;
    private Moneda moneda;

    public Producto(Integer idProducto, String codigo, Float precio, Integer stock) {
        this.idProducto = idProducto;
        this.codigo = codigo;
        this.precio = precio;
        this.stock = stock;
    }

    public Moneda getMoneda() {return moneda;}

    public void setMoneda(Moneda moneda) {
        this.moneda = moneda; //Análogo a "agregar moneda"
    }

    public Integer getIdProducto() {return idProducto;}

    public void setIdProducto(Integer idProducto) {
        this.idProducto = idProducto;
    }

    public String getCodigo() {return codigo;}

    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }

    public Float getPrecio() {return precio;}

    public void setPrecio(Float precio) {
        this.precio = precio;
    }

    public Integer getStock() {return stock;}

    public void setStock(Integer stock) {
        this.stock = stock;
    }    
}

Relación bidireccional

Agregación

Es un tipo especial de asociación entre clases conocido como: “contiene a” o “es contenido en”. Ambas clases tiene una vida independiente, pero una de estas (llamada invitado) trabaja en orden a otra (huésped). Esto le permite a huésped usar características de invitado en la ejecución de algunas tareas.

Se representa con una línea con rombo blanco, donde el rombo esta en el huésped y el otro lado en el invitado.

Código ejemplo

package com.agregacion;

public class Punto {
    
    private Integer x;
    private Integer y;

    public Punto(Integer x, Integer y) {
        this.x = x;
        this.y = y;
    }

    public Integer getY() {return y;}

    public void setY(Integer y) {this.y = y;}

    public Integer getX() {return x;}

    public void setX(Integer x) {this.x = x;}     
}
package com.agregacion;

public class Figura {
    //Cuadrilatero asumido
    private Punto p1;
    private Punto p2;
    private Punto p3;
    private Punto p4;

    public Figura(Punto p1, Punto p2, Punto p3, Punto p4) {
        this.p1 = p1;
        this.p2 = p2;
        this.p3 = p3;
        this.p4 = p4;
    }

    public Punto getP1() {return p1;}

    public void setP1(Punto p1) {this.p1 = p1;}

    public Punto getP2() {return p2;}

    public void setP2(Punto p2) {this.p2 = p2;}
    
    public Punto getP3() {return p3;}

    public void setP3(Punto p3) {this.p3 = p3;}

    public Punto getP4() {return p4;}

    public void setP4(Punto p4) {this.p4 = p4;}
}

Composición de clases

Tipo especial de agregación. Conocida como "es parte de" o "es un todo de". En este caso las dos partes necesitan de ellas para existir (una no existe sin la otra), de manera que existe una clase (todo) que utiliza características de otra (parte) para la ejecución de alguna tarea.

Se representa con un rombo relleno, que esta junto al "todo" y al otro extremo la "parte".



Código ejemplo

package com.composicion;

public class Vehiculo {

    private Motor motor;
    private Transmision transmision;
    private Rueda ruedaDelantera;
    private Rueda ruedaTrasera;

    public Vehiculo(String motor, String transmision, String ruedaDelantera, String ruedaTrasera) {
        this.motor = new Motor(motor);
        this.transmision = new Transmision(transmision);
        this.ruedaDelantera = new Rueda(ruedaDelantera);
        this.ruedaTrasera = new Rueda(ruedaTrasera);
    }

    public Motor getMotor() {
        return motor;
    }

    public void setMotor(Motor motor) {
        this.motor = motor;
    }

    public Transmision getTransmision() {
        return transmision;
    }

    public void setTransmision(Transmision transmision) {
        this.transmision = transmision;
    }

    public Rueda getRuedaDelantera() {
        return ruedaDelantera;
    }

    public void setRuedaDelantera(Rueda ruedaDelantera) {
        this.ruedaDelantera = ruedaDelantera;
    }

    public Rueda getRuedaTrasera() {
        return ruedaTrasera;
    }

    public void setRuedaTrasera(Rueda ruedaTrasera) {
        this.ruedaTrasera = ruedaTrasera;
    }  
}


Clases genéricas

Java Generics

Java permite que los programadores puedan crear clases, interfaces y métodos en los que el tipo de datos sobre los que operan se especifica como parámetro. Es decir, de tipos parametrizados.

A estos se les denomina genéricos. Por ejemplo, una clase que maneja estos parámetros se denomina clase genérica, igualmente será con un método o interfaz.

Un método genérico debe ser declarado dentro de una clase o interfaz genérica. Para ello, empleamos la siguiente sintaxis:
   // Clase genérica
   public class Generico<T>

   //Interfaz genérica
   public interface Generico<T,E>

La ventaja del código que emplea estos métodos es que funcionará automáticamente con el tipo de datos pasados a su parámetro de tipo.
   // Instanciación de la clase genérica
   Generico<String> gen = new Generico<>();
   // En este caso el tipo de dato es un String


Estos algoritmos son muy útiles para y se emplean muchísimo en las bibliotecas internas de Java como en las Colecciones o métodos de ordenamiento rápido.

Clase genérica simple- Código

Declaramos el tipo genérico T y un atributo de ese tipo llamado "atributo"
package clases;

public class Generico<T> {

    private T atributo;

    public Generico(T atributo) {
        this.atributo = atributo;
    }

    public String getClase() {
        return String.format("Clase: %s", this.atributo.getClass().getName());
    }

    public String getAtributo() {
        return String.format("Contenido: %s", this.atributo.toString());
    }

}

Prueba y resultado

Al crear objetos de estas clases genéricas podemos emplear 3 formas:
  • Indicar dentro de la sintaxis diamante el tipo
  • Usar el tipo desconocido ?, el constructor recibe el tipo de parámetro
  • Obviar el tipo, el constructor recibe el parámetro y usa su tipo.
package test;

import clases.ContenedorGenerico;
import clases.Generico;
import clases.Operador;

public class Test {

    public static void main(String[] args) {
        Generico<String> gen1 = new Generico<>("Hola");
        System.out.println(gen1.getClase());
        System.out.println(gen1.getAtributo());
        
        Generico<?> gen2 = new Generico(45d);
        System.out.println(gen2.getClase());
        System.out.println(gen2.getAtributo());
        
        Generico gen3 = new Generico(true);
        System.out.println(gen3.getClase());
        System.out.println(gen3.getAtributo());        

    }
    
}

Clase: java.lang.String
Contenido: Hola

Clase: java.lang.Double
Contenido: 45.0

Clase: java.lang.Boolean
Contenido: true


Clase genérica con varios parámetros - Código

Podemos indicar más de un tipo genérico, estos van separados por comas.
package clases;

import java.util.HashMap;
import java.util.Map;

public class ContenedorGenerico<E,F> {

    private Map<E, F> contenedor;

    public ContenedorGenerico() {
        this.contenedor = new HashMap<>();
    }

    public void agregar(E clave, F valor) {
        this.contenedor.put(clave, valor);
    }

    public Map<E, F> getContenedor() {
        return this.contenedor;
    }
}

Prueba y resultado

Las colecciones emplean internamente las clases y métodos genéricos.
package test;

import clases.ContenedorGenerico;
import clases.Generico;
import clases.Operador;

public class Test {

    public static void main(String[] args) {
        
        ContenedorGenerico<Integer,String> contenedor = new ContenedorGenerico<>();
        contenedor.agregar(12, "doce");
        contenedor.agregar(11, "once");
        contenedor.agregar(10, "diez");
        
        contenedor.getContenedor().forEach((k,v)->{
            System.out.println("Clave: "+k);
            System.out.println("Valor: "+v);            
        });
    }
    
}

Clave: 10
Valor: diez

Clave: 11
Valor: once

Clave: 12
Valor: doce


Clase genérica con parámetros limitados - Código

Para limitar el tipo de datos que se pueden recibir se utiliza la palabra reservada "extends" y luego la superclase. Por ejemplo, el siguiente código muestra una clase que solo permite tener parámetros de tipo numéricos.
package clases;

public class Operador<A extends Number, B extends Number> {

    A valorA;
    B valorB;

    public Operador(A valorA, B valorB) {
        this.valorA = valorA;
        this.valorB = valorB;
    }

    public Double getSuma() {
        return this.valorA.doubleValue() + this.valorB.doubleValue();
    }

    public Double getProducto() {
        return this.valorA.doubleValue() * this.valorB.doubleValue();
    }
}

Prueba y resultado

package test;

import clases.ContenedorGenerico;
import clases.Generico;
import clases.Operador;

public class Test {

    public static void main(String[] args) {
        
        Operador op1 = new Operador(4, 5);
        System.out.println("Suma: " + op1.getSuma());
        System.out.println("Producto: " + op1.getProducto());
        
        Operador op2 = new Operador(4.6, 5);
        System.out.println("Suma: " + op2.getSuma());
        System.out.println("Producto: " + op2.getProducto());
        
        Operador op3 = new Operador(2.5, 1.65);
        System.out.println("Suma: " + op3.getSuma());
        System.out.println("Producto: " + op3.getProducto());
    }
    
}

Suma: 9.0
Producto: 20.0

Suma: 9.6
Producto: 23.0

Suma: 4.15
Producto: 4.125


miércoles, 17 de junio de 2020

Mostrar imágenes en JSP con Servlet

Consideramos la clase "Espacios" que proviene de la siguiente estructura SQL (Se ha obviado intencionalmente a la clave foránea en el campo "tipo"):
-- -----------------------------------------------------
-- Table espacios
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS espacios (
  idespacios INT NOT NULL AUTO_INCREMENT,
  piso TINYINT NOT NULL,
  precio DOUBLE(6,2) NOT NULL,
  ubicacion VARCHAR(25) NULL,
  tipo TINYINT NULL,
  imagen BLOB NULL,
  PRIMARY KEY (idespacios)
  )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


Su clase en Java con el patrón DTO sería:
package dto;

public class Espacios {

    private Integer idespacios;
    private Integer piso;
    private Double precio;
    private String ubicacion;
    private Integer tipo;
    private byte[] imagen;

    public Espacios() {
    }

    /* Métodos Setter y getter */

}


El atributo imagen no se emplea, pero será de utilidad si convertimos el proyecto a uno de escritorio.
Su Interfaz e implementación DAO son:
package dao;

import java.util.List;
import dto.Espacios;

public interface DaoEspacios {

    public byte[] espaciosImg(Integer id);

    public String getMessage();
}

package dao.impl;

import biblioteca.ConectaBD;
import dao.DaoEspacios;
import dto.Espacios;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DaoEspaciosImpl implements DaoEspacios {

    private final ConectaBD conectaDb;
    private String mensaje;

    public DaoEspaciosImpl() {
        this.conectaDb = new ConectaBD();
    }

    @Override
    public byte[] espaciosImg(Integer id) {
        byte[] img = null;
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("imagen")
                .append(" FROM espacios WHERE idespacios = ?");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setInt(1, id);
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    Blob blob = rs.getBlob(1);
                    if (blob != null) {
                        byte[] bytes = blob.getBytes(1, (int) blob.length());
                        blob.free();
                        img = bytes;
                    }
                } else {
                    img = null;
                }
            } catch (SQLException e) {
                mensaje = e.getMessage();
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return img;
    }

    @Override
    public String getMessage() {
        return mensaje;
    }
}


El servlet que permite mostrar la imagen sería:
package web.servlet;

import biblioteca.DeString;
import dao.DaoEspacios;
import dao.impl.DaoEspaciosImpl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "ImagenServlet", urlPatterns = {"/Imagen"})
public class ImagenServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("image/jpg");
        DaoEspacios daoEspacios = new DaoEspaciosImpl();
        Integer id = DeString.aInteger(request.getParameter("id"));
        try {
            byte[] data = daoEspacios.espaciosImg(id);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            output.write(data, 0, data.length);
            response.setContentLength(output.size());
            try (OutputStream out = response.getOutputStream()) {
                output.writeTo(out);
                out.flush();
            }
        } catch (IOException ex) {
            System.err.println(String.format("%s - %s", daoEspacios.getMessage(), ex.getMessage()));
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }
}


El URL para mostrar una imagen sería por ejemplo: http://localhost:8084/Demo/Imagen?id=8 donde el valor que cambia es el número "8" por el "id" del registro del que se desea mostrar la imagen.

Ejemplo:

Dentro de un JSP el código tendría la siguiente forma:

      <img src="Imagen?id=8" alt="img"/>
   


Ese valor 8 se puede reemplazar con código de manera que recibe el "id" esperado como en esta porción de código que captura el id mediante una estructura que lista todos los espacios con JSTL.

      <img src="Imagen?id=${f.idespacios}" alt="img"/>
   




lunes, 15 de junio de 2020

Colecciones List

List es parte del Java Collection Framework. Esta es una interfaz que tiene como superinterfaz a Collection y este a su vez a Iterable. De manera que una implementación de List puede emplear los métodos declarados en Collection e Iterable.

Esta es una colección ordenada de objetos (secuencia) en la que cada elemento tiene una posición.Por lo tanto, el usuario tiene control sobre cada uno de sus elementos a través de un índice entero (index). Además, esta interfaz define métodos para consultar o establecer el elemento en una posición particular.

Una colección de este tipo se asemeja a un array cuyo tamaño cambia según sea necesario para acomodar la cantidad de elementos que contiene. A diferencia de las Interfaces Set, esta permite que se tengan elementos duplicados.

Se pueden implementar objetos que empleen los métodos de esta interfaz a través de las clases:
  • ArrayList
  • LinkedList
  • CopyOnWriteArrayList
  • Vector
  • Stack

Clase ArrayList

ArrayList es una estructura de datos similar a los arrays, pero mientras en los arrays se debe definir la longitud o tamaño de este, en los ArrayList no es necesario, esto genera una simplicidad al programador para agregar, recorrer, modificar o eliminar sus elementos.

Se puede crear una colección de tipo ArrayList mediante la interfaz List o directamente como una clase.

package test;

import java.util.ArrayList;

public class Test {

    public static void main(String[] args) {

        /* Creando la estructura de datos*/
        ArrayList<string> lista = new ArrayList<>();

        /*Agregando elementos*/
        lista.add("Juan");
        lista.add("Luis");
        lista.add("Carlos");
        lista.add("Ana");
        lista.add("Alberto");

        /*Listando los elementos*/
        lista.forEach((nom) -> {
            System.out.println("Nombre: " + nom);
        });

        /* Tamaño de la estructura "size()" */
        System.out.println("Tamaño: " + lista.size());
        System.out.println("----------------");

        /* Modificando un valor */
        System.out.println("Valor inicial: " + lista.get(2));
        lista.set(2, "Reemplazado"); //Indicamos el index
        System.out.println("Valor modificado: " + lista.get(2));
        System.out.println("----------------");

        /* Eliminando un registro por contenido o index*/
        lista.remove("Ana"); // lista.remove(3);
        lista.forEach((nom) -> {
            System.out.println("Nombre: " + nom);
        });
        System.out.println("----------------");

        /* Agregar al inicio o al final */
        lista.add(0,"Ada");
        lista.add(lista.size(),"Veronica");
        lista.forEach((nom) -> {
            System.out.println("Nombre: " + nom);
        });
        System.out.println("----------------");       
    }

}


Resultado:
Nombre: Juan
Nombre: Luis
Nombre: Carlos
Nombre: Ana
Nombre: Alberto
Tamaño: 5
----------------
Valor inicial: Carlos
Valor modificado: Reemplazado
----------------
Nombre: Juan
Nombre: Luis
Nombre: Reemplazado
Nombre: Alberto
----------------
Nombre: Ada
Nombre: Juan
Nombre: Luis
Nombre: Reemplazado
Nombre: Alberto
Nombre: Veronica
----------------


Clase LinkedList

LinkedList es una estructura de datos lineal que se asemeja a los arrays. la gran diferencia es que los elementos dentro de esta clase no están almacenados de forma contigua como en los arrays. sino que se vinculan entre sí mediante punteros. Cada elemento de LinkedList tiene la referencia (dirección / puntero) al siguiente elemento de LinkedList.

Se puede crear una colección de tipo LinkedList mediante las interfaces List o Deque, o directamente como una clase.
package test;

import java.util.LinkedList;

public class Test {

    public static void main(String[] args) {

        /* Creando la estructura de datos*/
        LinkedList<string> lista = new LinkedList<>();

        /*Agregando elementos*/
        lista.add("Juan");
        lista.add("Luis");
        lista.add("Carlos");
        lista.add("Ana");
        lista.add("Alberto");

        /*Listando los elementos*/
        lista.forEach((nom) -> {
            System.out.println("Nombre: " + nom);
        });

        /* Tamaño de la estructura "size()" */
        System.out.println("Tamaño: " + lista.size());
        System.out.println("----------------");

        /* Modificando un valor */
        System.out.println("Valor inicial: " + lista.get(2));
        lista.set(2, "Reemplazado"); //Indicamos el index
        System.out.println("Valor modificado: " + lista.get(2));
        System.out.println("----------------");

        /* Eliminando un registro por contenido o index*/
        lista.remove("Ana"); // lista.remove(3);
        lista.forEach((nom) -> {
            System.out.println("Nombre: " + nom);
        });
        System.out.println("----------------");

        /* Agregar al inicio o al final */
        lista.addFirst("Ada");
        lista.addLast("Veronica");
        lista.forEach((nom) -> {
            System.out.println("Nombre: " + nom);
        });
        System.out.println("----------------");

        /* Capturar un valor y eliminarlo */
        String primero = lista.pollFirst();
        System.out.println("Nombre eliminado: " + primero);
        lista.forEach((nom) -> {
            System.out.println("Nombre: " + nom);
        });
        System.out.println("----------------");
    }

}


Resultado:
Nombre: Juan
Nombre: Luis
Nombre: Carlos
Nombre: Ana
Nombre: Alberto
Tamaño: 5
----------------
Valor inicial: Carlos
Valor modificado: Reemplazado
----------------
Nombre: Juan
Nombre: Luis
Nombre: Reemplazado
Nombre: Alberto
----------------
Nombre: Ada
Nombre: Juan
Nombre: Luis
Nombre: Reemplazado
Nombre: Alberto
Nombre: Veronica
----------------
Nombre eliminado: Ada
Nombre: Juan
Nombre: Luis
Nombre: Reemplazado
Nombre: Alberto
Nombre: Veronica
----------------



Comparación entre ArrayList y LinkedList


ArrayList LinkedList
Internamente emplea una matriz dinámica para almacenar los elementos. Internamente utiliza una lista doblemente vinculada para almacenar los elementos.
La manipulación es lenta, porque internamente usa una matriz. Si se elimina algún elemento de la matriz, todos los bits se desplazan en la memoria. La manipulación es rápida, porque utiliza una lista doblemente vinculada, por lo que no se requiere ningún cambio en la memoria.
Puede actuar como una lista solo porque implementa solo a la interfaz List. Puede actuar como una lista y una cola, ya que implementa las interfaces List y Deque.
Es la mejor opción para almacenar y acceder a datos. Es la mejor opción para manipular datos.


miércoles, 10 de junio de 2020

Java Server Faces Page Navigation

Antes de la versión 2.0 de JSF se debía crear reglas de navegación en el archivo faces-config.xml y declarar el destino en el método, pero desde esta versión se puede reemplazar ambos simplemente declarando un valor de retorno String como se muestra en el siguiente "Bean"

package proyectoJSF.view;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class NavigationView {

   private String mensaje;

   public String viaje1() {
      mensaje = "Llego al destino #1";
      return "destino1"; // return "destino.xhtml"
   }
 
   public String viaje2() {
      mensaje = "Llego al destino #2";
      return "destino2?faces-redirect=true";
   }
 
   public void viaje3() {
      mensaje = "Llego al destino #3";
      //retorno vacío o "null"
   }

   /* Métodos Setter y Getter*/
   public String getMensaje() {
      return mensaje;
   }

   public void setMensaje(String mensaje) {
      this.mensaje = mensaje;
   } 

}

Y tendríamos la siguiente estructura de archivos html y xhtml

Donde los códigos son:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Proyecto Demo de JSF</title>
</head>
<body>
   <h1>Probando JSF</h1>
   <hr />
   <a href="prueba1.xhtml">Prueba #1</a>
   <br/><br/>
   <a href="prueba2.xhtml">Prueba #2</a>
</body>
</html>

prueba2.xhtml
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
 xmlns:f="http://xmlns.jcp.org/jsf/core"
 xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
   <title>Prueba 02</title>
</h:head>
<h:body>
   <h1>Navegación</h1>
   <h:form>
      <h:commandButton value="Viaje 1" action="#{navigationView.viaje1()}">
      </h:commandButton>
      <br/><br/>
      <h:commandButton value="Viaje 2" action="#{navigationView.viaje2()}">   
      </h:commandButton>
      <br/><br/>
      <h:commandButton value="Viaje 3" action="#{navigationView.viaje3()}">
         <f:ajax execute="@form" render=":salida" />
      </h:commandButton>
   </h:form>
   <h:outputText id="salida" value="#{navigationView.mensaje}" />
</h:body>
</html>

destino1.xhtml y destino2.xhtml tienen un código similar
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
 xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
   <title>Destino 01</title>
</h:head>
<h:body>
   <h1>Bienvenido al destino 01</h1>
   <h:outputText id="output" value="#{navigationView.mensaje}" />
</h:body>
</html>

Con el siguiente resultado visual en prueba2.xhtml:

Clic en la miniatura para ver la imagen completa


Y los resultados de cada uno de los botones, mostrando la navegación entre páginas.


Clic en la miniatura para ver la imagen completa

Java Server Faces Tag Library

Componentes estándar de HTML 

JSF proporciona un conjunto de componentes para crear HTML con la ayuda de la tecnología de visualización Facelets.

Esos componentes HTML están disponibles en el URI (Uniform Resource Identifier) http://xmlns.jcp.org/jsf/html que debe asignarse al prefijo "h" del espacio de nombres XML como se muestra en el siguiente código en la línea 4:
<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Título</title>
    </h:head>
    <h:body>
        <!--Cuerpo de la página-->
    </h:body>
</html>

Los elementos más importantes para una página JSF deben ser los de <h:head> y <h:body> para luego incluir dentro los demás componentes HTML, sin estos la tecnología JSF no podrá incluir a los recursos de JS u hojas de estilo que se asocian con determinados componentes.

El código anterior generaría una página HTML como la siguiente:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Título</title>
    </head>
    <body>
        <!--Cuerpo de la página-->
    </body>
</html>

Tabla de componentes HTML de JSF
Component tag (Etiqueta del componente) Superclase del componente Salida en HTML
U<h:column> UIColumn <td>
U<h:commandButton> UICommand <input type="submit">
U<h:commandLink> UICommand <a onclick="form.submit()">
U<h:commandScript> UICommand <script>
U<h:dataTable> UIData <table>
U<h:form> UIForm <form method="post">
U<h:graphicImage> UIGraphic <img>
U<h:inputFile> UIInput <input type="file">
U<h:inputHidden> UIInput <input type="hidden">
U<h:inputSecret> UIInput <input type="password">
U<h:inputText> UIInput <input type="text">
U<h:inputTextarea> UIInput <textarea>
U<h:selectBooleanCheckbox> UIInput <input type="checkbox">
U<h:selectManyCheckbox> UIInput <table><input type="checkbox">
U<h:selectManyListbox> UIInput <select multiple size="n"><option>
U<h:selectManyMenu> UIInput <select multiple size="1"><option>
U<h:selectOneListbox> UIInput <select size="n"><option>
U<h:selectOneMenu> UIInput <select size="1"><option>
U<h:selectOneRadio> UIInput <table><input type="radio">
U<h:selectOneRadio group> UIInput <input type="radio" name="group">
U<h:message> UIMessage <span>
U<h:messages> UIMessages <ul>
U<h:messages layout=table> UIMessages <table>
U<h:button> UIOutcomeTarget <button onclick="window.location">
U<h:link> UIOutcomeTarget <a>
U<h:body> UIOutput <body>
U<h:doctype> UIOutput <!DOCTYPE>
U<h:head> UIOutput <head>
U<h:outputFormat> UIOutput <span>
U<h:outputLabel> UIOutput <label>
U<h:outputText> UIOutput <span>
U<h:outputScript> UIOutput <script>
U<h:outputStylesheet> UIOutput <link rel="stylesheet">
U<h:panelGrid> UIPanel <table>
U<h:panelGroup> UIPanel <span>
U<h:panelGroup layout=block> UIPanel <div>


Componentes estándar del Core

JSF proporciona un conjunto de componentes "Core" que dan soporte a configurar declarativamente uno o más componentes de destino HTML.

Esos componentes HTML están disponibles en el URI (Uniform Resource Identifier) http://xmlns.jcp.org/jsf/core que debe asignarse al prefijo "f" del espacio de nombres XML como se muestra en el siguiente código en la línea 5:
<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>Título</title>
    </h:head>
    <h:body>
        <!--Cuerpo de la página-->
    </h:body>
</html>

Dentro del tenemos:
Core tag Constructores o manejadores Componente destino
<f:actionListener> javax.faces.event.ActionListener ActionSource
<f:ajax> javax.faces.component.behavior.AjaxBehavior ClientBehaviorHolder(s)
<f:attribute> UIComponent#getAttributes() UIComponent
<f:attributes> UIComponent#getAttributes() UIComponent
<f:convertDateTime> javax.faces.convert.DateTimeConverter (Editable)ValueHolder
<f:convertNumber> javax.faces.convert.NumberConverter (Editable)ValueHolder
<f:converter> javax.faces.convert.Converter (Editable)ValueHolder
<f:event> javax.faces.event.ComponentSystemEvent UIComponent
<f:facet> UIComponent#getFacets() UIComponent
<f:importConstants> javax.faces.component.UIImportConstants UIViewRoot
<f:loadBundle> java.util.ResourceBundle UIViewRoot
<f:metadata> javax.faces.view.ViewMetadata UIViewRoot
<f:param> javax.faces.component.UIParameter UIComponent
<f:passthroughAttribute> UIComponent#getPassthroughAttributes() UIComponent
<f:passthroughAttributes> UIComponent#getPassthroughAttributes() UIComponent
<f:phaseListener> javax.faces.event.PhaseListener UIViewRoot
<f:selectItem> javax.faces.component.UISelectItem UISelectOne/UISelectMany
<f:selectItems> javax.faces.component.UISelectItems UISelectOne/UISelectMany
<f:setPropertyActionListener> javax.faces.event.ActionListener ActionSource
<f:subview> javax.faces.component.NamingContainer UIComponents
<f:validateBean> javax.faces.validator.BeanValidator UIForm
<f:validateDoubleRange> javax.faces.validator.DoubleRangeValidator EditableValueHolder
<f:validateLength> javax.faces.validator.LengthValidator EditableValueHolder
<f:validateLongRange> javax.faces.validator.LongRangeValidator EditableValueHolder
<f:validateRegex> javax.faces.validator.RegexValidator EditableValueHolder
<f:validateRequired> javax.faces.validator.RequiredValidator EditableValueHolder
<f:validateWholeBean> javax.faces.validator.BeanValidator UIForm
<f:validator> javax.faces.validator.Validator EditableValueHolder
<f:valueChangeListener> javax.faces.event.ValueChangeListener EditableValueHolder
<f:view> javax.faces.component.UIViewRoot UIComponents
<f:viewAction> javax.faces.component.UIViewAction UIViewRoot
<f:viewParam> javax.faces.component.UIViewParameter UIViewRoot
<f:websocket> javax.faces.component.UIWebsocket UIViewRoot

Herramienta CDI para JSF en Eclipse

Para trabajar con el Framework JSF se debe realizar algunas configuraciones en el IDE, en este caso se procede a la configuración del IDE Eclipse.


Instalación de JBoss Tool Plug-in

La versión estándar para Java EE de Eclipse requiere de una herramienta que pueda dar soporte a CDI.

"CDI define contextos para especificar y gestionar ciclos de vida de bean y utiliza inyección de dependencias para satisfacer las dependencias declaradas de una forma dinámica y con seguridad de tipos. CDI también utiliza un modelo de suceso e interceptor acoplado ligeramente, y proporciona un mecanismo de ampliación portátil potente y flexible para otras infraestructuras para definir sus propios beans de CDI o actualizar los componentes existentes."

Para ello, nos dirigimos al Marketplace de Eclipse como se muestra en la siguiente imagen


Dentro se buscará el complemento "JBoss Tool" y se instalará el mostrado.


Luego se hallarán múltiples elementos, pero solo se requiere la herramienta CDI como se muestra


Luego se debe proceder a aceptar los términos de acuerdo de licencia para posteriormente reiniciar el IDE Eclipse.




Fuente