set 22 2011

O que estou fazendo no momento

Category: Off-TopicEdson Gonçalves @ 21:46

Olá Pessoal, tudo bom? Como vão vocês?

Sei que estou sumido do blog. Muitos leitores estão, nestes meses, me mandando comentários pedindo  a continuação de alguns artigos, de séries, que comecei e ainda não terminei. Quero informar a todos que, neste momento, estou renovando meus livros, por isso parei um pouco de postar no blog.

Muitas pessoas já sabem, outras nem fazem muita ideia, mas escrever toma muito tempo. Quem possui pouco tempo livre, como eu, no caso, é deixar os finais de semana com a família e  o descanso das noites, para nos dedicar a escrita.

Os escritores que sempre apoio em meu blog, até mesmo outros que desejarem aparecer no mural, só entrar em contato comigo. Sei o quanto é difícil divulgar um livro e ter um pouco de reconhecimento. Muita gente acha que ganhamos dinheiro com livros, que ficamos ricos, mas estou aqui para desmentir. Na área de informática, quem escreve é para ter o prazer de ajudar aqueles que estão com as mesmas dificuldades que, com certeza, passamos um dia.

Quero deixar aqui os meus sinceros agradecimentos a todos aqueles que postam comentários elogiando, criticando e pedindo mais tutoriais no blog. Para aqueles que não liberei os comentários, fiquem tranquilos que eu os li. Só não os liberei, muitas vezes, porque não tive tempo ou, por serem pedidos e perguntas relacionadas diretamente a mim, sobre o assunto, não me permiti o tempo necessário para responde-los.

Assim que terminar o meu primeiro objetivo, que é a completa reformulação e atualização, do livro “Desenvolvendo Aplicações Web com JSP, SERVLETS, JAVASERVER FACES, HIBERNATE, EJB 3 PERSISTENCE E AJAX”, voltarei a postar os diversos tutoriais, que já os tenho quase prontos, no blog.

Deixo aqui o espaço aberto, neste tópico, para que comentem o que acham interessante de estar neste livro que estou trabalhando. Já garanto que muitas criticas e pedidos, vindos de algumas centenas de leitores, não serão ignorados. Professores de universidades, faculdades e escolas técnicas do Brasil e alguns países de língua portuguesa, que também me procuraram para deixar seus pedidos e criticas, quero manter meu compromisso de que todos serão levados em consideração.

Agradeço a compreensão de todos.

Bons códigos!

Tags: , , , , , , , , , , , , ,


jan 28 2011

Gerando relatórios JasperReports na Web com Fontes embebidas

Category: iReport,JasperReportsEdson Gonçalves @ 5:43

Olá Pessoal, tudo bom? Como vão vocês?

Em 2011 quero começar com um artigo ensinando uma dúvida muito frequente aos usuários de hospedagem da Integrator Host: embeber as fontes desktop no relatório JasperReports para serem usadas no aplicativo Web.

No geral, relatórios são criados no desktop, onde usamos uma ferramenta visual, arrastando,  modificando e, claro, gerando uma aparência agradável. Se a aparência então for feita por um Designer, este pouco se importa onde vai ser gerado tal relatório, o importante é o VISUAL. É neste momento que começa o problema.

Um relatório pode usar fontes desktop que não estão disponíveis no servidor online. Pior, se o seu aplicativo roda em um servidor compartilhado, raramente uma empresa de hospedagem vai ficar instalando suas fontes desktop na máquina servidora, toda vez que você estiver com um relatório “enfeitadinho”. Se instalar, também não será na hora. O que fazer neste caso então? Como obter independência?

Pensando nesta questão, a equipe de desenvolvimento do JasperReports incluiu a capacidade de adicionar as fontes desktop em seu aplicativo, para que estejam disponíveis quando aquele seu belo relatório for gerado para o cliente.

O que veremos neste artigo é como executar tal tarefa, partindo de um relatório já gerado no iReport.

Para acompanhar este artigo

Criei um banco de dados simples, com uma tabela chamada produtos, contendo os campos selecionados como mostra a Figura 1.

Figura 1 – A tabela usada

O relatório foi criado usando o assistente do iReport 4, onde o resultado final, após minhas pequenas alterações, é o que mostra a Figura 2.

Figura 2 – Relatório gerado pelo assistente com pequenas modificações

Tenham em mente que este artigo não vai ensiná-los a criar relatórios e sim como contornar um problema comum entre os desenvolvedores Java. Caso queiram dominar a arte de desenvolver relatórios JasperReports com o iReport, vejam a minha seção de livros clicando aqui.

Trabalhando com fontes personalizadas no relatório

Após desenhar o relatório, chega o momento de finalizar a “arte” com alguns toques e, em meio as mudanças, eis que surge a ideia de personalizar a fonte também do texto contido no relatório.

No exemplo que fiz, os textos fixos foram todos personalizados com uma fonte que possuo em minha máquina, chamada Impact.

Figura 3 – A fonte escolhida para o texto estático Produtos do relatório

Embora esta fonte seja importante para o design do meu relatório, não tenho garantias que ela exista no servidor onde hospedo meus aplicativos.  Logo, o que parece simples, pode se tornar um pesadelo se não for eu o responsável pela administração do sistema operacional.

Adicionando a fonte ao aplicativo

Graças ao problema de ausência de fontes em servidores de hospedagem, muitos desenvolvedores não podiam depender da empresa ou administrador que fornece a máquina onde disponibilizam se encontram aplicativos, principalmente quando se trata de uma hospedagem compartilhada.  É nisto que o JasperReports inclui a  possibilidade de ter todas as fontes que usou em seu relatório em produção.

