Utilizando AJAX com JSF de maneira eficiente
Graças a natureza orientada à componentes e eventos do JavaServer Faces podemos implementar aplicações com AJAX de maneira simples e prática. Existem vários frameworks e conjuntos de componentes AJAX disponíveis para JSF, uns mais simples e super fáceis de integrar, outros mais chatinhos, porém bastante eficientes em determinados cenários. Entre eles o mais utilizado e prático sem dúvida nenhuma é o Ajax4jsf que é trazido juntamente com o conjunto de componentes Richfaces da JBoss, com ele é possível inserir recursos AJAX em aplicações JSF de forma transparente e bastante produtiva.
Mesmo com a toda a simplicidade e gama enorme de componentes/frameworks AJAX ainda assim estes recursos não são aproveitados de forma eficiente ao se desenvolver com JSF, muitos desenvolvedores mesmo utilizando-se destes recursos continuam pensando de forma “click’n’wait”, o que no final das contas acaba meio que “anulando” os benefícios oferecidos por tais recursos.
Na onda de aplicações ricas e WEB2.0 não podemos deixar de aproveitar certos recursos essenciais para desenvolver tais aplicações. Utilizar estes recursos em JSF de forma eficiente trará ganhos consideráveis em vários aspectos para o projeto, à equipe de desenvolvimento e principalmente ao cliente, entre eles podemos destacar aspectos como performance, escalabilidade, produtividade e principalmente usabilidade.
Mas fica a pergunta: Como conseguir isso?
Abandonando a velha escola
O que precisamos fazer é deixar de lado o pensamento em interfaces “click’n'wait”, deixar de lado o desenvolvimento baseado em “action-like”, abandonar a navegação dirigida à páginas, precisamos aproveitar melhor os recursos AJAX oferecidos por frameworks e componentes ricos, inserir maior usabilidade nas páginas, aprender um pouco sobre AJAX Patterns e obter mais produtividade ao desenvolver páginas com JSF.
Com estes pensamentos em mente já temos uma melhor direção para um desenvolvimento mais eficiente. Para obter isso eu pretendo me utilizar de certas premissas básicas, como:
- Utilizar um conjunto de componentes ricos e um framework AJAX. (Neste caso eu optei pelo Richfaces/Ajax4jsf por ser bastante simples de usar e integrar, por ser estável e por ser bastante utilizado na comunidade, contudo, qualquer outro conjunto de componentes AJAX poderia ser utilizado, como Trinidad ou mesmo o IceFaces);
- Desenvolver as regras de navegação entre views orientada à estados e não à páginas;
- Inserir um maior controle de fluxo de navegação e inteligência nos managed beans;
- Utilizar algum framework de templating. (Optei pelo Facelets por ser simples, prático, produtivo, estável, ter uma excelente performance e principalmente por ter sido desenvolvido para JSF);
- Diminuir o número de páginas (xhtml, jspx, jsp etc) no projeto;
- Evitar reloads/refresh de páginas ao máximo, ou sempre que possível;
Observando a lista acima fica fácil ver que a maioria dos itens se complementam e colaboram entre si, porém o mais importante sem dúvida é o 2º item, “Desenvolver as regras de navegação entre views orientada à estados e não à páginas”, acho que este item resume 90% do que pretendo falar. Baseado nestas premissas básicas vou implementar uma aplicação bem simples (CRUD) e comentar certos pontos nela que facilitarão o entendimento.
Desenvolvendo as regras de navegação orientada à estados
Primeiramente devemos tirar da cabeça a maneira convencional de criar as regras de navegação orientada à páginas, ou seja, ter que desenvolver 3 ou 4 páginas para implementar um CRUD por exemplo, páginas como searchlist.jsp, add.jsp, update.jsp e show.jsp (algumas vezes se resume em até 2 páginas) devem ser descartadas. Ter várias páginas significa neste caso ter várias árvores de componentes, significa que o framework precisa gerar novas árvores de componentes a cada mudança de página, e isso custa memória e processamento no servidor, sem falar consumo de banda e overhead no cliente (browser).
Sendo, substituiremos essa abordagem da velha escola por outra mais eficiente, orientada à estados, em que utilizaremos somente uma única página que terá seu fluxo de navegação gerenciado por um managed bean mais inteligente.
A idéia principal tem por objetivo evitar escrever muitas páginas para representar cada view (tela), diminuindo assim o número de páginas no projeto, o número de regras de navegação no faces-config.xml, diminuindo o overhead no servidor e no cliente a cada refresh de página, obtendo uma melhor performance utilizando sempre a mesma árvore de componentes, inserir maior usabilidade na aplicação para o usuário, e claro, aproveitar eficientemente os recursos AJAX em cada página.
Logo, eu criei um template bem simples com Facelets para nossas páginas de CRUDs, com este template dá para ter uma idéia de como poderíamos escrever páginas bem melhores para nossas aplicações, o template (parte dele) seria algo do tipo:
[myCrudTemplate.xhtml]
<body>
<a4j:outputPanel ajaxRendered="true" id="mainOutputPanel">
<a4j:form>
<!-- bloco de pesquisa -->
<rich:panel id="searchlistBlock"
rendered="#{defaultBean.pesquisarState}">
<f:facet name="header">
Pesquisar
</f:facet>
<ui:insert name="searchlistBlock">
</ui:insert>
</rich:panel>
<!-- bloco de edição -->
<rich:panel id="addUpdateBlock"
rendered="#{defaultBean.adicionarState or defaultBean.editarState}">
<f:facet name="header">
Dados do Usuário
</f:facet>
<ui:insert name="addUpdateBlock">
</ui:insert>
</rich:panel>
</a4j:form>
</a4j:outputPanel>
</body>
Nosso template se resume em dois blocos, um bloco para pesquisa e exibição dos resultados (searchlistBlock):

