Guide du langage d’expression JSF 3.0

Guide de JSF Expression Language 3.0

1. Vue d'ensemble

Dans cet article, nous examinerons les dernières fonctionnalités, améliorations et problèmes de compatibilité d'Expression Language, version 3.0 (EL 3.0).

Il s’agit de la version la plus récente au moment de la rédaction de ce document. Elle est livrée avec les serveurs d’application JavaEE les plus récents (JBoss EAP 7 et Glassfish 4 sont de bons exemples ayant pris en charge cette fonction).

L'article se concentre uniquement sur les développements d'EL 3.0 - pour en savoir plus sur Expression Language en général, lisez d'abord l'article deEL version 2.2.

2. Conditions préalables

Les exemples présentés dans cet article ont également été testés sur Tomcat 8. Pour utiliser EL3.0, vous devez ajouter la dépendance suivante:


    javax.el
    javax.el-api
    3.0.0

Vous pouvez toujours vérifier le référentiel Maven pour la dernière dépendance en suivant celink.

3. Expressions Lambda

La dernière itération EL fournit un support très robuste pour les expressions lambda. Les expressions lambda ont été introduites dans Java SE 8, mais Java EE 7 le prend en charge.

La mise en œuvre ici est complète, permettant une grande flexibilité (et un risque implicite) dans l'utilisation et l'évaluation des LE.

3.1. Expressions de valeur EL Lambda

L'utilisation de base de cette fonctionnalité nous permet de spécifier une expression lambda comme type de valeur dans une expression de valeur EL:

En plus de cela, on peut nommer la fonction lambda dans EL pour la réutiliser dans des instructions composées, comme vous le feriez dans une expression lambda dans Java SE. Les expressions lambda composées peuvent être séparées par un point-virgule (;):

Cet extrait de code affecte la fonction à l'identifiantcube, qui est alors immédiatement disponible pour une réutilisation.

3.2. Transmission d'expressions Lambda au Backing Bean

Allons un peu plus loin: nous pouvons obtenir beaucoup de flexibilité en encapsulant la logique dans une expression EL (en tant que lambda) et en la passant au bean de support JSF:

Cela nous permet maintenant de traiter l'expression lambda dans son ensemble comme une instance dejavax.el.LambdaExpression:

public String multiplyValue(LambdaExpression expr){
    return (String) expr.invoke(
      FacesContext.getCurrentInstance().getELContext(), pageCounter);
}

C'est une fonctionnalité convaincante qui permet:

  • Une façon propre de loger la logique, offrant un paradigme de programmation fonctionnelle très flexible. La logique de haricot de support ci-dessus pourrait être conditionnelle en fonction de valeurs extraites de différentes sources.

  • Un moyen simple d'introduire la prise en charge de lambda dans les bases de code antérieures à JDK 8 qui pourraient ne pas être prêtes à être mises à niveau.

  • Un outil puissant pour utiliser la nouvelle API Streams / Collections.

4. Améliorations de l'API Collections

La prise en charge de l'API Collections dans les versions précédentes d'EL manquait quelque peu. EL 3.0 a apporté des améliorations majeures aux API pour la prise en charge des collections Java. Tout comme les expressions lambda, EL 3.0 prend en charge JDK 8 Streaming dans Java EE 7.

4.1. Définition de collections dynamiques

Nouveauté 3.0, nous pouvons maintenant définir de manière dynamique des structures de données ad-hoc dans EL:

  • Listes:

   
       
           
       
   
  • Ensembles:

   
    ....
   

Note: Comme pour Java normalSets,, l'ordre des éléments est imprévisible, lorsqu'ils sont répertoriés

  • Plans:

   

