lunes, 27 de octubre de 2014

Tutorial JSF 2.2 - Sesión 9: Lenguaje de expresiones

Tutorial JSF 2.2 - Sesión 9: Lenguaje de expresiones
Seguimos con nuestro recorrido por las características de JSF 2.2 . Esta vez veremos el Lenguaje de Expresiones, o también conocido como EL (Expression Language).

El EL es usado en varias tecnologías de JavaEE, tales como JSF, JSP y CDI. Además lo podemos encontrar en entornos stand-alone. Lo que veremos ahora solo es cuando se ejecuta en contenedores Java EE.

Las expresiones nos permite acceder a los datos de los componentes JavaBean. Como sabemos, un JavaBean (no confundir con Enterprise JavaBean) debe tener el siguiente formato:

  • Las propiedades deben accederse usando los métodos con prefijo set para poner un valor y get para obtener un valor. Para los valores boolean se puede utilizar get o is, el resultado es el mismo.
  • Después del prefijo, debe comenzar el nombre con mayúscula
  • Los métodos set solo deben tener un único parámetro
  • Los métodos get no deben tener ningún parámetro.
  • Los métodos son public
Ejemplo:
public void setNombre(String nombre){
 //...
}
public String getNombre(){
 //...
}
public boolean isActivo(){
  //...
}

Y para accederlo desde un EL, simplemente se utiliza el nombre sin el prefijo, pero comenzando con minúsculas
<c:if test="#{sessionScope.persona.activo}">
   Hola #{sessionScope.persona.nombre}
...
</c:if>

Para abreviar, el EL proporciona una manera simple - usando expresiones - para realizar las siguientes tareas:
  • Leer dinámicamente datos almacenados en los componentes JavaBeans, diversas estructuras de datos y objetos implícitos
  • Escribir dinámicamente datos, tales como entradas de formularios a componentes JavaBeans.
  • Invocar arbitrariamente métodos públicos y estáticos.
  • Realizar operaciones aritméticas, lógicas y de cadena.
  • Construir colecciones de objetos y realizar operaciones en colecciones.

Sintaxis de evaluación de expresiones

Existen dos maneras para evaluar una expresión: 
  • De manera inmediata 
  • De manera diferida.
La manera inmediata se hace cuando se necesita que el valor del componente bean se escriba directamente cuando construye la página. Para ello se utiliza la sintaxis ${}

<c:out value="${persona.nombre}" />

La manera diferida se utiliza cuando el valor a obtener debe pasar por todo el ciclo de vida. Se pueden utilizar para:

  • Leer y escribir datos
  • Utilizar expresiones de método

<h:inputText value="#{persona.nombre}" />
<h:outputText value="#{persona.calcularRenta(tasa.ingreso)}" />

Referenciando expresiones

Para mostrar o manejar las expresiones de objetos, se hace simplemente (como se vió hasta ahora) con  la declaración tal cual
#{persona.nombre}

también podemos invocar a la misma propiedad usando corchetes:
#{persona["nombre"]}

Con esto, como podrás imaginar, podrías invocar a cada propiedad de una manera dinámica
#{persona[campoActual]}

Donde campoActual es una variable de tipo String que contiene el nombre del campo a mostrar.
#{ valor == objeto.campo }

Si tenemos una clase enum:
public enum Estado {
   activo,enProceso,suspendido,terminado
} 

.. también podemos invocarlo desde la expresión:
#{ estado == estado.activo }

Los arreglos también se pueden acceder usando un índice entre corchetes
#{cliente.pedidos[1]}

También podemos manipular mapas (java.util.Map). Supongamos que la propiedad pedidos es un java.util.Map con el key de tipo String, y queremos acceder al pedido con key "teclado". Estas dos líneas hacen lo mismo:
#{cliente.pedido["teclado"]}
#{cliente.pedido.teclado}

Es decir, manipula los maps como si fueran propiedades de un objeto.

Lambda

También podemos usar las expresiones Lambda. A pesar que son parte de Java SE 8, se pueden usar en expresiones EL de Java EE 7 con Java SE 7.

Para probar las expresiones lambda en Java SE debemos agregar la biblioteca respectiva a nuestro proyecto. Por ello - para efectos de este ejemplo - agregaremos la siguiente dependencia a nuestro proyecto Maven.

        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.el</artifactId>
            <version>[3.0-b03,)</version>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>