Adicionando e exportando a fonte no iReport

Vá no menu Tools >Options (menu iReport>Preferences no Mac OS X) e, na janela Options, em iReport, selecionem a aba Fonts.

Através do botão Install Font selecionamos as fontes que desejamos importar no iReport. Depois de importadas, podemos selecionar todas elas e exportá-las através do botão Export as extension.

Figura 4 – A fonte escolhida e usada no relatório pronta para ser exportada

No exemplo que explico, chamei o arquivo que exportei de font.jar. É justamente este arquivo que vou adicionar em meu projeto.

A fonte como uma biblioteca no seu aplicativo Web pelo Eclipse IDE

No Eclipse, basta clicar com o direito do mouse sobre o projeto, selecionar o item Properties. Na caixa de diálogo Properties, vamos em Java Build Path, na aba Libraries. Para adicionarmos a biblioteca font.jar, vamos no botão Add External JARs.

Figura 5 – O JAR font.jar adicionado nas bibliotecas do meu projeto

Claro que eu não poderia deixar de comentar uma particularidade do Eclipse IDE na versão Helios. Para projetos Java EE. Nesta versão, temos um item de nome diferente para adicionarmos as bibliotecas do projeto no aplicativo Web. Este item está na janela Properties, em  Deployment Assembly. É neste local que determinamos quais bibliotecas serão exportadas ao executarmos o servidor Java.

Figura 6 – Adicionando os arquivos JARs do projeto no aplicativo Web

Ao clicarmos no botão Add, a caixa de diálogo New Assembly Directive surge. Esta caixa de diálogo é a responsável por selecionarmos as bibliotecas do projeto em Java Build Path Entries.

Figura 7 – Obtendo os arquivos JARs de Java Build Path

Ao clicarmos em Next, veremos todas as bibliotecas que dispomos em Java Build Path. Selecionem todas – as bibliotecas para executar o relatório JasperReports devem estar presentes – finalizando no botão Finish.

Figura 8 – Arquivos JARs selecionados

Retornando ao diálogo Properties, no item Deployment Assembly, temos todas as bibliotecas que serão adicionadas ao diretório lib do projeto, incluindo font.jar.

Figura 9 – As bibliotecas que serão exportadas para o diretório /lib do projeto Web

A fonte como uma biblioteca no seu aplicativo Web pelo NetBeans IDE

No NetBeans IDE, basta adicionar em Libraries, clicando com o direito do mouse e selecionando, no menu de contexto, o item Add JAR / Folder.

Figura 10 – As bibliotecas que serão exportadas para o diretório /lib do projeto Web

Antes e depois da fonte adicionada ao projeto

Para satisfazer a curiosidade do que será visto, temos a Figura 11 que mostra um relatório gerado, em formato PDF, sem a fonte no diretório lib do projeto. Note a diferença com a Figura 12 em relação ao formato da fonte, principalmente do título “Produtos”.

Figura 11 – Arquivo PDF gerado como relatório sem a fonte no diretório lib do projeto

Figura 12 – Arquivo PDF gerado como relatório com a fonte no diretório lib do projeto


O projeto para download

Clique aqui para baixar o projeto e alterá-lo como desejar.

Tags: , , , , ,


fev 21 2010

JavaServer Faces 2.0 na Prática – Parte 3

Category: JSF 2.0Edson Gonçalves @ 3:55

Olá, tudo bom? Como vão vocês?

Este artigo é o terceiro de uma série ao qual vou ensiná-los a trabalhar com o JavaServer Faces 2.0.

Nesta terceira parte iremos conhecer melhor o framework JavaServer Faces 2.0 e seu comportamento.

Dúvidas e críticas são bem vindas.

Conhecendo melhor o JavaServer Faces

Como pudemos  ver, o framework JSF é responsável por interagir com o usuário (cliente). Porém, o escopo de JSF é restringido à camada de apresentação. A persistência de dados e outras conexões back-end estão fora do escopo de JSF.

Se você está começando agora, recomendo voltar até a Parte 1 para melhor compreender este artigo.

Renderizando componentes

Ao chamar uma página JSF no navegador, o servidor inicia uma chamada a árvore de componentes do JSF para renderizar a página de acordo com o encontrado.

O servlet JavaServer Faces inicializa o código do framework e lê a página index.xhtml. Como esta página contém tags JSF, como <h:form />, <h:inputText />, <h:commandButton /> e <h:outputText />, cada uma possui uma classe tag handler associada. Quando a página é lida, as tags handles são executadas, de modo que cada uma colabora com a outra para construir o que chamamos de árvore de componentes. A Figura 1 mostra as tag handlers dos componentes utilizados no exemplo criado na Parte 2 do conjunto de artigos.

Figura 1 – Os componentes da aplicação de exemplo

Figura 1 – Os componentes da aplicação de exemplo

Após ler cada componente, a página HTML é devolvida ao navegador, que a renderiza. Todo e qualquer texto que não for uma tag JSF será passado adiante, onde as demais que não forem serão convertidas em HTML.

O processo de devolver a página no formato HTML ao navegador é chamado de encoding. Se olhar o código HTML gerado, verá que o objeto UIInput, por exemplo, procura o ID (unique ID) e o seu valor atual da expressão #{meuManagedBean.texto}. Por padrão, as strings de atributos ID, do HTML, são adicionadas pelo framework, podendo ser aleatórias. Caso não houver um ID na tag <h:form/>, como no exemplo desenvolvido, poderemos ter um ID como j_idt17:texto:

<input id=”j_idt17:texto” name=”j_idt17:texto” />

