¿Qué es JSF? Presentación de JavaServer Faces

JavaServer Faces (JSF) es la tecnología estándar de Java para crear interfaces web basadas en componentes y orientadas a eventos. Como JavaServer Pages (JSP), JSF permite el acceso a datos y lógica del lado del servidor. A diferencia de JSP, que es esencialmente una página HTML imbuida de capacidades del lado del servidor, JSF es un documento XML que representa componentes formales en un árbol lógico. Los componentes JSF están respaldados por objetos Java, que son independientes del HTML y tienen la gama completa de capacidades de Java, incluido el acceso a bases de datos y API remotas.

La idea clave de un marco como JSF es encapsular (o envolver ) tecnologías del lado del cliente como HTML, CSS y JavaScript, lo que permite a los desarrolladores crear interfaces web sin mucha interacción con estas tecnologías.

Este artículo presenta una instantánea del enfoque de JSF para el desarrollo de interfaces de usuario basadas en componentes para aplicaciones web Java. Los ejemplos simples presentan la arquitectura MVC, el modelo de eventos y la biblioteca de componentes de JSF. Los ejemplos incluyen nuevas características en JSF 2.3 y usaremos PrimeFaces para nuestra biblioteca de componentes.

JSF en evolución

JSF, de gran popularidad, se ha enfrentado recientemente a la competencia de los marcos web compatibles con Java, incluidos los marcos de JavaScript del lado del cliente. Aún así, JavaServer Faces sigue siendo el estándar de Java, especialmente para el desarrollo empresarial Java a gran escala. La especificación JSF también ha generado una gran cantidad de marcos y bibliotecas, que se han mantenido al día con las mejoras recientes del lado del cliente. Uno de ellos es PrimeFaces, que exploramos en este tutorial.

Si bien el programa para el desarrollo futuro no está claro, JSF 2.3 ofrece a los desarrolladores mucho con qué trabajar mientras esperamos. Lanzado en marzo de 2017, JSF 2.3 fue diseñado intencionalmente para modernizar JSF. Entre varios cientos de pequeñas reparaciones y actualizaciones más grandes, JSF 2.3 desaprueba las anotaciones de beans administrados a favor de CDI, que presentaré más adelante en este tutorial.

JSF 2.3 en Yakarta EE

En septiembre de 2017, Oracle anunció su intención de realizar la transición de Java EE a Eclipse Foundation. Desde entonces, Java EE ha cambiado de nombre a Jakarta EE, y JSF 2.3 (Eclipse Mojarra) se ha adoptado para su continuación. La próxima versión importante de la especificación JSF será Eclipse Mojarra 3.0.

Construyendo interfaces web basadas en componentes en JSF

La idea central de JSF es encapsular la funcionalidad en componentes reutilizables. Esto es similar a las etiquetas reutilizables utilizadas en JSP, pero los componentes JSF son más formales.

Si bien puede usar páginas JSF dentro de JavaServer Pages, es más común usar Facelets para crear páginas JSF independientes. Facelets son páginas XHTML diseñadas para definir interfaces JSF. Con Facelets, usa etiquetas XML para crear un árbol de componentes que se convierte en el andamio para una interfaz de usuario JSF.

El Listado 1 presenta las partes principales de una página JSF simple escrita con Facelets. En este ejemplo, accedemos a las capacidades del lado del servidor de Java a través de un bean que se ha colocado en el alcance a través de CDI. Verá más sobre CDI más adelante.

Listado 1. Página de muestra de JSF

    Hello JavaWorld!   #{javaBean.content}  

En el Listado 1 vemos una página XHTML estándar. Una vista de Facelets se construye sobre XHTML. Además del espacio de nombres XHTML, se define y se hace referencia a un espacio de nombres secundario.

La hbiblioteca contiene componentes estándar para su uso en páginas HTML JSF. La //xmlns.jcp.org/jsf/htmlbiblioteca define una colección de componentes JSF, en este caso una colección de elementos HTML comunes. Uno de estos componentes es el elemento.

Componentes HTML en JSF

En términos de sintaxis, el elemento del Listado 1 hace referencia a la jsf/htmlbiblioteca con el hprefijo. Luego hace referencia al componente específico dentro de la biblioteca, que es el headcomponente.

El componente genera el elemento de encabezado HTML. (Toda esa sintaxis puede parecer excesiva para un propósito tan simple, pero hay una buena razón para ello, como verá en breve).

Componentes de anidamiento

Dentro de la cabecera se anida un elemento HTML estándar . Este elemento se proporciona al componente, junto con los elementos secundarios de contenido anidados dentro de él.

