Qu'est-ce que JSF? Présentation de JavaServer Faces

JavaServer Faces (JSF) est la technologie standard Java pour la création d'interfaces Web orientées événements et basées sur des composants. À l'instar de JavaServer Pages (JSP), JSF permet d'accéder aux données et à la logique côté serveur. Contrairement à JSP, qui est essentiellement une page HTML dotée de fonctionnalités côté serveur, JSF est un document XML qui représente des composants formels dans une arborescence logique. Les composants JSF sont soutenus par des objets Java, qui sont indépendants du HTML et ont la gamme complète des capacités Java, y compris l'accès aux API et bases de données distantes.

L'idée clé d'un cadre comme JSF est d'encapsuler (ou enveloppe ) technologies côté client comme HTML, CSS et JavaScript, ce qui permet aux développeurs de créer des interfaces web sans beaucoup d' interaction avec ces technologies.

Cet article présente un aperçu de l'approche de JSF en matière de développement d'interface utilisateur basée sur des composants pour les applications Web Java. Des exemples simples présentent l'architecture MVC, le modèle d'événement et la bibliothèque de composants de JSF. Les exemples incluent de nouvelles fonctionnalités dans JSF 2.3, et nous utiliserons PrimeFaces pour notre bibliothèque de composants.

Évolution de JSF

Longtemps populaire, JSF a récemment été confronté à la concurrence des frameworks Web compatibles Java, y compris les frameworks JavaScript côté client. Néanmoins, JavaServer Faces reste la norme Java, en particulier pour le développement d'entreprise Java à grande échelle. La spécification JSF a également engendré une multitude de frameworks et de bibliothèques, qui ont suivi le rythme des récentes améliorations côté client. L'un d'eux est PrimeFaces, que nous explorons dans ce tutoriel.

Bien que le calendrier du développement futur ne soit pas clair, JSF 2.3 donne aux développeurs beaucoup de choses avec lesquelles travailler pendant que nous attendons. Sorti en mars 2017, JSF 2.3 a été intentionnellement conçu pour moderniser JSF. Parmi plusieurs centaines de petites réparations et de mises à jour plus importantes, JSF 2.3 désapprouve les annotations de bean gérés au profit de CDI, que je présenterai plus tard dans ce tutoriel.

JSF 2.3 à Jakarta EE

En septembre 2017, Oracle a annoncé son intention de faire la transition de Java EE vers la Fondation Eclipse. Java EE a depuis été renommé Jakarta EE, et JSF 2.3 (Eclipse Mojarra) a été adopté pour la suite. La prochaine version majeure de la spécification JSF sera Eclipse Mojarra 3.0.

Création d'interfaces Web basées sur des composants dans JSF

L'idée centrale de JSF est d'encapsuler les fonctionnalités dans des composants réutilisables. Ceci est similaire aux balises réutilisables utilisées dans JSP, mais les composants JSF sont plus formels.

Bien que vous puissiez utiliser des pages JSF dans les pages JavaServer, il est plus courant d'utiliser Facelets pour créer des pages JSF autonomes. Les facelets sont des pages XHTML conçues pour définir des interfaces JSF. Avec Facelets, vous utilisez des balises XML pour créer une arborescence de composants qui devient l'échafaudage d'une interface utilisateur JSF.

Le listing 1 présente les principales parties d'une simple page JSF écrite à l'aide de Facelets. Dans cet exemple, nous accédons aux capacités côté serveur de Java via un bean placé dans la portée via CDI. Vous en saurez plus sur CDI plus tard.

Liste 1. Page d'exemple JSF

    Hello JavaWorld!   #{javaBean.content}  

Dans le listing 1, nous voyons une page XHTML standard. Une vue Facelets est construite sur XHTML. En plus de l'espace de noms XHTML, un espace de noms secondaire est défini et référencé.

La hbibliothèque contient des composants standard à utiliser dans les pages HTML JSF. La //xmlns.jcp.org/jsf/htmlbibliothèque définit une collection de composants JSF, dans ce cas une collection d'éléments HTML communs. L'un de ces composants est l' élément.