Se houver um atributo ID na tag <h:form/> (ex: <h:form id=”form1″ />), você terá como resultado o ID form1:texto na renderização da página:

<input type=”text” />

Se desejarmos retirar essa pré-definição de nome no atributo ID, basta adicionar seguinte atributo e seu valor na tag <h:form/>: prependId=”false”. O resultado tag <h:form/> completa ficaria assim:

<h:form prependId=”false”>

No encoding, o atributo ID gerado seria apenas o nome atribuído na tag pela propriedade id, como, por exemplo, na tag de entrada <h:inputText id=”texto” />, onde a renderização HTML seria:

<input type=”text” />

Depois de ocorrer o encoding, elas são enviadas ao navegador que agora as reconhece como uma página HTML. A Figura 2 ilustra esta transformação.

Figura 2 – Codificação e decodificação das páginas JavaServer Faces

Figura 2 – Codificação e decodificação das páginas JavaServer Faces

Do navegador para o servidor

Depois que o usuário receber a página, este a preenche como deve e submete o formulário ao servidor novamente. No caso do exemplo, o formulário é submetido pelo método HTTP POST, contendo o endereço da página e os dados do formulário.

Os dados no servidor são colocados em uma tabela hash, como ocorre normalmente em processamentos Servlet, que pode ser acessada por todos os componentes. O framework JSF permite que cada componente inspecione esta tabela em um processo chamado de decoding. Neste momento, cada componente decide como serão interpretados os dados do formulário.

O processo como um todo é chamado de Ciclo de Vida e será visto mais adiante, ainda neste artigo.

A arquitetura do JavaServer Faces

Para melhor compreensão, a seguir teremos um resumo de como funcionam as páginas JavaServer Faces:

A arquitetura Model-View-Controller

JSF conecta a apresentação e o modelo. Como vimos, um componente de apresentação pode ser unido a uma propriedade do Managed Bean de um objeto modelo:

<h:outputText value=”#{meuManagedBean.texto}”/>

O JSF opera como o controlador que reage ao usuário processando a ação e os eventos de alteração de valores, enquanto dirige o código para atualizar o modelo ou a apresentação. A invocação ao controlador ocorre através do componente <h:commandButton />.

Quando o botão é clicado e o formulário é enviado (submetido) ao servidor, a implementação JSF invoca o método para checar o bean do usuário. O componente <h:commandButton /> pode possuir um método que entra em ação para atualizar o modelo e devolver para a navegação o ID da próxima página a ser exibida.

Validações e Conversão de dados

Usuários entram com os dados em um formulário Web com um formato de texto. Podemos validar de forma padrão ou personalizada como serão aceitos estes textos (dados). Estas validações, assim como suas conversões, são feitas pelo conjunto de tags JSF Core, que incluímos da seguinte forma:

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:f="http://java.sun.com/jsf/core">

A biblioteca de tags Core pode ser incluída também em uma página JSP da seguinte forma:

<%@ taglib uri=”http://java.sun.com/jsf/core” prefix=”f”%>

Para validar, por exemplo, o tamanho mínimo de caracteres aceitos, podemos fazer da seguinte forma:

<h:inputText id="texto" value="#{meuManagedBean.texto}">

<f:validateLength minimum="3" />

</h:inputText>

Também podemos validar se um campo é obrigatório ou não, utilizando required=”true”:

<h:inputText value=”#{meuManagedBean.texto}” required=”true” >

Objetos de negócios também requerem informações como números, datas ou outros tipos de dados. Com JavaServer Faces podemos definir com as tags Core como serão os dados aceitos em um determinado campo, convertendo-os ou até mesmo personalizar a regra de conversão.

Um exemplo simples seria utilizar o <f:convertDateTime />, que faz com que o campo de entrada seja apenas um tipo de data e hora com o formato definido, que pode ser acrescido ao seu código da seguinte forma:

<h:inputText id="texto" value="#{meuManagedBean.texto}">

<f:convertDateTime pattern="dd/MM/yyyy" />

</h:inputText>

Manipulação de erros

O JSF utiliza regras de validação para campos como “este campo é obrigatório”. Claro que, quando os usuários entrarem com dados inválidos, preciamos exibir mensagens de erros mais apropriadas.

Os erros, tanto de validação, como de conversão, são tratados da mesma forma: uma mensagem é adicionada ao componente que não passou na verificação (seja validação ou conversão), onde a página atual é novamente exibida contendo uma frase do problema ocorrido.

As tags utilizadas para tais representações são: <h:message /> e <h:messages />. Os erros também podem ser lançados de forma personalizada utilizando o atributo validatorMessage ou requiredMessage. Para o exemplo, poderíamos ter algo assim:

<h:inputText

value="#{meuManagedBean.texto}"

required="true"

validatorMessage="Mínimo de 3 caracteres"

requiredMessage="Campo obrigatório">

<f:validateLength minimum="3" />

</h:inputText>

<h:messages />

Internacionalização

JSF fornece suporte à internacionalização como codificações de caractere e a seleção de pacotes de recursos.

A internacionalização no JSF 2.0 é possível de duas formas: faces-config.xml e a tag Core <f:loadBundle />.

Para uma internacionalização com o arquivo faces-config.xml, devemos adicionar este arquivo dentro do diretório WEB-INF. O conteúdo é mostrado na Listagem 1.

Listagem 1 – O arquivo faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"

version="2.0">

<application>

<resource-bundle>

<base-name>br.com.integrator.rotulos</base-name>

<var>rotulo</var>

</resource-bundle>

<locale-config>

<default-locale>pt</default-locale>

<supported-locale>en</supported-locale>

</locale-config>

</application>

