Вы находитесь на странице: 1из 9

capa_

Melhorando o
desempenho de
aplicações em JSF
Aumente a escalabilidade através de
configurações e refatorações efetivas

Adriano Castro | adrianocastro189@gmail.com


é formado em Ciência da Computação pela Universidade Federal de Juiz de Fora e atua como desenvolvedor Java pela TO Brasil.
Além disso é criador e desenvolvedor dos projetos Checando.com.br e toString (www.tostring.com.br).

/ 12
Aplicações JSF possuem escalabilidade ameaçada quando utilizado
sem o conhecimento básico da especificação do framework ou da
implementação escolhida. Muitas vezes não sabemos como proce-
der diante de um cenário com recursos limitados e a performance
da aplicação acaba sendo prejudicada. Este artigo irá mostrar como
planejar e refatorar sistemas em JSF de acordo com a disponibilida-
de de recursos em ambientes de produção.

O que motiva a escolha do JSF como arquitetura de


referência para uma aplicação Web baseada em
Java? Talvez seja a facilidade de desenvolver inter-
de acordo com as peculiaridades de cada sistema.
Dessa forma, as estratégias de otimização nem sem-
pre suprem completamente tais peculiaridades. Por
faces gráficas complexas; talvez seja sua capacidade isso é muito importante analisar o perfil da aplicação
de manter as camadas de modelo, controle e visu- antes de decidir como arquitetá-la ou refatorá-la.
alização bem separadas e injetáveis por containers, Nos primeiros tópicos serão abordados o consu-
ou até mesmo sua característica orientada a eventos mo de memória e processamento pelo JSF para man-
que permite o desenvolvimento de aplicações tão ri- ter o estado dos componentes visuais presentes na
cas quanto uma aplicação desktop. Mas o que torna view. Você verá como é possível gerenciar a ordem de
o JSF tão robusto pode também o fazer pouco esca- prioridade de cada um desses recursos em detrimen-
lável. Segundo Eelco Klaver, na apresentação citada to do outro levando-se em conta os recursos dispo-
como referência para este artigo, enquanto aplica- níveis no servidor de aplicações utilizado. Você verá
ções web tradicionais servem a centenas de usuá- também como fazer uso dos conversores e validado-
rios, aplicações JSF podem não suportar 50 usuários. res presentes no JSF de uma forma menos impactan-
Nesse cenário, os maiores gargalos são o tamanho da te e, principalmente, o quanto é importante dizer ao
sessão, o consumo de CPU e o uso de banda. Mas por
JSF quando utilizá-los. Por fim serão apresentados
que a utilização do JSF é tão custosa? Cada requisi-
parâmetros de configuração que podem contribuir
ção feita a uma aplicação JSF faz com que o contai-
em melhorias de desempenho. Espera-se, entretan-
ner instancie um objeto de contexto responsável por
to, que o leitor tenha um conhecimento mínimo da
executar o fluxo de fases do framework. Esse objeto
especificação do Java Server Faces ou que pelo me-
não é thread-safe, isto é, ele atende apenas a uma
nos esteja familiarizado com seu uso. De qualquer
requisição por vez. Dessa forma, cada requisição, por
mais que seja um simples post via AJAX, resulta em forma, no início de cada tópico será dada uma breve
um grande consumo de processamento e memória introdução a respeito do que motivou tal otimização.
no ciclo de vida desse objeto.
Detalhado o problema é possível então modelar Saving State Method
uma estratégia de otimização que visará diminuir o O saving state method (método de armazena-
tempo e o consumo de recursos entre cada requisição mento de estado) foi escolhido para iniciar o proces-
e resposta de uma aplicação JSF. Tal estratégia será so de otimização de uma aplicação JSF. E não foi por
granularizada nos tópicos seguintes. É importante acaso. Ele diz respeito a uma decisão arquitetural
ressaltar que as decisões de implementação variam que refletirá impactando a aplicação por completo