Composants HTML dans JSF

En termes de syntaxe, l' élément du Listing 1 fait référence à la jsf/htmlbibliothèque avec le hpréfixe. Il fait ensuite référence au composant spécifique dans la bibliothèque, qui est le headcomposant.

Le composant génère l'élément de tête HTML. (Toute cette syntaxe peut sembler exagérée pour un objectif aussi simple, mais il y a de bonnes raisons à cela, comme vous le verrez bientôt.)

Emboîtement des composants

À l'intérieur de la tête est imbriqué un élément HTML standard . Cet élément est fourni au composant, avec les éléments enfants de contenu imbriqués à l'intérieur de celui-ci.

Dans le corps du document, une expression JSF est contenue dans la #{}syntaxe. C'est exactement analogue à une expression JSP au ${}format: elle permet l'accès d'objets Java dans la portée, et des fonctions simples.

Le modèle de base pour JSF est simple: utilisez Facelets pour créer une arborescence XML qui référence une ou plusieurs bibliothèques de composants, puis utilisez les composants de la bibliothèque pour rendre les objets Java au format HTML.

Utilisation d'objets Java dans JSF

En revenant au Listing 1, notez qu'à l'intérieur de l'expression JSF ( ${javaBean.content) L' javaBeanobjet est dans la portée lorsque ce balisage est exécuté. Le XHTML de Facelets accède à la .contentpropriété sur l' javaBeanobjet. Le résultat final est une interface Web qui fusionne la structure de vue Facelets avec les données côté serveur et les capacités logiques de Java.

L'utilisation d'une expression JSF n'est qu'un moyen d'accéder aux données d'application Java à partir d'une interface utilisateur JSF. Finalement, vous voudrez explorer d'autres façons dont un composant JSF peut interagir avec le backend Java - des éléments tels que des listes et des grilles de données et une variété de contrôles d'entrée. Pour l'instant, il suffit d'absorber la façon dont JSF utilise les balises XML (ou annotations) pour créer une arborescence de composants qui génère du HTML en fonction des données contenues dans les objets Java.

Annotations vs XML

Avec JSF 2.3, il est devenu possible de définir des composants JSF avec des annotations, évitant totalement les métadonnées XML. Il est tout à fait possible de définir et de déployer une application JSF sans modifier aucun XML.

Structure d'une application JSF

À l'instar des pages JavaServer et de l'API Servlet, JavaServer Faces nécessite une structure de répertoire et des métadonnées standard. Ceux-ci sont déployés sous forme de fichiers .war .

La structure d'un fichier .war est similaire à celle d'une application Servlet ou JSP. Il contient un /web-apprépertoire, qui contient les fichiers de balisage de l'application (dans ce cas HTML, JSP et Facelets), ainsi qu'un /WEB-INFrépertoire, qui présente les métadonnées pour décrire l'application.

Au service de JSF

Alors que vous pouvez exécuter JSF dans un conteneur Java EE comme Glassfish, un simple conteneur de servlet est tout ce dont vous avez vraiment besoin. Tomcat est un conteneur populaire pour JSF et d'autres technologies Java côté serveur.

JSF 2.3: Spécifications et implémentations

L'une des forces de Java est qu'il est basé sur des normes, et ces normes sont régies par un processus communautaire open source. Depuis sa création, le Java Community Process (JCP) a supervisé le développement de la technologie Java. Une fois qu'une spécification ou une amélioration de spécification a été développée et approuvée par JCP, elle peut être mise en œuvre par plusieurs parties. Jusqu'à récemment, les servlets, JSP et JSF étaient tous développés à l'aide du processus de spécification open source de JCP.

La spécification JSF la plus récente à ce jour est JSF 2.3, publiée dans le cadre de Java EE 8 en 2017. Mojarra d'Oracle (maintenant Eclipse) est l'implémentation de référence JSF, et MyFaces et PrimeFaces sont des implémentations tierces populaires.