</faces-config>

O arquivo faces-config.xml é usado no JSF 2.0 principalmente para numerosas configurações globais de sua aplicação.

Os rótulos neste caso são colocados em arquivos .properties, onde o nome de cada arquivo possui _ABREVIAÇÃO DO IDIOMA como, por exemplo: rotulos_pt.properties. Crie os arquivos mostrados nas Listagens 2 e 3 dentro do pacote br.com.integrator.

Listagem 2 – O arquivo rotulos_en.properties

texto = Text:

enviar = Submit Text

obrigatorio = Required Field

validacao = Minimum 3 characters

titulo = One simple JSF Page

Listagem 3 – O arquivo rotulos_pt.properties

texto = Texto:

enviar = Enviar Texto

obrigatorio = Campo Obrigatório

validacao = Mínimo de 3 caracteres

titulo = Uma simples página JSF

Para compreender como ficará seu projeto, a Figura 3 mostra onde estará cada um dos arquivos que o compõem.

Figura 3 – Estrutura de diretórios do projeto

Figura 3 – Estrutura de diretórios do projeto

As alterações na página index.xhtml são mostradas na Listagem 4 a seguir.

Listagem 4 – Alterações na página index.xhtml

...

<h:head>

<title><h:outputText value="#{rotulo.titulo}" /></title>

</h:head>

<h:body>

<h:form>

<h:outputText value="#{rotulo.texto}" />

<h:inputText id="texto"

value="#{meuManagedBean.texto}"

required="true"

validatorMessage="#{rotulo.validacao}"

requiredMessage="#{rotulo.obrigatorio}">

<f:validateLength minimum="3" />

</h:inputText>

<h:messages />

<br />

<h:commandButton value="#{rotulo.enviar}" action="enviar" />

<br />

<h3><h:outputText value="#{meuManagedBean.texto}" /></h3>

</h:form>

</h:body>

...

Para visualizar as alterações, será necessário trocar o idioma padrão do seu navegador. No Mozilla Firefox, por exemplo, basta ir em Ferramentas>Opções>Conteúdo>Idiomas e clicar no botão Selecionar. Coloque o idioma diferente do que está usando como primeiro na ordem da lista de idiomas de preferência e confirme tudo. Dê um reload na página que verá as alterações.

Caso não queira usar uma declaração global dos recursos de localidades, podemos adicionar a tag <f:loadBundle  /> em cada página JSF. A seguir o trecho que poderá substituir a configuração global no arquivo faces-config.xml.

<f:loadBundle

basename="br.com.integrator.rotulos"

var="rotulo />

Nota: Das duas formas apresentadas para internacionalização de uma aplicação Web com o framework JSF, a versão com o elemento <resource-bundle />, encontrado no arquivo faces-config.xml, é a mais eficiente, pois é utilizado em todo o aplicativo e não somente na página configurada.

Componentes customizados

O desenvolvedor de componentes pode criar componentes sofisticados que são chamados pelos designers simplesmente colocando suas tags em suas páginas, ou arrastando-as caso sejam visuais. Um exemplo é pegar bibliotecas criadas, como de calendários, gráficos ou de upload de arquivos com barra de progresso e simplesmente adicionar na página desenvolvida.

Desde o JavaServer Faces 2.0, criar componentes customizados ficou mais fácil, com um recurso chamado de Composite Components (Componentes Compostos). Para exemplificar como funcionam os recursos de Composite Components, altere como nos passos a seguir seu projeto:

  1. Crie um diretório chamado de resources, no mesmo diretório onde se encontra a página index.xhtml.
  2. Dentro do diretório resources, adicione outro diretório chamado de componente.
  3. No diretório componente, crie uma página XHTML, chamada de component.xhtml,  com o conteúdo mostrado na Listagem 5.

Listagem 5 – Conteúdo do arquivo component.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:composite="http://java.sun.com/jsf/composite">

<h:head>

<title>Meu Primeiro Componente JSF 2.0</title>

</h:head>

<h:body>

<composite:interface>

<composite:attribute name="identificacao" required="true"/>

<composite:attribute name="managedbean" required="true"/>

<composite:attribute name="qtdcaracteres" required="true"/>

</composite:interface>

<composite:implementation>

<h:outputText value="#{rotulo.texto}" />

<h:inputText id="#{cc.attrs.identificacao}"

value="#{cc.attrs.managedbean}"

required="true"

validatorMessage="#{rotulo.validacao}"

requiredMessage="#{rotulo.obrigatorio}">

<f:validateLength minimum="#{cc.attrs.qtdcaracteres}" />

</h:inputText>

<h:messages />

<br />

<h:commandButton value="#{rotulo.enviar}" />

<br />

<h3><h:outputText value="#{cc.attrs.managedbean}" /></h3>

</composite:implementation>

</h:body>

</html>

Uma página de componente(s) no JSF 2.0 pode conter suporte aos componentes do JSF, a validação, converters e listeners. Além disso, qualquer outra tag HTML pode ser adicionada ao componente, incluindo também recursos de templates.

As tags utilizadas para criar componentes compostos no exemplo são: <composite:interface/> e <composite:implementation/>. Para utilizá-las, é necessário adicionar o seguinte namespace:

<html xmlns:composite=”http://java.sun.com/jsf/composite”>

A tag <composite:interface/> declara o contrato para um componente, ou seja, definimos quais são os atributos que o componente receberá. Os atributos são definidos dentro desta tag, com a tag <composite:attribute />, onde temos os atributos name e required. Em name colocamos o nome do atributo do nosso componente composto e definindo true, em required, definimos o atributo como de preenchimento obrigatório.