e outro bloco para o formulário de inclusão e edição de cada registro (addUpdateBlock):

Estes blocos substituem as páginas que a velha escola sempre pregou, assim ao se pensar em navegar entre views (telas) nós não mais navegaremos entre páginas (recursos físicos), mas sim entre blocos (recursos lógicos) dentro daquela mesma página. Estes blocos serão gerenciados por estado(s) no managed bean e não mais regras de navegação do faces-config.xml, assim sempre que quisermos “mudar de tela” nós alteramos o estado atual no managed bean e atualizamos parte da página com AJAX escondendo os blocos desnecessários e exibindo os blocos correspondentes à nova view.
Reparem no template que os blocos somente serão renderizados (através do atributo rendered do componente rich:panel) de acordo com o estado atual da view.
Meu managed bean será como qualquer outro, porém eu terei um atributo para representar o estado atual da view (tela) e alguns métodos para expor este estado de maneira legível, logo meu managed bean será algo como:
[UsuarioCrudBean.java]
public class UsuarioCrudBean {
public static final String PESQUISAR_STATE = "pesquisar";
public static final String ADICIONAR_STATE = "adicionar";
public static final String EDITAR_STATE = "editar";
private String currentState = PESQUISAR_STATE;
private String nome;
private Usuario usuario;
private List<Usuario> usuarios = new ArrayList<Usuario>();
private UIPanel panelForm;
// métodos gets e sets
/**
* Pesquisa usuários por nome
*/
public void pesquisar() {
this.setCurrentState(PESQUISAR_STATE);
this.usuarios = UsuarioRepositorio.findUsuarioByNome(this.nome);
}
/**
* Prepara view adicionar
*/
public void prepareAdicionar() {
this.clear();
this.setCurrentState(ADICIONAR_STATE);
}
/**
* Adiciona usuário
*/
public void adicionar() {
UsuarioRepositorio.add(this.usuario);
this.pesquisar();
}
/**
* Prepara view editar
*/
public void prepareEditar() {
this.setCurrentState(EDITAR_STATE);
}
/**
* Edita usuário
*/
public void editar() {
// já edita diretamente na lista (a lista está como static)
this.pesquisar();
}
/**
* Exclui usuário
*/
public void excluir() {
UsuarioRepositorio.delete(this.usuario);
this.pesquisar();
}
/**
* Referente ao botão voltar
*/
public void voltar() {
this.clear();
this.pesquisar();
}
/**
* Limpa atributos
*/
private void clear() {
this.nome = "";
this.usuario = new Usuario();
this.cleanSubmittedValues(this.panelForm);
}
/*
* Métodos que expõem o estado à página
*/
public boolean isPesquisarState() {
String state = this.getCurrentState();
return (state == null || PESQUISAR_STATE.equals(state));
}
public boolean isAdicionarState() {
return ADICIONAR_STATE.equals(this.getCurrentState());
}
public boolean isEditarState() {
return EDITAR_STATE.equals(this.getCurrentState());
}
/**
* Limpa os componentes filhos para que depois eles possam ser recriados
* @param component
*/
protected void cleanSubmittedValues(UIComponent component) {
component.getChildren().clear();
}
}
As regras de navegação serão gerenciadas internamente pelo managed bean, a página (jsp, xhtml etc) deve trabalhar em cima dos métodos expostos pelo managed bean, e não do atributo currentState em si, ou seja, para a página não importa como está implementada as regras de navegação, a página somente precisa conhecer qual o estado atual para que assim ela possa renderizar ou não seus componentes.
Nossa página de CRUD utilizará o template myCrudTemplate.xhtml como base, segue abaixo o código fonte da página somente com o bloco de edição:
[usuarioCrud.xhtml]
<ui:composition template="/pages/myCrudTemplate.xhtml">
<!-- passa parâmetro para o template -->
<ui:param name="defaultBean" value="#{usuarioCrudBean}" />
<ui:define name="title">
Cadastro de Usuários
<t:saveState id="_bean" value="#{usuarioCrudBean}" />
</ui:define>
<ui:define name="searchlistBlock">
<!-- bloco de pesquisa -->
</ui:define>
<ui:define name="addUpdateBlock">
<h:panelGrid columns="2" id="panel2" binding="#{usuarioCrudBean.panelForm}" columnClasses="odd-row,even-row">
<h:outputLabel value="Login: "/>
<h:column>
<h:inputText value="#{usuarioCrudBean.usuario.login}" size="30" required="true" id="login"
requiredMessage="Campo Login é obrigatório."
readonly="#{usuarioCrudBean.editarState}"
style="#{usuarioCrudBean.editarState ? 'color: gray;' : ''}"/>
<br/>
<h:message for="login" errorStyle="color: darkred;"/>
</h:column>
<h:outputLabel value="Senha: "/>
<h:column>
<h:inputSecret value="#{usuarioCrudBean.usuario.senha}" size="30" redisplay="true"/>
<br/>
</h:column>
<h:outputLabel value="Nome: "/>
<h:column>
<h:inputText value="#{usuarioCrudBean.usuario.nome}" size="60" required="true" id="nome"
requiredMessage="Campo Nome é obrigatório." />
<br/>
<h:message for="nome" errorStyle="color: darkred;"/>
</h:column>
<h:outputLabel value="Blog: "/>
<h:column>
<h:inputText value="#{usuarioCrudBean.usuario.blog}" size="90" id="blog"/>
</h:column>
<h:outputLabel value="Ativo?"/>
<h:column>
<h:selectOneMenu value="#{usuarioCrudBean.usuario.ativo}" id="ativo"
requiredMessage="Campo Ativo é obrigatório."
required="true">
<f:selectItem itemValue="" itemLabel="[Selecione uma opção]" />
<f:selectItem itemValue="#{true}" itemLabel="Sim" />
<f:selectItem itemValue="#{false}" itemLabel="Não" />
</h:selectOneMenu>
<br/>
<h:message for="ativo" errorStyle="color: darkred;"/>
</h:column>
</h:panelGrid>
<a4j:commandButton value="Adicionar" action="#{usuarioCrudBean.adicionar}" rendered="#{usuarioCrudBean.adicionarState}"/>
<a4j:commandButton value="Editar" action="#{usuarioCrudBean.editar}" rendered="#{usuarioCrudBean.editarState}"/>
<a4j:commandButton value="Voltar" action="#{usuarioCrudBean.voltar}" immediate="true"/>
</ui:define>
</ui:composition>
Assim como nossos blocos principais (searchlistBlock e addUpdateBlock) do template, muitos componenentes também são renderizados ou mudam de estado dependendo do fluxo de navegação, um deles por exemplo é o botão “Editar” que somente será renderizado quando nossa view estiver no estado de edição:
<a4j:commandButton value="Editar" action="#{usuarioCrudBean.editar}" rendered="#{usuarioCrudBean.editarState}"/>
Na minha página usuarioCrud.xhtml eu estou passando a referência do managed bean atual como parâmetro para o template para que ele consiga gerenciar os blocos corretamente, isso me possibilita ter um template mais genérico para minhas páginas de CRUDs:
<ui:param name="defaultBean" value="#{usuarioCrudBean}" />
Atentem que eu estou utilizando o componente t:saveState do Myfaces Tomahawk para ampliar o escopo de conversação, com ele eu posso manter meus managed beans como escopo de request enquanto eu navego entre os blocos lógicos, depois de mudar literalmente de página (recurso físico) eu terei aqueles dados removidos da memória do servidor.
<t:saveState id="_bean" value="#{usuarioCrudBean}" />
Outra coisa interessante é que por estarmos sempre trabalhando sob a mesma árvore de componentes (viewRoot) é necessário resetar o estado de alguns componentes ou bloco de componentes quando necessário, pois mesmo que estes componentes não sejam renderizados eles ainda assim mantém o estado anterior.
No nosso caso eu estou sempre limpando o estado do formulário de edição ao clicar no botão “Voltar” da aplicação, que por sua vez faz uma chamada ao método cleanSubmittedValues(), é este método que se encarrega de limpar o estado anterior do formulário:
protected void cleanSubmittedValues(UIComponent component) {
component.getChildren().clear();
}
Existem outras abordagens para resetar o estado dos componentes de um formulário, eu busquei utilizar a maneira mais simples, porém creio que não seja a mais performática -neste caso-. Mesmo não possuindo a melhor performance ainda assim é -várias vezes- mais rápida que gerar todo uma nova árvore de componentes (utilizado pela velha escola), com toda certeza.
E quais seriam as vantagens dessa abordagem?
Existem várias vantagens em relação a abordagem da velha escola, entre elas podemos destacar:
- Menor consumo de memória e processamento no servidor, pois estaremos sempre trabalhando sob a mesma árvore de componentes (viewRoot);
- Menor overhead no cliente (browser), pois estaremos evitando reload completo de páginas;
- Menor tráfego de dados na rede, muito menor, pois estaremos apenas transportando pequenos blocos de página;
- Maior escalabilidade e performance na aplicação;
- Diminui drasticamente o número de pontos de manutenção na aplicação (páginas, arquivos de configuração etc);
- Renderização dos componentes muito mais rápida, sejam parciais ou grandes blocos lógicos;
- Maior usabilidade e controle de renderização parcial nas páginas;
- Evita o problema do botão voltar (back button);
- Evita resubmissão do formulário após um refresh (F5);
- Managed beans realmente mais inteligentes;
- Exibição das páginas com um aspecto mais leve, possibilitando ainda a utilização de efeitos através de frameworks javascripts;
- Facilidade em criar classes de managed beans mais genéricas (um CrudBean por exemplo);
- Melhor controle/tratamento de respostas entre cliente e o servidor (barra de progresso, timed out etc);
Bem, vantagens é o que não falta em relação a velha escola. Provavelmente possamos discutir mais algumas vantagens e até quem sabe desvantagens na lista de discussão do JavaSF.
Concluindo
Mesmo esta abordagem sendo superior a abordagem da velha escola ela ainda assim não é a “bala de prata”, como toda nova abordagem ela deve ser estudada e utilizada com bom senso, haverá momentos em que será mais prático e até melhor efetuar um reload completo de página, ou dividir os blocos lógicos em pequenas páginas para evitar grandes arquivos físicos, enfim, bom senso é algo que sempre deve ser levado em consideração.
Eu não me prendi a utilização dos frameworks ou conjuntos de componentes utilizados pois este não era o intuito do post, isso é algo simples e acredito que a maioria dos leitores não tenham dificuldades em relação a isso. Além do mais é possível implementar isso não somente com o Richfaces/Ajax4jsf, mas com qualquer outro framework ou conjuntos de componentes AJAX, por exemplo, no último projeto que participei implementamos nossas páginas utilizando-se desse conceito com Myfaces Trinidad, que por sinal está funcionando muito bem.
É bastante notório a velocidade na renderização das páginas, sendo aconselho vocês a fazerem alguns testes com esta abordagem e observarem o quanto mais rápido se torna o desenvolvimento e a renderização das páginas. Eu fiz a aplicação o mais simples possível para demonstrar essa abordagem, com certeza ainda é possível otimizar as requisições AJAX através de configurações do Ajax4jsf e do Richfaces, você pode ver mais sobre isso na documentação do mesmo.
Eu estou disponibilizando esta aplicação exemplo como prova de conceito, é um projeto do Eclipse (MyEclipse para ser mais exacto), sendo basta importa-lo e efetuar o deploy da aplicação.
Tags: AJAX, ajax4jsf, Boas Práticas, escalabilidade, facelets, ICEFaces, Java, JavaScript, JavaServer Faces, JEE, JSF, mojarra, myfaces, patterns, performance, richfaces, savestate, tomahawk, trinidad, usabilidade, web
April 10th, 2008 at 5:11 pm
Muito boa abordagem sobre os benefícios que o AJAX oferece nas nossas aplicações, em especial em JSF. Claro que não podemos criar aplicações em uma só página, ai vai o bom senso dos programadores…
Abraços
April 10th, 2008 at 7:08 pm
A idéia não é criar uma aplicação somente em uma única página, longe disso. Mas sim substituir conjuntos de telas (páginas) por blocos lógicos dentro da mesma página. Por exemplo, um CRUD muitas vezes se divide entre 2 a 4 páginas, neste caso teríamos uma única página dividida em 2 a 4 blocos para cada CRUD.
April 11th, 2008 at 7:21 am
Ponte,
Parabens . Este é um exemplo que eu estava procurando para começar a usar o rich pois sou iniciante.
Eu não sei usar facelets é tranquilo passar para jsp ?
Muito Obrigado.
April 11th, 2008 at 7:25 am
Sim, facelets é bem simples. Utilizar JSF hoje sem facelets é até “feio”, rss.. Um bom lugar para começar a aprender facelets é no artigo da devmedia, http://www.devmedia.com.br/articles/viewcomp.asp?comp=5332
April 12th, 2008 at 7:48 am
Boa … muito boa essa sua tacada.
Vc falou certo Rafael!
Ajax ainda é usado de uma meio fraca sem explorar sua capacidade 100%. Seu post mostrou que se vc fizer um projeto bem modular e reutilizável, pode-se sim explorar o Ajax de uma forma incrívelmente legal. Como vc disse, o JSF ajuda mesmo!
Tenho estudado e trabalhado com aplicações Ajax com Java, Php e Rails, e eu particularmente acho incrível essa capacidade do JSF em permitir vc reutilizar modulos e de renderizar componentes e seu sub-componentes inteiros e não somente um componente ou apenas um atributo específico como no php+html.
Muito legal mesmo seu post!
April 13th, 2008 at 7:35 pm
Olá Rafael
Primeiro gostaria de parabeniza-lo e seus parceiros pelo serviços prestados nos seus respectivos blogs. Vocês sempre abordando assuntos interessantes no meio do desenvolvimentos e sempre nos oferecendo uma excelente visão de um todo.
Meu nome é Bruno, tenho 21 anos e estou cursando Sistemas de Informação aqui em Jundiaí. Estou no meu último ano (4º ano), ou seja, ano de TCC…e juntamente com um companheiro de classe, resolvemos abordar uma tecnologia java…Avaliação comparativa dos frameworks de interface, JavaServer Faces vs Tapestry, iremos desenvolver um prototipo e em cima disso fazer nosso trabalho. Gostaria, se possivel, de algumas dicas, algum tipo de ajuda que possa ser útil para esse nosso projeto.
Desde já agradeço
Forte abraço e obrigado por tudo.
April 16th, 2008 at 4:21 am
Olá Rafael! Você usou aí qual versão do richfaces? Não sei se é isso, mas eu to usando o Facelets 1.2 e o Richfaces 3.2 e não funciona. O container não consegue carregar o richfaces e acontece um erro como esse:
http://www.guj.com.br/posts/list/58628.java
Se soube de algo, valeu!
April 21st, 2008 at 9:03 pm
[...] web, temos o costume de sempre pensar em navegação entre páginas. O Rafael Ponte apresentou uma alternativa no mínimo interessante para JSF utilizando RichFaces + [...]
April 25th, 2008 at 6:16 am
Não sei se vc tentou usar com Spring, mas eu tentei e me deparei com um problema:
Na declaração do meu bean, declarei também uma ‘managed-property’ que é utilizada pelo Spring.
Apenas por causa disso, eu tenho que colocar meu bean com escopo ’session’, pq na troca de painéis os botões param de funcionar.
Tem como corrigir isso?
April 25th, 2008 at 6:24 am
Olá Romulo, eu não entendi sua pergunta. De que parte exatamente você está falando?
April 26th, 2008 at 2:35 pm
Por exemplo: O managed bean tem uma propriedade q é injetada pelo Spring.
No painel da pesquisa aperte no botao adicionar. Se o managed bean estiver com escopo ‘request’, os botoes do painel de cadastrar nao funcionam, apenas dão refresh na página, e aí volta pra o painel da pesquisa.
Se eu tirar, lá no faces-config.xml, o ‘managed-property’ q o Spring usa, esse problema nao ocorre.
Ja testei usando xml e annotation do Spring.
April 26th, 2008 at 4:10 pm
Isso é muito estranho, eu não tive problemas com isso. Estranho mesmo. Você já fez testes com o componente t:saveState do Myfaces Tomahawk?
Abraços!
April 27th, 2008 at 12:30 pm
Se eu usar o t:saveState ocorre isso:
Variable ‘myBean’ refers to a Spring bean which by definition is not writable.
April 28th, 2008 at 1:07 pm
Rafael Ponte, ótimo artigo. Vou começar outro projeto nesse momento, qual sua opinião com relação a inumeros acessos a uma página com essa estrutura, utilizando rich/ajax? posso colocar isso em produção sem medo? ou tenho que dar um tunning no servidor tb? Valeu e Abraço.
April 28th, 2008 at 8:09 pm
Olá Murilo, o ideal é que você levante metas e requisitos sobre a escalabilidade da tua aplicação, assim fica mais fácil saber a configuração de um servidor decente, se há necessidade de algum tunning no teu servidor ou algo do tipo.
Utilizando-se dessa abordagem você terá uma melhor escalabilidade e performance do que utilizando a maneira convencional, você poderá até melhorar isso com mais algumas configurações e otimizações como por exemplo uma simples paginação sob demanda.
Enfim, como citei no post as vantagens existem, mas não deixe de usar o bom senso em certos momentos.
Abraços.
April 29th, 2008 at 10:17 am
Rafael… me explica esse UIPanel… não consigo rodar com ele .. da que tem uma referencia NULL no panelForm.. qual a funcionalidade??? pq vc usou??? valeu d++
April 30th, 2008 at 10:49 am
cara seguinte!!! to só te encehndo hein .. funcionou mais sem o UIPanel .. e outra ele não altera o datatable… e nao da nenhum erro monitoro pelo firebug a requisição vai mas nao altera nada nem na pesquisa nem na paginação … abração … desculpa o amadorismo kkkk
May 1st, 2008 at 7:47 am
Murilo,
Esse UIPanel é um binding para o panel do formulário, assim você poderá resetar o estado da árvore de componentes sempre que possível, pois como você não muda de página e consequentemente não muda de viewroot o estado da árvore é mantido entre requests, logo é necessário reseta-lo ou simplesmente altera-lo quando necessário.
May 1st, 2008 at 7:48 am
Não altera o datatable em que momento? Não entendi bem o teu problema
May 2nd, 2008 at 5:56 pm
Cara acredite se quiser … o que esta diferente do meu codigo para o seu é só a consulta que eu faço no banco com jpa … mas no IE e no Konqueror funciona mas no firefox não puts kkk já aconteceu com vc???
May 4th, 2008 at 5:57 am
parabens, otimo artigo continue assim rafael. Abraços
May 7th, 2008 at 5:45 am
Olá Rafael, como já disse parabéns pelo artigo.
Eu fiz um projeto semelhante e tentei utilizar internacionalização e não consegui. Onde utilizo o ?
Desde já agradeço a resposta
May 7th, 2008 at 6:05 am
Olá Clériston, não entendi tua pergunta. Mas sobre internacionalização, você consegue com algumas configurações no faces-config.xml e arquivos properties para cada idioma.
May 7th, 2008 at 6:32 am
entao acho o blog nao permitiu eu adicionar uma “tag” na minha pergunta…
Eu queria saber onde coloco o f : loadbundle ??
May 7th, 2008 at 7:18 am
Você está utilizando JSF1.1 ou JSF1.2? Na verdade eu te aconselho fortemente a entrar na lista de discussão JavaSf, http://groups.google.com/group/javasf , lá com certeza você terá mais detalhes sobre a configuração
May 11th, 2008 at 8:41 am
so uma duvida
esta parte do codigo
var infoWindowAMShown = false;
var infoWindowAMTimer;
function showModalInfoWindow()
{
infoWindowAMTimer = setTimeout(”if(!infoWindowAMShown){Richfaces.showModalPanel(’ajaxLoadingModalBox’);infoWindowAMShown=true;}”, 500);
}
function hideModalInfoWindow()
{
if (infoWindowAMShown) {
Richfaces.hideModalPanel(’ajaxLoadingModalBox’);
infoWindowAMShown=false;
} else {
if(infoWindowAMTimer)
clearTimeout(infoWindowAMTimer);
}
}
seria obrigatoria?
poderia me dar uma esclarecida nela
parabens pelo tutorial, sao tutoriais que nem esse que estao faltanto!
abs
T+
May 11th, 2008 at 9:23 am
Olá Krusst, na verdade isso não é obrigatório. Eu somente o coloquei para criar um delay antes de exibir um modalpanel com uma mensagem no estilo “carregando..”. Assim, a mensagem somente irá aparecer para o usuário caso realmente demore. Como foi uma aplicação exemplo e provavelmente será testada localmente, as requisições são muito rápidas, logo fica chato ver a mensagem de “carregando..” aparecendo e sumindo rapidamente no browser.
May 13th, 2008 at 5:12 am
Olá Rafael!
Acho q dá pra fazer um Bean genérico utilizando generics não é?
Pois a única coisa que muda de um bean para o outro é o “Registro atual” (neste exemplo é a variável usuario) e a lista de registros (neste exemplo é a variável usuarios).
Seria uma boa idéia nao é?
May 20th, 2008 at 9:34 am
Oi Rafael,
Ótima matéria mesmo, parabéns.
Estou com um pequeno problema, pois estou usando JSF 1.1 e ele não aceita a linha:
Qual a sua dica para solucionar esse problema?
[]´s
May 21st, 2008 at 1:38 pm
Boa tarde Chará!
Muito bom seu tutorial, porém estou com a seguinte dúvida:
- Como faço para utilizar o estilo do input (Azul bem clarinho com gradiente) baseado no estilo padrão (Skin) do richfaces, conforme imagens exibidas no seu post.
Fico no aguardo de uma resposta…
May 21st, 2008 at 1:43 pm
Esqueci de mencionar também dos estilos dos botões, pois quando executo a aplicação, os botãos não ficam com o background azul bem claro.
Meu ambiente: Eclipse Europa 3.3; Richfaces 3.2; Facelets 1.1.4; e tomahawk (Versão utilizada neste post)
May 21st, 2008 at 1:44 pm
Você poderá ver como eu fiz aqui,
http://livedemo.exadel.com/richfaces-demo/richfaces/standardSkinning.jsf?c=StandardSkinning
Abraços!
May 22nd, 2008 at 6:00 pm
Cara estou com mais uma dúvida.
Criei uma tela de login e estou usando a seguinte tag para validação:
Meu problema é que nesse caso eu preciso que ele vá para outra pagina mesmo.
faces.congig.xml:
/pages/login.xhtml
#{loginHandler.doLogin}/from-action>
sucesso
/pages/usuarioCrud.faces
O problema é que ele valida e fica na mesma página.
Agradeço a ajuda.
June 5th, 2008 at 10:34 am
[...] incrível como depois do post Utilizando AJAX com JSF de maneira eficiente muitos desenvolvedores tem utilizado o exemplo básico do post -que nada mais era do que uma prova [...]
June 28th, 2008 at 12:38 pm
Boa tarde Rafael!
Gostaria de saber onde você declarou os métodos: adicionarState, editarState e pesquisarState, pois não estou encontrando no bean utilizado nesse exemplo.
Fico no aguardo!
June 28th, 2008 at 12:42 pm
Olá Raphael, são os métodos isAdicionarState(), isEditarState() e isPesquisarState(). Métodos que começam com get*, set* e is* estão dentro da especificação JavaBeans.
Abraços!
June 30th, 2008 at 4:58 am
Bom dia Raphael!
Valeu mesmo, o problema foi resolvido!!!
Abraços!
June 30th, 2008 at 11:52 am
[...] Ext4JSF por aí? Além do mais será mais rápido e prático implementar interfaces do tipo “on a single page interface web application“, já que todo o processamento da interface gráfica ficará no lado [...]
July 12th, 2008 at 12:13 pm
[...] as aplicações web estão caminhando para uma GUI mais rica e versátil, e ao abrir mão da “velha escola” conseguimos contornar os problemas citados acima facilmente, como também obter inúmeras [...]
July 16th, 2008 at 5:23 pm
Pefeito, esta sanando muitas duvidas minhas sobre como fazer as coisas!
August 6th, 2008 at 12:25 pm
Olá, nao estou conseguindo usar seu exemplo com JSF 1.1, como vc disse essa versão é somente para 1.2….. mas não há como usar Ajax com JSF 1.1 ????
August 6th, 2008 at 12:28 pm
Sim, é possível utilizar AJAX com JSF1.1, levando em consideração que seu framework ou conjunto de componentes AJAX trabalhe com JSF1.1
Se não me engano, a partir da versão 3.2 do Richfaces ele não suporta mais JSF1.1, logo será necessário trabalhar com uma versão anterior.
Abraços e boa sorte.
August 27th, 2008 at 10:00 am
Envia por favor para meu email os códigos do .xhtml da parte
Pois estou sem saber como configurar algumas tags.
September 9th, 2008 at 6:54 am
é as velhas formas de gerenciamento de formulários voltando ahahha, ou seja, gerencia estado e ativa ou não algo
ai pompom, acho q vc é re-incarnação de algum veio erudita
ahhaha
eh nois
October 16th, 2008 at 5:58 pm
importei sua aplicação de exemplo richfaces ajax4jsf , mas quando rodo o index . jsp ele da erro 4004 dizemdo que não achou o index.faces.
om que pode ta acontecendo?
October 31st, 2008 at 5:01 am
Primeiramente parabéns pelo artigo. Já vi os comentários sobre a utilização consciente da técnica e concordo totalmente, pois como você mesmo citou, o artigo não é uma receita de bolo. rsrsrs…
Por isso gostaria de saber se você tem uma solução que estou buscando há mais ou menos um mês, para que possamos aperfeiçoar a estrutura que você demonstrou.
O problema é o seguinte: Pelo que observei para utilizar-mos tal estrutura, é preferível que a configuração do javax.faces.STATE_SAVING_METHOD esteja como server pois se não deveremos implementar a classe java.io.Serializable em nossos managed`s beans o que não se torna a coisa mais interessante. Então, como com o server a estrutura da árvore de componentes fica no servidor, e não no cliente, quando a sessão do usuário termina por inatividade, por exemplo, se o usuário fizer qualquer requisição ajax, é gerada uma exceção do tipo javax.faces.application.ViewExpiredException que torna a aplicação inativa para qualquer outro cliente. Você sabe como tratar esta exceção? Você já teve algum problema semelhante?
Desde já agradeço sua ajuda e atenção.
November 11th, 2008 at 6:39 am
Parabéns pelo post, estou sentindo dificuldades para rodar a aplicação, pois uso o eclipse 3.4 j2ee e faltam jars para a devida aplicação.
Poderia disponibilizar um arquivo .war ,da aplicação, configurado para o eclipse?