Chacun de ces frameworks implémente le noyau JSF, qui comprend certains composants standard. Les fournisseurs peuvent également proposer des bibliothèques de composants supplémentaires en plus de la norme. Lors de l'évaluation des frameworks JSF, il est judicieux de prendre en compte les besoins de votre application et les bibliothèques de composants disponibles pour vous aider à la créer. Idéalement, votre framework JSF devrait vous rapprocher le plus possible de ce dont vous avez besoin, dès la sortie de la boîte.

MVC dans JSF 2.3

JSF est un framework MVC , implémentant le modèle modèle-vue-contrôleur. Dans le modèle MVC, l'idée est de séparer les trois préoccupations d'une interface utilisateur en parties discrètes, afin qu'elles soient plus faciles à gérer. En général, la vue est responsable de l'affichage des données dans le modèle et le contrôleur est responsable de la configuration du modèle et du routage de l'utilisateur vers la vue correcte.

Dans une implémentation JSF, la vue est la page Facelets avec son ensemble de balises XML. Ceux-ci définissent la disposition de l'interface utilisateur. L'autre moitié de l'utilisation de JSF est le côté serveur, où les classes Java sauvegardent ces composants d'interface utilisateur.

Managed beans obsolètes dans JSF 2.3

Les annotations de bean gérés ont été déconseillées dans JSF 2.3 et remplacées par CDI (Contexts and Dependency Injection). Avec CDI, les développeurs définissent un contexte et injectent des objets dans ce contexte. Ceux qui sont familiers avec les beans gérés trouveront la syntaxe d'annotation légèrement différente, mais la sémantique reste exactement la même.

Beans contrôleur

Dans JSF 2.3, les beans de contrôleur fournissent la partie contrôleur de l'équation MVC. Les objets Java normaux (souvent appelés POJO ou objets Java simples) fournissent le modèle.

En termes de flux de processus, les beans de contrôleur:

  1. Décidez où diriger les demandes des utilisateurs
  2. Configurer des POJO pour le modèle
  3. Utilisez le modèle pour rendre la vue Facelets

JSF plie ensuite l'arborescence des composants et le modèle pour rendre le HTML de sortie.

La liste 2 montre comment vous définiriez l' javaBeanobjet de la liste 1 en utilisant CDI. Cette liste suppose que l'application a le cdi-api-1.2.jar dans ses dépendances.

Listing 2. Un JavaBean défini à l'aide de 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 avec PrimeFaces

Dans les sections suivantes, j'utiliserai PrimeFaces pour vous montrer comment JSF implémente le modèle MVC, la messagerie événementielle et les composants réutilisables. Pour commencer, ouvrez PrimeFaces Showcase, cliquez sur le lien Données dans la colonne de gauche et sélectionnez DataList . Cela affichera le code de démonstration DataList pour PrimeFaces.

La figure 1 vous montre où trouver ces échantillons.

Matthew Tyson

La figure 2 montre la sortie d'une simple table de données, qui est tirée de la démo PrimeFaces DataList.

Matthew Tyson

PrimeFaces DataList: accès au modèle de données

Le listing 3 présente le balisage de cet dataListaffichage. Si vous faites défiler vers le bas de la vitrine PrimeFaces, vous pouvez voir le balisage dans l' dataList.xhtmlonglet.

Listing 3. Facelet pour PrimeFaces DataList

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

Dans le listing 3, notez la valuepropriété du dataListcomposant. Vous pouvez voir que cela fait référence à un dataListViewobjet et accède à la .cars1propriété sur celui-ci. Le composant va utiliser l'objet modèle renvoyé par ce champ. Les jetons JSF utilisent des accesseurs conventionnels pour référencer les propriétés des objets, ils .cars1feront donc référence au getCars()getter sur l'objet.

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.

Ensuite, observez que la CarServicepropriété a l' @Injectannotation (appelée @ManagedPropertyavant JSF 2.3). C'est une autre fonctionnalité JSF qui permet aux beans d'être "câblés ensemble", une technique popularisée par le framework Spring et d'autres outils d'injection de dépendances. En substance, JSF trouvera l' carServiceobjet dans la portée et l'associera automatiquement au servicechamp de l' DataListViewobjet.