O exemplo mostrado possui um componente que terá os seguintes atributos obrigatórios, em ordem definidos na interface: identificacao, managedbean e qtdcaracteres.

A tag <composite:implementation/> é onde definimos o conteúdo do componente composto. Onde definir #{cc.attrs.x}, sendo que “x” é o nome do atributo do seu componente, será o local de substituição quando preencher o componente na página que o utilizar.

Para utilizar este componente, vá à página index.xhtml e altere seu conteúdo conforme a Listagem 6 a seguir:

Listagem 6– A página index.xhtml

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:f="http://java.sun.com/jsf/core"

xmlns: comp="http://java.sun.com/jsf/composite/componente">

<h:head>

<title><h:outputText value="#{rotulo.titulo}" /></title>

</h:head>

<h:body>

<h:form>

<comp:component

identificacao="texto"

managedbean="#{meuManagedBean.texto}"

qtdcaracteres="3" />

</h:form>

</h:body>

</html>

Para utilizar o componente criado, você adiciona o seguinte namespace em sua página:

xmlns: comp=”http://java.sun.com/jsf/composite/componente

Observe que componente, no namespace, é o nome do diretório onde se encontra seu componente composto (o diretório fica dentro de resources caso não se lembre). O nome comp é dado por nós para chamar o componente. Podemos ter inúmeros componentes dentro de um diretório, assim como vários diretórios dentro de resources. Os agrupamos como acharmos melhor, de acordo com o conveniente no desenvolvimento de nossos aplicativos.

Para utilizar o componente, o chamamos assim: <comp:component/>. Onde component é o nome do arquivo .xhtml criado. Os atributos deste componente podem ser vários e os definidos como obrigatórios precisam ser preenchidos para que não ocorram erros.

Figura 4 – Da criação do componente até sua utilização e renderização na página

Figura 4 – Da criação do componente até sua utilização e renderização na página

Renderizadores Alternativos

Por padrão, JSF produz HTML em sua saída, mas é extensível o suficiente para produzir outros tipos de saídas como, por exemplo, WML ou XUL.

Ajax

JavaServer Faces possui atualmente uma comunicação Ajax padrão que torna-se totalmente transparente as chamadas cliente-servidor sem a necessidade de reload na página.

Para conhecer rapidamente o Ajax no JavaServer Faces 2.0, altere a página index.xhtml como mostrado na Listagem 7.

Listagem 7 – Alterações na página index.xhtml

...

<h:form>

<h:outputScript name="jsf.js" library="javax.faces" target="head"/>

<h:outputText value="#{rotulo.texto}" />

<h:inputText id="texto" value="#{meuManagedBean.texto}"/>

<br />

<h:commandButton id="enviar" value="#{rotulo.enviar}">

<f:ajax execute="form1:texto" render="form1:saida"/>

</h:commandButton>

<br />

<h3>

<h:outputText id="saida" value="#{meuManagedBean.texto}" />

</h3>

</h:form>

...

Com algumas pequenas mudanças, sua aplicação passou a utilizar o recurso de Ajax.

O JSF 2.0 possui uma nova API JavaScript, ao qual pode chamar o servidor, enviando e recebendo dados. Nesta API JavaScript, temos o seguinte método:

jsf.ajax.request(source, event, options)

Este método envia e recebe os dados do servidor de forma assíncrona diretamente para os componentes da view. Você pode vê-lo no HTML renderizado.

A tag <f:ajax /> que utilizamos no exemplo pode ser substituída pela chamada direta à  jsf.ajax.request() da seguinte forma:

<h:commandButton value=”#{rotulo.enviar}”

onclick=”jsf.ajax.request(this, event,

{execute: ‘form1:texto’, render: ‘form1:saida’}); return false;” />

Em ambos os casos, seja com a tag <f:Ajax/> ou pelo script adicionado na tag, na renderização, o método recebe o elemento que está disparando a ação , que no geral é o próprio que o chama (this), o evento e um conjunto de parâmetros.

Neste conjunto de parâmetros existem duas propriedades: execute e render. Tanto o execute, como o render, recebem os IDs dos elementos HTML renderizados no cliente, ou seja, o ID dos componentes que passaram pelo encoding. O execute define o componente que será submetido ao servidor via Ajax e render qual componente receberá a resposta.

O Ajax padrão de JSF 2.0 é obtido pela tag <h:outputScript />. Esta tag, configurada como no exemplo, renderiza a tag HTML <script/>, que trás um JavaScript existente na biblioteca JSF 2.0. Os três atributos usados no exemplo são:

  • name – O nome do arquivo externo de JavaScript que, no caso, pertence a própria biblioteca de JSF 2.0;
  • library – A biblioteca usada;
  • target –  Onde será renderizada a tag <script/>, que no caso será por entre as tags <head/>, sempre no HTML.

Nota: O JavaScript contido no JSF 2.0 em questão está dentro do JAR jsf-impl.jar, em META-INF/resources/javax.faces/jsf.js. Veja mais a respeito sobre o JavaScript padrão de JSF 2.0 no seguinte link: https://javaserverfaces.dev.java.net/nonav/docs/2.0/jsdocs/index.html.

O MVC de JSF

Para que JSF funcione, registramos a classe FacesServlet no deployment descriptor (web.xml). Ao fazer este registro, os pedidos são controlados pela classe javax.faces.webapp.FacesServlet (o Controller do MVC), uma implementação de javax.servlet.Servlet, roteando o tráfego e administrando o ciclo de vida dos beans e componentes de interface do usuário (UI).

Figura 5 – O MVC do framework JSF

Figura 5 – O MVC do framework JSF