13 \
pois refere-se a um recurso muito poderoso do JSF: O método client faz com que o estado da árvore de
a manutenção do estado de seus componentes que componentes seja armazenado no cliente. Em outras
pode ser configurada através do parâmetro javax.fa- palavras, o código da view que será gerado (HTML,
ces.STATE_SAViNG_METHOD. por exemplo) passa a conter uma String enorme, co-
Sabe-se que as requisições web são stateless (sem dificada em Base64 e que representa o estado dos
persistência de estado) ao contrário do JSF, que man- componentes que fazem parte dela. Com essa String
tém o estado dos componentes entre as requisições. armazenada no cliente, o servidor passa a manter
Para controlar os estados de todos os componentes menos informações na sessão do usuário, resultando
presentes na view, uma árvore de estados gerenciada em economia de memória em detrimento de CPU, já
pelo framework deve ser armazenada em algum local que a cada requisição o estado deve ser decodificado,
de forma a ser carregada e atualizada. O JSF permite remontado e codificado novamente para a resposta.
que o desenvolvedor decida onde mantê-la. Além disso, uma quantidade maior de informações
Para dar suporte a essa escolha o JSF disponibi- trafega. isto é, abre-se mão de processamento e ban-
liza o parâmetro de contexto javax.faces.STATE_SA- da em prol de um menor consumo de memória. A fi-
ViNG METHOD que deve ser inserido no arquivo web. gura 1 demonstra como essa grande String codificada
xml da aplicação. Os valores aceitos para este parâ- é armazenada no código-fonte HTML de um cadastro
metro são: server - valor padrão quando o parâmetro simples de usuários com pouco menos de 10 campos.
for omitido - e client, como exemplifica a Listagem Neste exemplo, o valor do campo hidden cujo iD é
1. O que distingue as duas opções pode parecer sim- javax.faces.ViewState é enviado a cada requisição e
ples: o método server armazena os estados no ser- decodificado para que o JSF possa restaurar o estado
vidor enquanto o client os armazena no lado cliente do formulário.
da aplicação. As implicações em termos de consumo,
entretanto, diferem muito.
Listagem 1. Exemplo de configuração do parâmetro.
<context-param>
<param-name>
javax.faces.STATE_SAVING_METHOD
</param-name>
<param-value>client</param-value>
</context-param>

A performance apresentada por uma aplicação


em um determinado ambiente está muito relacio-
nada à quantidade de recursos de processamento,
Figura 1. Armazenamento do estado dos componentes no HTML
memória e banda do hospedeiro. É necessário ter co-
gerado.
nhecimento da disponibilidade destes recursos, pois
esta informação será relevante na escolha do método. Por outro lado, é muito importante analisar o que
Uma escolha malfeita resultará em desperdício de re- cada decisão implica em termos de usabilidade e se
cursos e, consequentemente, na perda de performan- as consequências de uma opção não interferem no
ce. produto final. Por exemplo, a opção server prejudi-
O processo de otimização se resume em colocar ca a funcionalidade de navegação entre históricos do
na balança o quanto de recurso se tem disponível e browser, enquanto o método client fornece pouca se-
o consumo resultante de acordo com cada opção. O gurança, já que expõe o estado dos componentes no
método de armazenamento server faz com que o JSF código gerado ao cliente. Além dessas, existem outras
armazene o estado dos componentes no servidor, re- implicações que devem ser levadas em conta que não
sultando em um maior consumo de memória nesse serão listadas aqui de forma a focar apenas na otimi-
lado e um consumo menor no lado do cliente. Com zação de aplicações em JSF.
esta opção, o consumo de banda é menor, já que não Não existe, assim, uma opção melhor que a outra.
há necessidade de armazenar informações a respeito Existe uma opção que melhor se adapta às necessida-
do estado dos componentes já que menos informa- des de cada aplicação e essa análise deve ser feita por
ções trafegam. Para aplicações que fazem uso intenso alguém que, além de conhecê-la por completo tam-
de ajax, onde o número de requisições é alto, perce- bém conhece quem a hospedará. Por esse motivo, se
be-se uma melhoria no tempo de resposta quando se a escolha acabar sendo a opção que apresenta a pior
tem limitações de tráfego por parte do servidor ou performance, deve-se pensar em aumentar a quanti-
quando a conexão do cliente não é das melhores. dade de recursos disponíveis no hospedeiro.