Tip: Une erreur courante dans les manuels lors de la définition de cartes dynamiques utilise des guillemets doubles (") au lieu de guillemets simples pour la clé Map - cela va entraîner une erreur de compilation EL.

4.2. Opérations de collecte avancées

Avec EL3.0, une sémantique de requête avancée prend en charge la puissance des expressions lambda, la nouvelle API de diffusion en continu et des opérations similaires à celles de SQL, telles que les jointures et les regroupements. Nous ne les aborderons pas dans cet article, car il s'agit de sujets avancés. Examinons un exemple pour démontrer sa puissance:


    
        
    

Le tableau ci-dessus filtrera une liste de sauvegarde en utilisant l'expression lambda passée

 
 

Le texte de sortieavg calculera la moyenne des nombres de la liste. Ces deux opérations sont sécurisées par null grâce aux nouveauxOptional API (une autre amélioration par rapport aux versions précédentes).

N'oubliez pas que la prise en charge de cela ne nécessite pas JDK 8, juste JavaEE 7 / EL3.0. Cela signifie que vous pouvez effectuer la plupart des opérations du JDK 8Streamdans EL, mais pas dans le code Java du bean de sauvegarde.

Tip: Vous pouvez utiliser la balise JSTL<c:set/> pour déclarer votre structure de données en tant que variable au niveau de la page et la manipuler à la place dans toute la page JSF:

 

Vous pouvez maintenant faire référence à“#{pageLevelNumberList}” tout au long de la page comme s'il s'agissait d'un composant JSF ou d'un bean de bonne foi. Cela permet une quantité importante de réutilisation sur la page.

5. Champs et méthodes statiques

Aucune prise en charge d'un champ statique, d'une méthode ou d'un accès Enum dans les versions précédentes de EL n'était prise en charge. Les choses ont changé.

Premièrement, nous devons importer manuellement la classe contenant les constantes dans le contexte EL. Ceci est idéalement fait le plus tôt possible. Ici, nous le faisons dans l'initialiseur@PostConstruct du bean géré JSF (AServletContextListener est également un candidat viable):

 @PostConstruct
 public void init() {
     FacesContext.getCurrentInstance()
       .getApplication().addELContextListener(new ELContextListener() {
         @Override
         public void contextCreated(ELContextEvent evt) {
             evt.getELContext().getImportHandler()
              .importClass("com.example.el.controllers.ELSampleBean");
         }
     });
 }

Ensuite, nous définissons un champ constantString (ou unEnum si vous choisissez) dans la classe souhaitée:

public static final String constantField
  = "THIS_IS_NOT_CHANGING_ANYTIME_SOON";

Après quoi, nous pouvons maintenant accéder à la variable dans EL:

 
 

Selon la spécification EL 3.0, toute classe en dehors dejava.lang.* doit être importée manuellement comme indiqué. Ce n’est qu’après cela que les constantes définies dans une classe sont disponibles dans EL. L'importation est idéalement effectuée dans le cadre de l'initialisation du moteur d'exécution JSF.

Quelques notes sont nécessaires ici:

  • La syntaxe exige que les champs et méthodes soientpublic, static (etfinal dans le cas des méthodes)

  • La syntaxe a changé entre le brouillon initial de la spécification EL 3.0 et la version publiée. Donc, dans certains manuels, vous pouvez toujours trouver quelque chose qui ressemble à:

    T(YourClass).yourStaticVariableOrMethod

    Cela ne fonctionnera pas dans la pratique (une modification de conception pour simplifier la syntaxe a été décidée tard dans le cycle de mise en œuvre)

  • La syntaxe finale qui a été publiée comportait toujours un bogue - il est important d’exécuter les dernières versions de celles-ci.

6. Conclusion

Nous avons examiné certains des points saillants de la dernière mise en œuvre EL. Des améliorations majeures ont été apportées pour apporter de nouvelles fonctionnalités intéressantes telles que lambda et la flexibilité des flux vers l'API.

Avec la flexibilité que nous avons maintenant dans EL, il est important de se souvenir de l’un des objectifs de conception du framework JSF: une séparation nette des problèmes avec l’utilisation du modèle MVC.

Il est donc intéressant de noter que les dernières améliorations apportées à l'API peuvent nous ouvrir à des anti-modèles dans JSF, car EL a désormais la capacité de faire de la vraie logique métier - plus qu'avant. Il est donc important de garder cela à l’esprit lors d’une mise en œuvre dans le monde réel, pour s’assurer que les responsabilités sont clairement séparées.

Et bien sûr, les exemples des articlescan be found on GitHub.