Os componentes UI são organizados em uma estrutura de árvore onde, cada componente, pode ser associado com os métodos e atributos de um bean. Cada componente também pode ser associado com uma função de validação ou classe.

Por trás, FacesServlet aceita pedidos de entrada e controla o objeto javax.faces.lifecycle.Lifecycle. Usando uma factory, ela cria um objeto do tipo javax.faces.context.FacesContext, que contém todos os processos.

O ciclo de vida do JSF

O objeto Lifecycle usa o objeto FacesContext em seis fases que compõem o ciclo de vida de uma aplicação JSF. Cada fase tem uma ação importante em sua aplicação e deve ser bem compreendida para que você possa manipular ao extremo sua interface e melhorar a legibilidade de seu desenvolvimento.

Figura 6 – Ciclo de vida do JavaServer Faces

Figura 6 – Ciclo de vida do JavaServer Faces

As seis fases são executadas na seguinte ordem:

  1. Restaurar Apresentação [1]– Esta fase inicia o processamento da requisição do ciclo de vida por meio da construção da árvore de componentes do JSF. Cada árvore de componentes possui um identificador único durante todo o aplicativo. O JSF constrói a apresentação da página e salva  na instância FacesContext para processamento das fases seguintes.
  2. Aplicar Valores Requisitados – Nesta fase, quaisquer novos valores inseridos são extraídos e armazenados por seus apropriados componentes. Se o valor do componente não for uma String, então ele é convertido para o seu determinado tipo. Se a conversão falhar, ocorrem diversas situações:
  1. 1. Uma mensagem de erro é gerada e associada com o componente;
  2. 2. Uma mensagem de erro é armazenada no FacesContext e depois mostrada posteriormente na fase de Renderizar a Resposta;
  3. 3. O ciclo de vida pula a fase de Renderizar a Resposta quando esta se completou.
  1. Processar Validações – Depois do valor de cada componente ser atualizado, na fase de processo de validações, os componentes serão validados naqueles valores, se necessário. Um componente que necessita de validação deve fornecer a implementação da lógica de validação. Por exemplo, em um carrinho de compras, podemos determinar a quantidade mínima a ser digitada e máxima. O valor requisitado é um inteiro (verificado na fase anterior) e, como passou pela fase 2, nessa fase pode ser barrado por estar além do determinado (com uma quantidade mínima ou máxima diferente da estipulada).
  2. Atualizar Valores do Modelo – Alcança-se essa fase após todos os componentes serem validados. Nesta fase são atualizados os dados do modelo do aplicativo. Na página em que foi criada para enviar um texto, a informação digitada foi armazenada no Managed Bean durante esta fase. Por ter passado pelo processo de validação, temos garantias que o valor armazenado  será garantido nessa fase. Entretanto, os dados podem violar a lógica de negócios, ao qual a validação ocorre na fase seguinte.
  3. Invocar Aplicação – Durante esta fase, a implementação JSF manipula quaisquer eventos do aplicativo, tal como enviar um formulário ou ir a outra página através de um link. Estes eventos são ações que retornam geralmente uma  string que está associada a uma navegação no qual se encarrega de chamar a página determinada.
  4. Renderizar Resposta – Esta é a fase final, ao qual é renderizada a página. Se este é um pedido inicial para esta página,  os componentes são acrescentados à apresentação neste momento. Se este é um postback,  os componentes já foram acrescidos à apresentação.  Se há mensagens de conversão ou erros de validação e a página contém um ou mais componentes <mensage /> ou um componente <messages />, estes serão exibidos.  Reciprocamente, se a página não contém um componente de mensagem,  nenhuma informação aparecerá.

Numa requisição a uma página JSF, podemos passar por todas essas fases ou por nenhuma, dependendo do tipo de pedido, de erros que ocorrem durante as validações, conversões e do tipo de resposta.

Uma requisição e uma resposta são consideradas faces request/response se contiverem tags JSF, assim como as que não as contém são chamadas de non-faces request/response. Uma non-faces request pode vir de um clique em um link, por exemplo.

Como já dito, toda requisição é recebida pelo FacesServlet e prossegue a passagem pelas fases (Lifecycle) até uma resposta ser retornada ao cliente.

O FacesServlet recupera uma instância de FacesContext, do FacesContextFactory, fornecendo uma implementação de LifeCycle. O processamento do ciclo de vida é então delegado a interface LifeCycle, a partir da chamada ao método execute. A implementação de LifeCycle inicia as fases do ciclo de vida. Se existir algum validador associado a algum campo do formulário este é inicializado nessa primeira fase. A árvore é armazenada pelo contexto e será utilizada nas fases seguintes. Também o estado do formulário é salvo automaticamente.

Testando o ciclo de vida

Para confirmar como todas as fases do ciclo de vida são usadas e quais são, basta criar um simples PhaseListener e mandá-lo gerar a saída antes e depois de cada fase.

Criando uma classe Phase Listener

Criar uma classe que implemente a PhaseListener exigem dois passos:

• Criar uma classe que implemente PhaseListener;

• Registrar esta classe no arquivo de configurações do JSF.

A classe PhaseListener deve implementa a classe javax.faces.event.PhaseListener.  A Listagem 8 demonstra como criar esta classe:

Listagem 8 – A classe PhaseListener

package br.com.integrator.listener;

public class PhaseListener implements javax.faces.event.PhaseListener {

public void afterPhase(PhaseEvent event) {

event.getFacesContext().getExternalContext().

log("AFTER: "+event.getPhaseId());

}

public void beforePhase(PhaseEvent event) {

event.getFacesContext().getExternalContext().

log("BEFORE: "+event.getPhaseId());

}

public PhaseId getPhaseId() {

return PhaseId.ANY_PHASE;

}

}