/ 14
Escopo dos managed beans Escolha com cuidado o escopo de seus
Todo managed bean gerenciável pelo JSF deve beans
possuir um escopo, ou pelo menos a indicação ex- Beans cujo escopo é Application, Session ou
plícita de que não pertence a escopo algum. Este View podem ocupar significantemente grande par-
escopo determina o local onde o bean ficará arma- te da memória em ambientes acessados por grandes
zenado e, principalmente, o tempo de vida de suas quantidades de usuários e por isso devem ser evita-
instâncias. Os escopos disponíveis pelo JSF são Re- dos. É recomendável guardar nestes beans somente
quest, View, Session, Application, Custom e None. A os componentes ou as informações que realmente
indicação do escopo ao bean pode ser feita tanto no necessitam ser persistidas entre as requisições. Há
faces-config.xml quanto por annotations na própria quem critique o uso de mais de um bean por view,
classe. mas, em determinados casos, isso pode ser necessá-
De uma forma bem resumida - apontando ape- rio, já que um dos beans pode ser usado apenas para
nas o que interessa para analisá-los em termos de os objetos que realmente precisam sobreviver a estas
desempenho e consumo de recursos - managed be- requisições e o outro para objetos que podem ser des-
ans com escopo de Request são instanciados pelo cartados após a resposta.
JSF no início de uma requisição e morrem após o Ao mesmo tempo é recomendável evitar que
response ser enviado. Managed beans cujo escopo é beans responsáveis por consultas ao banco tenham
o de View nascem quando o JSF cria uma nova view, escopo de request quando a página possuir renderi-
permanecem vivos enquanto requisições post são zações parciais. Requisições realizadas dentro desta
realizadas para a mesma página e morrem quando página com o objetivo de renderizar porções da mes-
outra view é criada a partir do modelo de navegação ma, como, por exemplo, as feitas em ajax para popu-
lar combos ou preencher componentes, resultarão
do JSF (vide JSF Navigation Model).
em uma nova instanciação dos beans e, consequen-
O escopo de um managed bean, quando omitido,
temente, uma nova consulta ao banco.
é o Request. É comum não informar o escopo de um
Dessa forma, é necessário analisar, bean por bean,
bean, muitas vezes por desconhecimento, e isso faz
quais deles merecem ou não ter um escopo mais cus-
com que todos os managed beans da aplicação sejam
toso, em termos de memória e processamento.
criados e eliminados durante uma única requisição.
isso resulta em uma carga de processamento mui-
to grande, pois beans que realizam instanciações
Utilize o CustomScope com mais
aninhadas ou que acessam a base de dados em sua frequência
inicialização para carregar os dependentes são ini- Este subtópico foi baseado no livro Java Ser-
cializados a todo o tempo, inclusive em requisições ver Faces 2.0 - The Complete Reference, escrito por
para atualizações parciais, como as em ajax. um dos desenvolvedores da especificação do JSF, Ed
Outro equívoco cometido com frequência é a Burns.
utilização do escopo View em todos os managed O escopo Request é muito utilizado em aplica-
ções JSF por ser uma ponte de passagem de dados en-
beans por manter os valores dos objetos de modelo
tre requisições e, principalmente, por ter um tempo
vivos entre requisições para a mesma página ou por
de vida curto. Este escopo, entretanto, faz parte da
que eles são mais compatíveis com componentes de
especificação de Servlets e, por esse motivo, atende
terceiros que envolvem paginação e estados mais
a seus contratos. Entre os termos deste contrato in-
complexos. Um bean cujo escopo é View pode ficar
cluem-se as notificações de listeners que podem ou
alocado na memória do servidor durante um longo
não ser registrados. independentemente de nenhum,
período de tempo. Para grandes beans e muitos usu- um, ou até mais de um listener é possível perceber
ários o consumo de memória se torna absurdo. impactos na performance de cada requisição.
Managed beans cujo escopo é Session perma- Para dar base à otimização desses beans, volta-
necem vivos enquanto a sessão do usuário estiver mos à definição de escopos, onde apresentamos o
ativa e o escopo Application mantém os beans vivos CustomScope. Ele permite ao desenvolvedor definir,
enquanto a aplicação estiver viva. Por fim, o esco- criar ou utilizar escopos personalizados ou forneci-
po Custom será detalhado no final deste tópico e o dos à parte. Tal escopo recebe como parâmetro uma
None significa que o bean tem seu escopo determi- EL que deve apontar para um objeto que implementa
nado pelo bean que o mantém. java.util.Map. Dessa forma o tempo de vida do bean
Selecionar bem o escopo dos managed beans passará a depender do tempo de vida do mapa utili-
de uma aplicação é crucial para seu desempenho. zado. Utilizar o CustomScoped com um escopo criado
Quanto menos deles houver associados à sessão ou e gerenciado por você é uma tarefa trabalhosa e pode
à aplicação melhor. trazer ganhos ao desempenho se bem-feito, mas não

