Atenção: esse artigo tem um vídeo complementar. Clique e assista!

Artigo no estilo: Curso

De que se trata o artigo:

Apresentação dos passos básicos necessários para a criação de componentes JSF. A possibilidade de criar componentes de interface gráfica personalizados é, sem dúvida, uma das principais qualidades do JavaServer Faces. Ao longo do artigo, é abordada, passo-a-passo, a criação de dois componentes, sendo uma caixa de sugestão e um componente de imagem que especializa o componente padrão permitindo a visualização de imagens a partir de um array de bytes, ideal para a exibição de imagens salvas em banco de dados.


Para que serve:

Este artigo destina-se a desenvolvedores interessados em conhecer o processo de criação de componentes de interface gráfica personalizados para aplicações JSF.


Em que situação o tema é útil:

O conteúdo deste artigo é útil para guiar o leitor em cenários pelos quais os componentes JSF padrões não atendem as necessidades da aplicação que exigem a criação de novos componentes.

Desenvolvendo com JavaServer Faces – Parte 2:

O JavaServer Faces é um framework web baseado em componentes de interface gráfica que possui todo um mecanismo que possibilita a criação de novos componentes. O desenvolvedor tem como opção criar um novo componente ou especializar um já existente.

A criação de um componente envolve quatro atividades básicas: criar o componente, criar o renderer, criar uma classe tag para integração com a JSP e registrar a tag no TLD. Inicialmente, parece ser um pouco trabalhoso criar um componente, mas a possibilidade de reutilização do código e ganhos de produtividade compensa o esforço gasto no desenvolvimento do mesmo.

Há, na comunidade, uma variedade considerável de componentes disponíveis, a exemplo, temos o Apache Tomahawk, JBoss RichFaces e o ICEFaces. Ao longo de um projeto, a necessidade de criação de novos componentes é, de certo modo, baixa, quando se utiliza estas bibliotecas.

No primeiro artigo da série, foram abordados os conceitos básicos do JavaServer Faces: ciclo de vida, conversores, validadores. Foi também proposta a criação de uma loja virtual onde foram aplicados alguns dos principais fundamentos e componentes padrões do JSF. Na ocasião, foi criada a página para registro dos clientes para a loja virtual. Porém, foi possível notar que os componentes padrões disponíveis atendem apenas a problemas muito básicos. Neste contexto, o desenvolvedor possui duas opções: utilizar componentes de terceiros, ou criar seus próprios componentes.

O JavaServer Faces é um framework que auxilia na criação de interfaces de usuário baseadas em componentes. O uso desses componentes ajuda a simplificar o desenvolvimento, uma vez que abstrai toda a complexidade do desenvolvedor, possibilitando a reutilização em diversas partes do projeto e até mesmo a reutilização dos mesmos em vários projetos. A implementação padrão de JSF oferece apenas componentes básicos para criação de formulários e componentes primitivos para interação de dados e formatação de layout.

Criar um componente JSF não é uma tarefa muito fácil. Mas, apesar da complexidade, há diversos artigos e sites na internet que abordam este assunto; a exemplo deles pode-se destacar um tópico dedicado a este item.

O presente artigo objetiva mostrar os fundamentos necessários para a criação de componentes Faces. Os componentes aqui criados auxiliarão na criação do carrinho de compras para a aplicação de LivrosOnline iniciado no artigo anterior. Será criado um componente para exibição de imagens salvas no banco de dados e um outro para exibir dicas de contexto (tooltips) personalizados com suporte a formatação HTML do conteúdo. Mas antes de criar o primeiro, iniciaremos conhecendo alguns conceitos.

Primeiros passos?

Criar componentes JSF não é uma tarefa complicada, porém, requer do desenvolvedor um conhecimento básico tanto da estrutura do Faces quanto da criação de custom tags em JSP. Essa tarefa pode ser simplificada ainda mais se o componente a ser criado tiver comportamento extra aos componentes padrões já existentes.