Para a classe da Listagem 8, três métodos são implementados: afterPhase(), beforePhase() e getPhaseId().

Os dois primeiros,  afterPhase()beforePhase(), definem o que ocorre ANTES e DEPOIS de cada fase.  Nestes métodos foram incluídos a capacidade de imprimir na saída console o que ocorreu.

O terceiro método, getPhaseId(), especifica  em  qual das fases é invocado este ouvinte (Listener) e PhaseId.ANY_PHASE menciona que será para todas as fases.

Com a classe criada, o próximo passo é registrar esta classe PhaseListener no arquivo de configurações do JSF (faces-config.xml).

Para fazer isso, no arquivo faces-config.xml,  adicionaremos os seguintes elementos do trecho a seguir:

<faces-config ...>

...

<lifecycle>

<phase-listener>

br.com.integrator.listener.PhaseListener

</phase-listener>

</lifecycle>

</faces-config>

Ao rodar a aplicação, haverá saídas no console de acordo com o uso da aplicação. A Figura 7 mostra tanto o uso da aplicação como sua saída no console, passando pelas seis fases do ciclo de vida.

Figura 7- Execução do exemplo e saída no Console resultante da classe PhaseListener

Figura 7- Execução do exemplo e saída no Console resultante da classe PhaseListener

Podemos testar o comportamento das fases enviando o formulário sem dados preenchidos ou preenchendo erroneamente. É uma forma de analisar de perto o ciclo de vida do framework JavaServer Faces.


[1] Defino aqui como Apresentação a tradução para View, que se refere ao Model-View-Controller, no qual traduzo como Modelo-Apesentação-Controle. Entretanto, a especificação JSF define como View o nome para uma página JSF. No decorrer dos artigos, sempre que me referir a View, estarei tratando da página JSF e não da palavra existente em MVC.

Tags: , , , ,


fev 09 2010

JavaServer Faces 2.0 na Prática – Parte 2

Category: JSF 2.0Edson Gonçalves @ 20:05

Olá, tudo bom? Como vão vocês?
Este artigo é o segundo de uma série ao qual vou ensiná-los a trabalhar com o JavaServer Faces 2.0.
Nesta segunda parte iremos conhecer e utilizar um Managed Beans.
Dúvidas e críticas são bem vindas.

Conhecendo o comportamento do  JavaServer Faces

Agora que já fizemos nossa primeira aplicação em JSF, é mais fácil de entender os serviços que o framework JSF oferece ao desenvolvedor.  Como pudemos ver, o framework JSF é responsável por interagir com o usuário (cliente) e fornece componentes para criar uma apresentação visual de uma aplicação Web, ou seja, o escopo de JSF é restringido à camada de apresentação. A persistência de banco de dados e outras conexões de back-end estão fora do escopo de JSF.

A arquitetura do JavaServer Faces, em um alto nível, se assemelha ao mostrado na Figura 1. Aplicações JSF utilizam como padrão a interceptação HTTP via Servlet Faces e produz HTML. Esta mesma arquitetura permite “plugar” novos elementos, gerando outras características, possibilitando criar páginas usando eventos, listeners e componentes como o seu irmão Java Swing.

A arquitetura JavaServer Faces

Figura 1. A arquitetura JavaServer Faces

A Figura 1 mostra a arquitetura rica e flexível existente no JSF, onde:

  • FacesServlet – é o servlet principal para a aplicação e, opcionalmente, você pode ter o arquivo de configuração faces-config.xml[1].
  • Renderers –  são os responsáveis por exibir um componente e traduzir uma entrada de valor realizada por um usuário em componente.
  • Páginas XHTML, JSP – o JavaServer Faces permite mais de um tipo de arquivo para renderizar seus componentes (PDL – Page Declaration Language[2]), como páginas JSP ou Facelets.
  • Converters – convertem o valor de um componente (como datas, moedas, porcentagem e outros) dando-lhes novos formatos.
  • Validators – responsáveis por validar a entrada ocorrida no componente pelo usuário.
  • Managed Bean – a lógica do negócio é gerenciada pelos managed beans, que controlam inclusive a navegação por entre páginas.
  • Ajax – Tanto o envio como o recebimento de dados podem ser feitos via Ajax, sem a necessidade de reload na página do usuário.

[1] Este arquivo só se tornou opcional na versão 2.0 ou superior.

[2] PDL herda a funcionalidade do núcleo de dois conhecidos projetos JSF: Facelets e JSFTemplates. Entre todos os outros recursos, permite criar novos componentes JSF de forma declarativa, sem a criação de um grupo de classes Java como era nas versões anteriores do JSF.

Compreendendo o comportamento da primeira página JSF criada

Assim como ocorre com outras bibliotecas de tags, o JavaServer Faces é configurado através da diretiva taglib, onde existem as bibliotecas que manipulam o HTML e a Core.

Para usar as tags HTML personalizadas que representam componentes JavaServer Faces, você precisa da diretiva taglib mostrada a seguir, geralmente posicionadas no topo de cada página JSP, como de costume no uso dessa diretiva.

<%@ taglib uri=”http://java.sun.com/jsf/html” prefix=”h”%>

No caso da utilização do Facelets, onde as páginas são XHTML’s, você terá a inclusão da tag personalizada HTML de JSF dessa forma:

<html … xmlns:h=”http://java.sun.com/jsf/html”>

Nota: Com a evolução, o desenvolvimento em JSF atualmente pode utilizar a versão com XHTML descartando a anterior, uma vez que se adéqua melhor ao modelo Web 2.0.

