Guia para JSF Expression Language 3.0

Guia para JSF Expression Language 3.0

1. Visão geral

Neste artigo, veremos os recursos, melhorias e problemas de compatibilidade mais recentes do Expression Language, versão 3.0 (EL 3.0).

Esta é a versão mais recente do momento em que este artigo foi escrito e é fornecida com servidores de aplicativos JavaEE mais recentes (JBoss EAP 7 e Glassfish 4 são bons exemplos que implementaram suporte a ele).

O artigo se concentra apenas nos desenvolvimentos do EL 3.0 - para aprender mais sobre a linguagem de expressão em geral, leia o artigoEL version 2.2 primeiro.

2. Pré-requisitos

Os exemplos mostrados no artigo também foram testados no Tomcat 8. Para usar o EL3.0, você deve adicionar a seguinte dependência:


    javax.el
    javax.el-api
    3.0.0

Você sempre pode verificar o repositório Maven para a dependência mais recente seguindo estelink.

3. Expressões Lambda

A iteração EL mais recente fornece suporte muito robusto para expressões lambda. As expressões Lambda foram introduzidas no Java SE 8, mas o suporte a ele no EL é fornecido com o Java EE 7.

A implementação aqui é completa, permitindo muita flexibilidade (e alguns riscos implícitos) no uso e avaliação de EL.

3.1. Lambda EL Value Expressions

O uso básico dessa funcionalidade nos permite especificar uma expressão lambda como o tipo de valor em uma expressão de valor EL:

Estendendo disso, pode-se nomear a função lambda no EL para reutilização em instruções compostas, como faria em uma expressão lambda no Java SE. As expressões lambda compostas podem ser separadas por um ponto e vírgula (;):

Este fragmento atribui a função ao identificadorcube, que fica então disponível para reutilização imediatamente.

3.2. Passando Expressões Lambda para o Backing Bean

Vamos um pouco mais adiante: podemos obter muita flexibilidade encapsulando a lógica em uma expressão EL (como um lambda) e passando-a para o bean de apoio JSF:

Isso agora nos permite processar a expressão lambda inteira como uma instância dejavax.el.LambdaExpression:

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

Este é um recurso atraente que permite:

  • Uma maneira limpa de empacotar a lógica, fornecendo um paradigma de programação funcional muito flexível. A lógica do bean de backup acima pode ser condicional com base em valores extraídos de diferentes fontes.

  • Uma maneira simples de introduzir o suporte lambda nas bases de código anteriores ao JDK 8 que podem não estar prontas para atualização.

  • Uma ferramenta poderosa no uso da nova API Streams / Collections.

4. Melhorias na API de coleções

Faltava um pouco o suporte para a API Collections em versões anteriores do EL. O EL 3.0 introduziu importantes melhorias de API em seu suporte às coleções Java e, assim como as expressões lambda, o EL 3.0 fornece suporte ao JDK 8 Streaming no Java EE 7.

4.1. Definição de coleções dinâmicas

Novo no 3.0, agora podemos definir dinamicamente estruturas de dados ad-hoc no EL:

  • Listas:

   
       
           
       
   
  • Conjuntos:

   
    ....
   

Note: Assim como em Java normalSets,, a ordem dos elementos é imprevisível, quando listados

  • Mapas:

   

Tip: Um erro comum em livros didáticos ao definir mapas dinâmicos usa aspas duplas (“) em vez de aspas simples para a chave Map - isso resultará em um erro de compilação EL.

4.2. Operações de coleta avançadas

Com o EL3.0, há suporte para uma semântica de consulta avançada que combina o poder das expressões lambda, a nova API de streaming e operações semelhantes a SQL, como junções e agrupamentos. Não cobriremos isso neste artigo, pois são tópicos avançados. Vejamos um exemplo para demonstrar seu poder:


    
        
    

A tabela acima filtrará uma lista de suporte usando a expressão lambda passada

 
 

O texto de saídaavg calculará a média dos números na lista. Ambas as operações são null-safe por meio do novoOptional API (outra melhoria nas versões anteriores).

Lembre-se de que o suporte para isso não requer JDK 8, apenas JavaEE 7 / EL3.0. O que isso significa é que você pode fazer a maioria das operações JDK 8Stream em EL, mas não no código Java do bean de apoio.

Tip: Você pode usar a tag JSTL<c:set/> para declarar sua estrutura de dados como uma variável de nível de página e manipulá-la em toda a página JSF:

 

Agora você pode consultar“#{pageLevelNumberList}” em toda a página como se fosse um componente ou bean genuíno JSF. Isso permite uma quantidade significativa de reutilização em toda a página

5. Métodos e campos estáticos

Não havia suporte para um campo estático, método ou acesso ao Enum nas versões anteriores do EL. As coisas mudaram.

Primeiro, precisamos importar manualmente a classe que contém as constantes para o contexto EL. Idealmente, isso é feito o mais cedo possível. Aqui, estamos fazendo isso no inicializador@PostConstruct do bean gerenciado JSF (AServletContextListener também é um candidato viável):

 @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");
         }
     });
 }

Em seguida, definimos um campo constanteString (ou umEnum se você escolher) na classe desejada:

public static final String constantField
  = "THIS_IS_NOT_CHANGING_ANYTIME_SOON";

Após o qual agora podemos acessar a variável no EL:

 
 

De acordo com a especificação EL 3.0, qualquer classe fora dejava.lang.* precisa ser importada manualmente, conforme mostrado. É só depois de fazer isso que as constantes definidas em uma classe estão disponíveis em EL. A importação é idealmente feita como parte da inicialização do tempo de execução JSF.

Algumas notas são necessárias aqui:

  • A sintaxe requer que os campos e métodos sejampublic, static (efinal no caso de métodos)

  • A sintaxe foi alterada entre o rascunho inicial da especificação EL 3.0 e a versão de lançamento. Portanto, em alguns livros didáticos, você ainda pode encontrar algo parecido com:

    T(YourClass).yourStaticVariableOrMethod

    Isso não funcionará na prática (uma mudança de design para simplificar a sintaxe foi decidida no final do ciclo de implementação)

  • A sintaxe final lançada ainda apresentava um bug - é importante executar as versões mais recentes deles.

6. Conclusão

Examinamos alguns dos destaques na implementação de EL mais recente. Grandes melhorias foram feitas para trazer novos recursos interessantes, como lambda e flexibilidade de fluxos para a API.

Com a flexibilidade que agora temos em EL, é importante lembrar um dos objetivos de design da estrutura JSF: separação limpa de interesses com o uso do padrão MVC.

Portanto, é importante notar que as melhorias mais recentes na API podem nos abrir para antipadrões em JSF porque o EL agora tem a capacidade de fazer lógica de negócios real - mais do que antes. E por isso é importante ter isso em mente durante uma implementação no mundo real, para garantir que as responsabilidades sejam separadas de forma organizada.

E, claro, os exemplos dos artigoscan be found on GitHub.