Y usaremos el paquete javax.el.*. Para nuestro ejemplo usaremos el siguiente código:
    void eval(String input) {
        System.out.println("\n====");
        System.out.println("Cadena EL: " + input);
        Object ret = elp.eval(input); //aquí evaluamos el contenido
        System.out.println("Valor obtenido: " + ret);
    }

Las expresiones Lambda usan el operador flecha (->). Los identificadores que se encuentran a la izquierda del operador son llamados parámetros lambda. El cuerpo, que se encuentra a la derecha del operador, pueden ser expresiones EL. Los parámetros lambda pueden estar envueltos en signos de paréntesis, y pueden ser omitidos si solo tienen un parámetro.
x -> x+1
(x,y) -> x + y
() -> 64

Las expresiones lambda pueden ser utilizadas como una función, y se pueden invocar inmediatamente:
((x,y)-> x + y)(3,4)

.. e imprime 7

También se pueden usar en conjunción con un asignamiento, separados por un punto y coma (;)
 v = (x,y) -> x + y; v(3,4)

v es la función lambda creada, y después se invoca con v(3,4)




Operaciones con colecciones

EL permite operaciones de colecciones de objetos: conjuntos (set), listas y mapas. Permite la creación dinámica de colecciones de objetos, los cuales pueden ser manipulados por streams y pipelines.

Al igual que las expresiones lambda, las operaciones sobre colecciones de objetos son parte de Java SE 8, pero podemos usar estas expresiones EL en Java EE 7 sobre Java SE 7.

Veamos: así creamos un par de conjuntos (set):

{1,2,3}
{"Ana","Beto","Carlos"}


Para construir una lista, es como sigue... además podemos hacer que una lista contenga diferentes tipos:

["Abraham","Bart","Carl"]
[1,"dos",[tres,cuatro]]


Las variables tres y cuatro deben existir

    void run() {
        eval("nums={1,2,3}");
        eval("noms={'Ana','Beto','Carlos'}");
        eval("noms2=['Abraham','Bart','Carl']");
        eval("tres=3;cuatro='4'");
        eval("lista=['Abraham','Bart','Carl']");
        eval("lista2=[1,'dos',[tres,cuatro]]");
        
    }



Ok, ok, he mostrado el EL en un Java SE, pero la idea es mostrar en un JSF. Aquí va el ejemplo. Primer código:
<?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://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Ejemplos de EL</title>
    </h:head>
    <h:body>
        <h1>Ejemplos de EL</h1>
        ${lista= [512,128,65] }
    </h:body>
</html>




Y cuando se ejecuta, aparece...



Todo bien, todo normal. Ahora con la ayuda de nuestro super IDE NetBeans, a la variable que acabamos de crear vamos a ordenarlo. Vean qué pasa cuando escribimos el nombre de la variable lista seguido del punto (.)

Automáticamente, el IDE sabe que ese objeto es una lista y nos mostrará las propiedades de esa lista.... y de sus objetos

Por tanto, ejecutamos el código:
<?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://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Ejemplos de EL</title>
    </h:head>
    <h:body>
        <h1>Ejemplos de EL</h1>
        ${lista= [512,128,65].stream().sorted().toList() }
    </h:body>
</html>


Y el resultado es lo esperado:

Operadores

Son los clásicos que conocemos
  • Aritméticos: +, -, *, /, div, %, mod, - (signo negativo)
  • Concatenación de cadenas: +=
  • Lógicos: and, &&, or, ||, not, !
  • Relacional: ==, eq, !=, ne, <, lt, >, gt, <=, ge, >=, le
  • Si es vacío: El operador empty determina si una lista está vacía o un objeto es nulo
  • Condicional: A ? B : C (Lo mismo que en Java SE)
  • Lambda: ->(ya lo conocemos)
  • Asignación: =
  • Punto y coma: ;

En esta página podremos encontrar varios ejemplos de expresiones EL http://docs.oracle.com/javaee/7/tutorial/doc/jsf-el007.htm

Bibliografía

Me basé en el siguiente tutorial 9 Expression Language, y para más detalle sobre esta especificación, visitar la página del JSR 341 http://www.jcp.org/en/jsr/detail?id=341

Si te gustó, hazlo saber.. y si crees que es útil, compártelo. Es gratis