Dentre as tags JSF adicionadas na página, a tag <h:form />, representa um componente UIForm e cria um formulário para envio de dados pelo JSF. No HTML gerado, temos a tag <form/> para que o browser a compreenda.

A tag <h:outputText /> , representando um componente UIOutput que exibe valores, é a responsável pela geração do texto renderizado na página do usuário que, na grande maioria das vezes, é dinâmico. No atributo value você adicionou o texto diretamente, mas poderia adicionar a JSF EL (JavaServer Faces Expression Language), visto mais adiante, referente ao Bean criado, dando assim o retorno ao browser de um valor dinâmico produzido por uma entrada ou vindo do banco de dados.

A página no Browser

A página criada no aplicativo poderá ser aberta através do seguinte endereço também:

http://localhost:8080/TrabComJSF/faces/index.xhtml

Isso ocorre porque adicionamos a seguinte configuração no deployment descriptor (web.xml):

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>

Os itens em destaque mostram que o Servlet FacesServlet, usado para renderizar os componentes JSF, é acionado quando temos “/faces/” antes do nome da página.

Adicionando um bean ao projeto

Na primeira página JSF que criou, você simplesmente adicionou o texto diretamente na tag HTML JSF  <h:outputText />.

Desta vez, você irá adicionar o conteúdo através de um Managed Bean, que nada mais é que uma classe JavaBean comum. A Listagem 1 mostra o conteúdo do Managed Bean que deverá ser feito:

Listagem 1 – A classe MeuManagedBean.java

package br.com.integrator;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean(name="meuManagedBean")
@RequestScoped
public class MeuManagedBean {

private String texto;

public String getTexto() {
return "Exemplo Simples";
}
}

A estrutura de diretórios com o Managed Bean

Sua estrutura de diretórios deverá ser similar ao mostrado na Figura 2, onde apresentamos a classe MeuManagedBean.java compilada:

Estrutura de diretórios do projeto TrabComJSF

Figura 2. Estrutura de diretórios do projeto TrabComJSF

Alterando a página do projeto

Vá até a página index.xhtml e altere a tag JSF  <h:outputText /> da seguinte forma:

<h:outputText value=”#{meuManagedBean.texto}” />

Ao alterar a tag <h:outputText/>, o atributo value recebeu agora os delimitadores #{…}. Estes delimitadores são indicações de expressão ao qual ligam o componente JSF ao Managed Bean e seu atributo get correspondente, neste caso.

No JavaServer Faces 2.0, usamos a anotação @ManagedBean, de javax.faces.bean.ManagedBean, para registrar a classe como sendo uma Managed Bean onde, através do atributo name, damos o nome que será acessível pelos componentes das páginas JSF. No caso, chamamos de meuManagedBean.

O conteúdo é exibido pelo método público getTexto(), responsável por enviar as informações do Managed Bean para a página JSF e exibi-las através da tag <h:outputText />. A Figura 3 mostra como funciona essa integração.

Um managed bean possui um escopo onde, no caso, está definido como por requisição[3]. Este escopo é definido na anotação @RequestScoped, de javax.faces.bean.RequestScoped.


[3] Isso indica que as informações transmitidas serão recebidas e permanecerão apenas na página ao qual foi requisitada. Se você navegar para outra página, estas informações se perdem.

Componente da página JSF lendo o Managed Bean

Figura 3. Componente da página JSF lendo o Managed Bean

Os Beans em JSF

Um bean em Java é uma classe que expõe atributos/propriedades e eventos em um ambiente como o JSF. Um atributo é nada mais que uma variável nomeada com um determinado tipo que pode ser lido ou escrito. No bean, existe a convenção de declarar tais atributos como sendo do tipo privado e expô-los através de métodos públicos que encapsulam seus valores com as iniciais: set e get que servem para atribuir um valor e para pegar este valor respectivamente.

Utilizando Getters e Setters em um Managed Bean

Para compreender melhor estas características, vamos modificar novamente o exemplo de modo que possamos enviar dados de um campo e recebê-los.

Rascunho da representação final do exemplo

Figura 4. Rascunho da representação final do exemplo

Altere a página index.xhtml como mostra o trecho a seguir:

<h:form>
<h:inputText id="texto" value="#{meuManagedBean.texto}" />
<br />
<h:commandButton value="Enviar Texto" action="enviar" />
<br />
<h3><h:outputText value="#{meuManagedBean.texto}" /></h3>
</h:form>

E altere o Managed Bean MeuManagedBean adicionando o método setText() e modificando o método getText() como mostra o trecho a seguir:

public String getTexto() {
return texto;
}
public void setTexto(String texto) {
this.texto = texto;
}

Pronto, basta rodar o exemplo que verá o resultado.

Submissão do texto da página para o Managed Bean e retornando

Figura 5. Submissão do texto da página para o Managed Bean e retornando

Na próxima Parte

Desta vez você utilizou mais dois componentes: <h:inputText /> e <h:commandButton />. O primeiro permite a inserção de dados. O atributo id é o nome atribuído ao componente e o value possui a expressão JSF que contém a ligação entre o componente e o atributo no Managed Bean. O segundo componente, o <h:commandButton />, teve o atributo value que representa o texto a ser exibido no componente e action, que chama um método no servidor e, se não houver método, recebe como valor uma string qualquer, que pode indicar navegação para outra página ou não.

Na Parte 3 de JavaServer Faces 2.0 na Prática teremos uma visão geral da arquitetura do framework, com pequenos exemplos funcionais em alguns dos seus aspectos.

Tags: , , , ,


Próxima página »