15 \
é a criação de escopo que será sugerida aqui, e sim a 3 contêm um conversor e como eles são utilizados,
utilização de um escopo introduzido na versão 2.0 do respectivamente. Para isso será adotado um exemplo
JSF cujo tempo de vida é sutilmente reduzido e não de cadastro de veículos.
tem seu desempenho impactado pelos motivos cita-
dos anteriormente. Listagem 2. Criação do conversor.
Este novo escopo é chamado de FacesContext at- package cadastroplacas;
tributes scope e tem o tempo de vida definido pelo
tempo de vida da invocação do FacesServlet. Seu import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
acesso é realizado através de uma EL como no exem- import javax.faces.component.UIComponent;
plo abaixo: import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
#{facesContext.attributes} import javax.faces.convert.FacesConverter;

@FacesConverter(value = “cadastroplacas.
Recomenda-se, a partir daí, usar o CustomScoped
ConversorPlaca”)
apontando para este mapa de atributos do public class ConversorPlaca implements Converter {
FacesContext como alternativa ao RequestScoped de
forma a ter ganhos de desempenho para beans cujo public ConversorPlaca() {
objetivo foi citado no início deste sub-tópico. System.out.println(“Instância de
ConversorPlaca criada.”);
@ManagedBean }
@CustomScoped(value = “#{facesContext.attributes}”)
public class UmBeanQualquer { @Override
public Object getAsObject(FacesContext context,
} UIComponent component, String value) {
return new Placa(value.substring(0, 3),
value.substring(3));
}
Otimizando as validações e conversões
@Override
Converters e validators - conversores e validado-
public String getAsString(FacesContext context,
res, respectivamente - são dois recursos muito pode- UIComponent component, Object value) {
rosos do JSF e estão presentes nas primeiras fases do Placa placa = (Placa) value;
ciclo de vida de uma requisição. É através deles que return placa.getPrefixo().toUpperCase() + “-” +
os valores preenchidos nos clientes são convertidos placa.getNumero();
de String para os tipos do modelo da aplicação e va- }
lidados de acordo com as regras de negócio de cada }
um. Mais detalhes a respeito do ciclo de vida serão
vistos no próximo tópico.
É recomendável sempre utilizar os conversores Listagem 3. Utilização do conversor de placas.
e validadores presentes na implementação do JSF
<h:body>
utilizada, pois eles atendem a maioria dos casos e <h:form>
já são otimizados. De qualquer forma, o JSF fornece <h:panelGrid columns=”2”>
interfaces que permitem aos desenvolvedores criar e <h:outputLabel value=”Placa:” />
reutilizar implementações próprias destes recursos. <h:inputText value=”#{cadastroPlacaBean.placa}”
Quando componentes personalizados por demandas converter=”cadastroplacas.ConversorPlaca” />
peculiares de uma aplicação são construídos é quase
<h:outputText value=” “ />
certo que eles acompanharão um conversor e, pelo
<h:commandButton value=”Cadastrar” />
menos, um validador, também personalizados. </h:panelGrid>
A forma mais comum de se implementar um </h:form>
conversor é criando uma classe que implementa a </h:body>
interface javax.faces.convert.Converter e configu-
rando o JSF através de entradas no faces-config.xml
ou através de anotações para permitir ao container Foram omitidos também os outros campos que pos-
injetar instâncias destes recursos na aplicação. Estes sivelmente seriam relevantes a um cadastro de veí-
dois passos já bastam, mas as boas práticas na criação culos, assim como o bean de cadastro de placas, pois
de conversores e validadores serão omitidas por não não queremos entrar no mérito da funcionalidade,
fazer parte do escopo deste artigo. As Listagens 2 e mas sim no consumo de recursos dos conversores.

/ 16
Para se ter uma ideia dos efeitos causados na aplica- até que a aplicação não esteja mais em execução. A
ção, colocamos uma chamada à saída padrão do Java Listagem 5 mostra como o componente deve consu-
no construtor de ConversorPlaca, pois iremos focar mir essa única instância do conversor.
este tópico na instanciação desnecessária de conver-
sores para casos onde eles são consumidos da manei- Listagem 5. Como a tela deverá passar a consumir o
ra convencional. componente.
No momento em que a tela é carregada, assim <h:outputLabel value=”Placa:” />
como em cada evento disparado pelo botão “Cadas- <h:inputText value=”#{cadastroPlacaBean.placa}”
trar”, uma nova instância de ConversorPlaca é criada. converter=”#{conversorPlaca}” />
isso acontece, pois no início o JSF busca o objeto do
modelo para convertê-lo e exibi-lo no campo. Já du-
rante o evento do botão, o valor do campo preenchido Com essa simples alteração economiza-se me-
é convertido para ser validado e atualizado no mo- mória, já que menos objetos do conversor serão ins-
delo. É possível perceber esse comportamento pela tanciados para cada requisição, além de evitar pro-
escrita da frase “instância de ConversorPlaca criada” cessamento desnecessário.
inúmeras vezes na saída padrão do Java enquanto se
utiliza o cadastro - estamos utilizando a saída padrão Uso de immediate nos campos e
apenas para simplificar o código, mas recomenda-se eventos
apontar sempre para o log da aplicação em questão. Como dito no início do artigo, uma de nossas me-
Sabe-se que a instanciação desnecessária e des- tas será reduzir o tempo gasto em um request. O JSF
controlada de objetos é um fator que compromete processa cada requisição em um fluxo de seis fases.
o desempenho. No exemplo acima estamos falando Explicar detalhadamente cada fase não faz parte do
apenas de um conversor e duas requisições, mas em escopo do artigo, mas um entendimento superficial
ambientes reais pode haver uma grande quantidade é necessário para otimizar as requisições que se apli-
deles em conjunto com um número maior de usuários cam a este tópico.
e eventos. Restore View é a primeira das seis fases. É aqui
Cada instância criada deste conversor será des- que o JSF obtém ou cria a view em que o usuário se
cartada ao final da requisição e o coletor de lixo pro-encontra. Esta view é mantida através de componen-
vavelmente cuidará dela, por isso não se preocupe, tes em estrutura de árvore. Logo após executada, se
você não vai ter problemas de estouro de memória a requisição se trata de um post, as próximas fases
por culpa dos conversores de sua aplicação. Entre- serão executadas, caso contrário ele irá diretamente
tanto por que não reduzir essa quantidade de instan- para a última delas. Considerando então uma requisi-
ciações já que é possível? Você poupará a JVM de um ção post, a segunda fase, Apply Request Values, recu-
trabalho desnecessário com apenas algumas modifi- pera os valores preenchidos no formulário submetido
cações. em formato de String e que serão convertidos nos ti-
Os beans cujo escopo é Application já foram des- pos corretos de acordo com a associação dos campos
critos em tópicos anteriores e este escopo será utili- com os objetos em seu managed bean. Em seguida,
zado para manter apenas uma instância do conver- a fase Process Validation realiza as validações dos
sor durante o tempo de vida da aplicação. Para isso, campos e se todos os campos forem válidos, Upda-
o conversor será tratado a partir de agora como um te Model Values aplica os valores no modelo. Por fim
managed bean e o JSF cuidará de sua instanciação invoke Application executa os eventos associados à
antes de começar a atender às requisições. A única requisição e Render Response atualiza a view a ser
alteração necessária na classe do conversor está pre- retornada para o usuário. Cada campo presente em
sente na Listagem 4. um formulário passa por todas estas fases e não é
Listagem 4. Alterações no conversor. possível ignorá-las. É possível, entretanto, aperfeiço-
ar parte do processo.
@FacesConverter(value = “cadastroplacas. Existem muitos casos onde um formulário possui
ConversorPlaca”) procedimentos internos que o modifica à medida que
@ManagedBean(eager = true)
o usuário o preenche. Para facilitar o entendimento
@ApplicationScoped
public class ConversorPlaca implements Converter { imagine um exemplo de cadastro de usuários onde,
na seção de endereço, há uma caixa de seleção de ci-
} dade cujo preenchimento depende do que foi selecio-
nado previamente na caixa de seleção de estado. Este
A partir de agora, sempre que a aplicação iniciar, uma campo permanece vazio e é preenchido no momento
instância de ConversorPlaca será criada e mantida em que um estado é selecionado. O evento que pre-

17 \
enche a caixa de cidades pode ser executado por uma especial de memória chamada Flash em JSF que ser-
requisição em ajax ou não, mas o que importa é que ve apenas como uma ponte para passagem de valores
ela será executada seguindo o fluxo do JSF. através de uma requisição. Um bean de cidades foi
Considere agora que esse formulário contém não criado com a simples tarefa de retornar uma lista de
somente os campos de UF e cidade, mas todos os acordo com a UF selecionada, mas ele será omitido,
campos relevantes de um cadastro de usuário com- pois depende muito de como as camadas de negócio
pleto como nome, data de nascimento etc. Qualquer são implementadas em cada aplicação.
evento no campo UF enviará todos os valores preen- O exemplo da Listagem 6 é uma prática ruim em
chidos nos campos e as fases do JSF se aplicarão a to- JSF, pois, como dito anteriormente, há o desperdício
dos eles. Nestes casos há um desperdício de recursos, de recursos na conversão e validação de todos os cam-
pois o formulário inteiro está sendo processado pelo pos no evento disparado pela lista de estados. Dessa
fluxo do JSF quando o que importa ali é obter a UF forma, para aperfeiçoar esta requisição precisaremos
selecionada e carregar uma lista de cidades para pre- dizer ao JSF que eventos gerados a partir da lista de
encher o campo. A Listagem 6 ilustra esse exemplo. estados se tratam apenas de atualizações parciais em
nossa view e não representam a ação de cadastro.
Listagem 6. Exemplo de uma tela de cadastro de É possível alcançar esse comportamento a partir
usuários. do atributo immediate. Este atributo garante ao com-
<h:panelGrid columns=”2”> ponente que sua conversão e validação, assim como
<h:outputLabel value=”Nome:” /> os eventos dos botões, se darão na primeira fase Ap-
<h:inputText value=”#{flash.nome}” /> ply Request Values. Com isso, percorre-se um “ata-
lho” no fluxo de fases somente com as informações
<h:outputLabel value=”Data de nascimento:” />
que interessam para aquela requisição. E este atalho
<h:inputText value=”#{flash.dataNascimento}” />
reduz o tempo do ciclo de vida da requisição, dando
<h:outputLabel value=”Logradouro:” /> lugar à próxima requisição mais rapidamente (lem-
<h:inputText value=”#{flash.logradouro}” /> bre-se que cada requisição é executada unitariamen-
te pelo JSF, pois o Faces Context não é thread-safe).
<h:outputLabel value=”Número:” />
<h:inputText value=”#{flash.numero}” /> Voltando ao exemplo da Listagem 6, iremos adicionar
o atributo immediate=”true” no campo que irá dispa-
<h:outputLabel value=”Complemento:” /> rar o evento e adicionar um novo botão, também com
<h:inputText value=”#{flash.complemento}” /> este atributo, que irá disparar o request “pegando o
atalho” discutido anteriormente. Não iremos adicio-
<h:outputLabel value=”UF:” /> nar o atributo no botão Cadastrar, pois não queremos
<h:selectOneMenu value=”#{flash.estado}” que o formulário inteiro tenha este comportamento.
onchange=”this.form.submit()” valueChangeListener=
Vamos otimizar somente o que dá pra otimizar aqui.
“#{cidades.atualizarListaCidades}”>
<f:selectItems itemLabel=”#{estado}”
Por fim alteraremos o evento onchange para chamar o
itemValue=”#{estado}” value=”#{cidades.estados}” novo botão criado. A Listagem 7 mostra como ficará o
var=”estado” /> código.
</h:selectOneMenu> Listagem 7 Aplicação do atributo immediate=”true”
no cadastro
<h:outputLabel value=”Cidade:” />
<h:selectOneMenu value=”#{flash.cidade}”>
<f:selectItems itemLabel=”#{cidade}” <h:panelGrid columns=”2”>
itemValue=”#{cidade}” value=”#{cidades.cidades}” <h:outputLabel value=”Nome:” />
var=”cidade” /> <h:inputText required=”true” value=”#{flash.nome}”
</h:selectOneMenu> />

<h:outputText value=” “ /> <h:outputLabel value=”Data de nascimento:” />


<h:commandButton action=”sucesso” <h:inputText value=”#{flash.dataNascimento}” />
value=”Cadastrar” />
</h:panelGrid> <h:outputLabel value=”Logradouro:” />
<h:inputText value=”#{flash.logradouro}” />

Repare que foram omitidos muitos outros cam- <h:outputLabel value=”Número:” />
<h:inputText value=”#{flash.numero}” />
pos relevantes ao cadastro de usuários de forma a fa-
<h:outputLabel value=”Complemento:” />
cilitar o entendimento das alterações que serão reali- <h:inputText value=”#{flash.complemento}” />
zadas. Outro detalhe importante é a ausência de um
managed bean para o usuário. Foi utilizado um tipo

/ 18
plos de como é possível obter melhores resultados
<h:outputLabel value=”UF:” /> em uma aplicação a partir de pré-configurações. Es-
<h:selectOneMenu immediate=”true” tas configurações deverão ser aplicadas no web.xml
value=”#{flash.estado}” onchange=”document.
de sua aplicação.
getElementByid(‘form:atualizarCidades’).click()”
valueChangeListener=
“#{cidades.atualizarListaCidades}”> Project Stage
<f:selectitems itemLabel=”#{estado}” O JSF 2.0 introduziu um parâmetro responsá-
itemValue=”#{estado}” value=”#{cidades.estados}” vel por manter referência à fase atual da aplicação
var=”estado” /> representado pelo enum javax.faces.application.
</h:selectOneMenu> ProjectStage. Os valores de fase permitidos são De-
velopment, UnitTest, SystemTest e Production. Para
<h:outputLabel value=”Cidade:” />
<h:selectOneMenu value=”#{flash.cidade}”> não fugir ao escopo deste artigo não serão deta-
<f:selectitems itemLabel=”#{cidade}” lhados os comportamentos da aplicação de acor-
itemValue=”#{cidade}” value=”#{cidades.cidades}” do com cada fase disponível. Basta saber que o JSF
var=”cidade” /> consome mais recursos quando a aplicação está em
</h:selectOneMenu> fase de desenvolvimento, pois ele trabalhará fo-
cado em fornecer aos desenvolvedores facilidades
<h:outputText value=” “ /> como mensagens de erro mais detalhadas e possi-
<h:commandButton action=”sucesso”
bilidades de diagnóstico da aplicação maximiza-
value=”Cadastrar” />
</h:panelGrid>
das, tudo isso a custo de processamento e memória.
<h:commandButton style=”visibility: hidden” Um detalhe que passa despercebido é que algumas
id=”atualizarCidades” value=”atualizarCidades” iDEs adicionam, por conta própria, o valor Develo-
immediate=”true” /> pment para este parâmetro no momento da criação
de novos projetos. Muitas vezes este valor é manti-
do nos ambientes de produção após a publicação por
Para grandes formulários é possível notar uma di- descuido ou por desconhecimento do parâmetro, o
ferença significativa - em questão de milissegundos que é prejudicial ao desempenho. Veja o exemplo da
- nos eventos disparados em ajax que passam a usar Listagem 8 que contém um trecho do web.xml gera-
o immediate como forma de não submetê-los por do automaticamente pelo NetBeans 7.1.2 quando da
completo ao fluxo de fases do JSF. É necessário lem- criação de uma nova aplicação web:
brar que este recurso não se restringe a requisições Listagem 8. Exemplo de configuração automática do
em ajax, mas também para requisições convencio- NetBeans.
nais que envolvam o refresh da página por completo.
Recomenda-se que, para aplicações em processo de
otimização, todos os formulários sejam revistos e, <context-param>
<param-name>javax.faces.PROJECT_STAGE
sempre que houver atualizações parciais em sua es-
</param-name>
trutura, o atributo immediate=”true” seja utilizado <param-value>Development</param-value>
nos campos e em botões com a finalidade única de </context-param>
realizar a requisição do evento. As requisições ter-
minarão mais rapidamente e o JSF irá suportar uma
quantidade maior delas em um dado espaço de tem- De acordo com a especificação do JSF, o valor de-
po. fault de PROJECT_STAGE é Production, por isso re-
mova esta tag de seu web.xml antes de cada publica-
Configurações adicionais ção. Mantenha este valor somente em seu ambiente
A especificação do JSF traz uma série de parâme- local de desenvolvimento.
tros de inicialização que permitem aos desenvolve-
dores configurá-la. Quanto maior for o conhecimento Facelets Refresh Period
desses parâmetros e do perfil da aplicação maior se- Durante a fase de desenvolvimento de uma apli-
rão a qualidade e o desempenho do produto gerado. cação, por questões de produtividade, é desejável que
Além desses parâmetros há também os parâmetros as alterações nos arquivos físicos das páginas sejam
específicos de cada implementação do JSF. Cada im- compiladas em tempo de execução para que elas fi-
plementação pode ainda fornecer valores padrões quem disponíveis no browser sem que haja a neces-
para estes parâmetros. sidade de um restart no servidor. E para que isso seja
Descrever cada um dos parâmetros tornaria este possível o Facelets verifica se há alterações nestas
artigo enorme, por isso serão fornecidos dois exem- páginas periodicamente. Essa varredura consome re-

19 \
Conheça mais sua implementação
Fabricantes de implementações da especificação JSF geralmente fornecem parâmetros de inicialização
adicionais que permitem ajustar ainda mais sua aplicação. Por isso não se limite a conhecer somente a
especificação do JSF, mas também a documentação da implementação utilizada.
Até a data desta publicação, o The Apache Software Foundation fornecia em seu site oficial (http://
myfaces.apache.org) uma seção chamada Web Context Parameters contendo a lista de parâmetros
presentes no JSF e os valores padrões adotados pelo MyFaces - uma das implementações do JSF dispo-
níveis - além de seus parâmetros específicos. Há uma categorização dos parâmetros e uma das catego-
rias é “performance”. Dê uma atenção especial a ela.
Espera-se que cada fabricante forneça essas informações, por isso é recomendável que você estude e
trace um plano de configuração de acordo com o perfil de sua aplicação.

cursos e muitos não sabem, mas é possível aumentar hospedar uma aplicação. A árdua tarefa de otimizar
seu período de execução ou até mesmo desativá-la. aplicações complexas requer paciência, mas também
A utilidade dessa recompilação automática se requer que você saiba o que está fazendo. Parte-se do
restringe ao ambiente de desenvolvimento. Afinal de princípio que ela já atende a seus clientes, mas pode
contas, a frequência com que uma aplicação é publi- atender melhor.
cada em ambientes de produção não justifica manter Um bom trabalho de otimização exige que você
o recurso ativado. Além disso, em muitos casos, pu- conheça bem sua aplicação e o framework utilizado.
blicações acompanham arquivos .java e sua atualiza- Por isso recomendo que leiam a especificação do JSF
ção requer o restart do servidor. e pelo menos um livro de referência completo. Muita
coisa já poderá ser óbvia pra você, mas sempre é pos-
Quando omitido, o período de atualização padrão do sível extrair detalhes pequenos que refletem melho-
Facelets depende da implementação do JSF utilizada rias no produto final.
– JSF é uma especificação e não uma implementação Além disso, recomendo utilizar ferramentas de
- e recomenda-se desligá-lo antes de cada publicação. perfil para que você possa observar as melhorias con-
Para desabilitar este recurso basta armazenar o valor sequentes das modificações e se o caminho seguido
-1 em seu parâmetro de inicialização correspondente, está correto.
como mostra a Listagem 9, que é um trecho do web.
xml de uma aplicação web.
Listagem 9. Desativação do recurso de atualização
do Facelets.
/referências
<context-param> > Java Server Faces 2.0 - The Complete Reference, Ed
<param-name> Burns, Chris Schalk;
javax.faces.FACELETS_REFRESH_PERIOD
</param-name> > JSF Best Practices: http://webmoli.com/2008/05/20/jsf-
<param-value>-1</param-value> best-practices/;
</context-param>
> Tuning JSF Applications - Session size matters: http://
www.nljug.org/pages/events/content/jspring_2008/
sessions/00017/;
Considerações Finais > JSF 2.0 Reminder: Project Stage: http://weblogs.java.net/
Não existe uma receita de bolo a ser seguida para
blog/driscoll/archive/2009/09/28/jsf-20-reminder-project-
otimizar suas aplicações. Como você pode ter per-
stage
cebido fizemos uso apenas da especificação do JSF
de forma a selecionar as decisões arquiteturais de
acordo com os recursos que temos disponíveis para

/ 20

Вам также может понравиться