En el cuerpo del documento, la #{}sintaxis contiene una expresión JSF . Esto es exactamente análogo a una expresión JSP con el ${}formato: permite el acceso de objetos Java en su alcance y funciones simples.

El patrón básico para JSF es simple: use Facelets para construir un árbol XML que haga referencia a una biblioteca de componentes o bibliotecas, luego use componentes dentro de la biblioteca para representar objetos Java como HTML.

Usando objetos Java en JSF

Volviendo al Listado 1, observe que dentro de la expresión JSF ( ${javaBean.content) El javaBeanobjeto está dentro del alcance cuando se ejecuta este marcado. El XHTML de Facelets accede a la .contentpropiedad del javaBeanobjeto. El resultado final es una interfaz web que fusiona la estructura de la vista Facelets con las capacidades lógicas y de datos del lado del servidor de Java.

El uso de una expresión JSF es solo una forma de acceder a los datos de la aplicación Java desde una interfaz de usuario JSF. Eventualmente, querrá explorar otras formas en que un componente JSF puede interactuar con el backend de Java, cosas como listas de datos y cuadrículas y una variedad de controles de entrada. Por ahora, es suficiente absorber cómo JSF usa etiquetas XML (o anotaciones) para crear un árbol de componentes que genera HTML en base a los datos contenidos en los objetos Java.

Anotaciones vs XML

Con JSF 2.3, es posible definir componentes JSF con anotaciones, evitando por completo los metadatos XML. Es completamente posible definir e implementar una aplicación JSF sin editar ningún XML.

Estructura de una aplicación JSF

Al igual que JavaServer Pages y la API de Servlet, JavaServer Faces requiere una estructura de directorios y metadatos estándar. Estos se implementan como archivos .war .

La estructura de un archivo .war es similar a una aplicación JSP o Servlet. Contiene un /web-appdirectorio que contiene los archivos de marcado de la aplicación (en este caso, HTML, JSP y Facelets), así como un /WEB-INFdirectorio que presenta los metadatos para describir la aplicación.

Sirviendo JSF

Si bien puede ejecutar JSF en un contenedor Java EE como Glassfish, todo lo que realmente necesita es un contenedor de servlet simple. Tomcat es un contenedor popular para JSF y otras tecnologías Java del lado del servidor.

JSF 2.3: especificaciones e implementaciones

Una de las fortalezas de Java es que se basa en estándares, y esos estándares se rigen por un proceso de comunidad de código abierto. Desde sus inicios, Java Community Process (JCP) ha supervisado el desarrollo de la tecnología Java. Una vez que JCP ha desarrollado y aprobado una especificación o mejora de especificación, está disponible para ser implementada por múltiples partes. Hasta hace poco, los Servlets, JSP y JSF se desarrollaban utilizando el proceso de especificación de código abierto de JCP.

La especificación JSF más reciente a la fecha de este escrito es JSF 2.3, lanzada como parte de Java EE 8 en 2017. Mojarra de Oracle (ahora Eclipse) es la implementación de referencia JSF, y MyFaces y PrimeFaces son implementaciones de terceros populares.

Cada uno de estos marcos implementa el núcleo JSF, que incluye algunos componentes estándar. Los proveedores también pueden ofrecer bibliotecas de componentes adicionales además del estándar. Al evaluar marcos JSF, es una buena idea considerar las necesidades de su aplicación y qué bibliotecas de componentes están disponibles para ayudarlo a construirla. Idealmente, su marco JSF debería acercarlo lo más posible a lo que necesita, desde el primer momento.

MVC en JSF 2.3

JSF es un marco MVC que implementa el patrón modelo-vista-controlador. En el patrón MVC, la idea es separar las tres preocupaciones de una interfaz de usuario en partes discretas para que sean más fáciles de administrar. En general, la vista es responsable de mostrar datos en el modelo y el controlador es responsable de configurar el modelo y enrutar al usuario a la vista correcta.

En una implementación JSF, la vista es la página Facelets con su conjunto de etiquetas XML. Estos definen el diseño de la interfaz de usuario. La otra mitad del uso de JSF es el lado del servidor, donde las clases de Java respaldan esos componentes de la interfaz de usuario.

Beans administrados en desuso en JSF 2.3

Las anotaciones de bean administradas se han desaprobado en JSF 2.3 y se han reemplazado por CDI (Contexts and Dependency Injection). Con CDI, los desarrolladores definen un contexto e inyectan objetos en ese contexto. Aquellos familiarizados con beans administrados encontrarán que la sintaxis de la anotación es ligeramente diferente, pero la semántica sigue siendo exactamente la misma.

Frijoles controlador

En JSF 2.3, los beans de controlador proporcionan la parte del controlador de la ecuación MVC. Los objetos Java normales (a menudo denominados POJO u objetos Java antiguos simples) proporcionan el modelo.

En términos de flujo de proceso, los beans de controlador:

  1. Decidir a dónde dirigir las solicitudes de los usuarios
  2. Configurar POJO para el modelo
  3. Usa el modelo para renderizar la vista Facelets

JSF luego junta el árbol de componentes y el modelo para representar el HTML de salida.

El Listado 2 muestra cómo definiría el javaBeanobjeto del Listado 1 usando CDI. Este listado asume que la aplicación tiene el cdi-api-1.2.jar en sus dependencias.

Listado 2. Un JavaBean definido usando CDI

 import javax.inject.Named; import javax.enterprise.context.SessionScoped; @Named @ViewScoped public class JavaBean implements Serializable { private String content = ìWelcome to JSF!î // getters/setters } 

JSF 2.3 con PrimeFaces

En las siguientes secciones usaré PrimeFaces para mostrarle cómo JSF implementa el patrón MVC, la mensajería basada en eventos y los componentes reutilizables. Para comenzar, abra PrimeFaces Showcase, haga clic en el enlace Datos en la columna del lado izquierdo y seleccione Lista de datos . Esto abrirá el código de demostración de DataList para PrimeFaces.

La Figura 1 le muestra dónde encontrar estas muestras.

Matthew Tyson

La Figura 2 muestra el resultado de una tabla de datos simple, que se toma de la demostración de PrimeFaces DataList.

Matthew Tyson

PrimeFaces DataList: Accediendo al modelo de datos

Listing 3 presents the markup for this dataList display. If you scroll to the bottom of the PrimeFaces showcase, you can see the markup in the dataList.xhtml tab.

Listing 3. Facelet for PrimeFaces DataList

   Basic  #{car.brand}, #{car.year}  

In Listing 3, notice the value property of the dataList component. You can see that this references a dataListView object, and accesses the .cars1 property on it. The component is going to use the model object returned by that field. JSF tokens use conventional accessors to reference object properties, so .cars1 will refer to the getCars() getter on the object.

Next, notice the var="car" property. This tells the dataList component what variable to use when it iterates over the list of cars returned by the value field. These properties are specific to the dataList component, but the value property is very common. The var attribute is also conventional for components that iterate over lists.

In the body of the component in Listing 3, you can see the car variable is accessed via JSF expressions like #{car.brand}. Each iteration of the dataListView.cars1 instance will output the car.brand field.

Notice that the tag demonstrates the ability to customize components for how they will display. In this case, the header is defined as Basic.

You can see how the Facelets XML will drive this output by combining the data with the markup. Now let's look at the Java code behind it.

DataList's server-side components

Listing 4 shows DataListView, the Java class that is used by the markup in Listing 3. You'll see shortly how the dataListView instance is associated with the DataListView class.

Listing 4. DataListView class

 package org.primefaces.showcase.view.data; import java.io.Serializable; import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Named; // Pre JSF 2.3, this was: // import javax.faces.bean.ManagedBean; import javax.inject.Inject; import javax.faces.bean.ViewScoped; import org.primefaces.showcase.domain.Car; import org.primefaces.showcase.service.CarService; @Named @ViewScoped public class DataListView implements Serializable { private List cars1; private Car selectedCar; @Inject("#{carService}") private CarService service; @PostConstruct public void init() { cars1 = service.createCars(10); } public List getCars1() { return cars1; } public void setService(CarService service) { this.service = service; } } 

Listing 4 has a few other important elements, which we'll consider piece by piece.

Dependency injection and annotations

First, notice that the DataListView class is annotated with @Named, which you can see from the import import javax.inject.Named; is part of JSF. The @Named annotation tells JSF this bean is part of the app. The @ViewScoped annotation informs JSF that the bean will live for just the life of the view.

A continuación, observe que la CarServicepropiedad tiene la @Injectanotación (denominada @ManagedPropertyanterior a JSF 2.3). Esta es otra característica de JSF que permite que los beans se "conecten", una técnica popularizada por el marco Spring y otras herramientas de inyección de dependencias. En esencia, JSF encontrará el carServiceobjeto en el alcance y lo asociará automáticamente al servicecampo del DataListViewobjeto.