Assim como foi dito na Parte 1 do artigo, a implementação de componentes é muito similar ao desenvolvimento de componentes Swing. Componentes JSF possuem eventos e propriedades assim como os componentes Swing. Possuem, também, o suporte à vinculação de componentes, ou seja, um componente que gerar uma linha de uma tabela precisa estar inserido dentro do corpo de uma tabela.

Basicamente, um componente centraliza duas funcionalidades: codificação e decodificação de dados. Neste contexto, a codificação é o processo destinado à conversão de determinados dados em artefatos HTML para o qual o componente é proposto. Por exemplo: gerar o código HTML correspondente a uma coluna de uma tabela ou a uma caixa de texto. Já a decodificação se propõe a converter os parâmetros da requisição para valores significativos ao contexto do componente. A Figura 1 mostra a codificação e decodificação de um componente em relação ao ciclo de vida JSF. A codificação ocorre durante a fase Apply Request Values e a decodificação do componente ocorre durante a última fase, denominada Render.

Figura 1. Fases JSF relacionadas com a codificação e decodificação de componentes JSF

Em tese, os componentes JSF não são diretamente dependentes do JSP e HTML. Neste caso, temos uma estrutura básica de três elementos:

  • Uma classe pertencente à hierarquia de UIComponentELTag para inicializar, receber os atributos da tag e definir qual é o componente e qual é o renderer associado a ele;
  • O componente propriamente dito pertencente à hierarquia de UIComponent, responsável por registrar eventos e gerenciar o estado do componente e;
  • Uma classe pertencente à hierarquia de Renderer, responsável por gerar os artefatos HTML e também por decodificar os dados recebidos.

O ambiente JSF oferece ao desenvolvedor duas formas de codificação e decodificação. Uma delas é a implementação direta. Neste caso, a codificação e decodificação ocorrem dentro do próprio componente, descartando o uso da classe Renderer. Já na outra forma, o componente delega a codificação e decodificação para a classe Renderer. Delegar a decodificação de um componente permite ao desenvolvedor reaproveitar este mesmo componente associando novos comportamentos, como por exemplo, uma caixa de multi-seleção e uma lista de checkbox.

Você pode encontrar em artigos na Internet ou em livros referências a classe UIComponentTag. Esta classe era usada até a versão 1.2 que, com o advento da integração com as expressões JSP passou a ser obsoleta. Se estiver usando a versão 1.2 dê preferência a classe UIComponentELTag, pois, possui alguns recursos facilitadores para a manipulação de EL (Expression Language).

Antes de criar o primeiro componente, é bom que o desenvolvedor conheça as classes básicas necessárias para criar componentes. A Figura 2 mostra um diagrama com as principais classes e o relacionamento entre elas.

Figura 2. Classes básicas usadas para criação de componentes

As interfaces ValueHolder e EditableValueHolder definem os métodos básicos para componentes que recebem um valor. Elas possuem métodos como GET/SET, além de métodos para definir o conversor a ser usado, para definir validadores e para definir eventos à alteração de valor. Já a interface StateHolder fornece os métodos responsáveis para manter o estado do componente.

As classes básicas para a criação de componentes são: UIComponent, UIComponentBase, UIOutput e UIInput. Essas classes implementam as interfaces citadas fornecendo o comportamento básico do componente.

Agora que temos uma ideia de como implementar um componente JSF, chegou o momento de pôr a mão na massa. Criaremos um componente capaz de gerar dicas de contextos, também conhecidos como tooltips, que será capaz de exibir tanto textos simples quanto textos formatados em HTML.

Criando componente dica de contexto

O primeiro passo a ser tomado ao iniciar o desenvolvimento de um componente é simular o resultado que se deseja com o mesmo. Isto permite identificar se o que se pretende fazer realmente funciona, ou seja, se não funcionar na simulação, dificilmente funcionará no componente.

Além de simular o código resultante, é importante testar a compatibilidade deste código com os principais componentes de terceiros. E, caso tenha funções JavaScript ou estilos CSS definidos, é sempre bom certificar-se de que estas funções e estilos não se colidem com códigos já existentes na página.

...
Quer ler esse conteúdo completo? Tenha acesso completo