JSF - Depurando o Ciclo de Vida

JSF (Java Server Faces) é um poderoso framework para desenvolvimento de aplicações Web em Java, veio com o intuito de substituir a “velha” interface em JSP por uma mais moderna e de fácil utilização, assim o desenvolvedor não precisa se preocupar com códigos HTML, layout, entre outros aspectos que fogem do real objetivo da aplicação.
Para se utilizar o JSF é necessário o entendimento do seu ciclo de vida, assim o desenvolvedor poderá ter noção do que acontece de forma transparente porém muito importante.
JSF possui 6 ciclos, são eles:
  • Restore View
  • Apply Request View
  • Process Validations
  • Update Model Values
  • Invoke Application
  • Render Response
Explicaremos cada fase através de exemplos práticos do JSF, mas antes precisaremos configurar o Listener que será responsável por monitorar essa mudança de estados doJSF, para isso implementaremos uma interface chamada PhaseListener. Veja na listagem 1 como ficará nossa interface.
Listagem 1: Implementando a Interface PhaseListener
package br.com.debugjsf.listener;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
ner; public class LifeCycleListener im
import javax.faces.event.PhaseList eplements PhaseListener { public PhaseId getPhaseId() {
forePhase(PhaseEvent event) {
return PhaseId.ANY_PHASE; } public void b e System.out.println("INICIANDO FASE: " + event.getPhaseId()); }
("FINALIZANDO FASE: " + event.getPhaseId());
public void afterPhase(PhaseEvent event) { System.out.printl n }
}
Vamos a explicação do código acima: Criamos uma classe que implementa o PhaseListener, nesta temos os seguintes métodos:
  • getPhaseId(): Apenas retorna um PhaseId que pode ser um daqueles 6 que citamos logo no inicio (1 - Restore View, 2 - Apply Request View, 3 - Process Validations, 4 - Update Model Values, 5 - Invoke Application e 6 - Render Response).
  • beforePhase(): Antes de uma determinada fase iniciar este método é chamado.
  • afterPhase(): Depois de uma determinada fase terminar este método é chamado.
Após termos nosso PhaseListener implementado, vamos configurar o nosso arquivo faces-config.xml para dizer a nossa aplicação quem será o nosso Listener, ou seja, apontar qual será a classe responsável por escutar as mudanças de fase do JSF. Veja na listagem 2 como ficou a configuração do nosso faces-config.xml.
Listagem 2: Configurando faces-config.xml
<lifecycle>
<phase-listener>br.com.debugjsf.listener.LifeCycleListener</phase-listener>
</lifecycle>
Temos enfim nossa aplicação configurada para escutar todas as fases do JSF, partiremos agora para os exemplos em cada fase. A saída de ciclo completo do JSF no console deve ser algo parecido com a listagem 3.
Listagem 3: Saída no console de um ciclo completo JSF
INICIANDO FASE: RESTORE_VIEW 1
FINALIZANDO FASE: RESTORE_VIEW 1
INICIANDO FASE: APPLY_REQUEST_VALUES 2
FINALIZANDO FASE: APPLY_REQUEST_VALUES 2
INICIANDO FASE: PROCESS_VALIDATIONS 3
3 INICIANDO FASE: UPDATE_MODEL_VALUES 4
FINALIZANDO FASE: PROCESS_VALIDATIONS FINALIZANDO FASE: UPDATE_MODEL_VALUES 4
LIZANDO FASE: INVOKE_APPLICATION 5 I
INICIANDO FASE: INVOKE_APPLICATION 5 FIN ANICIANDO FASE: RENDER_RESPONSE 6
6
FINALIZANDO FASE: RENDER_RESPONS E

Configurando a aplicação de exemplo no JSF

Vamos primeiramente configurar nossa página XHTML, que usaremos para realizar a depuração.
Listagem 4: teste.xhtml
<h:form>
<h:inputText
binding="#{myBean.inputComponent}"
value="#{myBean.inputValue}"
.inputChanged}"> <f:converter converterId="my
valueChangeListener="#{myBea nConverter" /> <f:validator validatorId="myValidator" /> </h:inputText>
<h:outputText
<h:commandButton value="submit" action="#{myBean.action}" /> binding="#{myBean.outputComponent}" value="#{myBean.outputValue}" /> <h:messages />
</h:form>
Vamos as explicações:
  • input text: Este componente está realizando um binding com a propriedade inputComponent do nosso ManagedBean, seu valor é armazenado na propriedade inputValue do ManagedBean, temos ainda um listener associado a ele (inputChanged) que escuta toda vez que alguma alteração é realizada no valor deste campo. Para finalizar este componente, temos ainda um conversor e um validador associados ao mesmo.
  • commandButton: O nosso commandButton dispensa explicações, ele apenas aciona um action em nosso ManagedBean.
  • outputText: Por fim, este componente que é apenas um “label” possui um binding também em nosso ManagedBean e um atributo associado ao seu valor.
Vamos agora ver como será nosso ManagedBean.
Listagem 5: MyBean.java
package br.com.debugjsf.mb;
import javax.faces.component.html.HtmlInputText;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.event.ValueChangeEvent;
ra Binding privat
public class MyBean { //Componentes p ae HtmlInputText inputComponent;
tComponent; //Armazena valores dos com
private HtmlOutputText outp uponentes private String inputValue; private String outputValue;
action() { o
public MyBean() { log("constructed"); } public voi dutputValue = inputValue; log("succes"); }
og(inputComponent); return inputCompon
public HtmlInputText getInputComponent() { lent; } public String getInputValue() { log(inputValue); return inputValue;
output
} public HtmlOutputText getOutputComponent() { log(outputComponent); return Component; } public String getOutputValue() { log(outputValue);
inputComponent) {
return outputValue; } public void setInputComponent(HtmlInputTex tlog(inputComponent); this.inputComponent = inputComponent; }
this.inputValue = inputValue; }
public void setInputValue(String inputValue) { log(inputValue) ; public void setOutputComponent(HtmlOutputText outputComponent) { log(outputComponent);
s do inputText e escreve no console quando houve
this.outputComponent = outputComponent; } //Escuta por alteraçõ er public void inputChanged(ValueChangeEvent event) { log(event.getOldValue() + " to " + event.getNewValue()); }
dName = Thread.currentThread().getStackTrace()[2].getMethodName();
//Escreve um LOG no console, para acompanharmos o ciclo de vida private void log(Object object) { String meth o System.out.println("MyBean " + methodName + ": " + object); }
}
E no nosso faces-config.xml configuraremos o ManagedBean assim como na listagem abaixo.
Listagem 6: Configurando faces-config.xml para o ManagedBean
<converter>
<converter-id>myConverter</converter-id>
<converter-class>br.com.debugjsf.util.MyConverter</converter-class>
</converter> <validator> <validator-id>myValidator</validator-id>
> </validator> <managed-bean> <managed-bean-name>myBean</managed-be
<validator-class>br.com.debugjsf.util.MyValidator</validator-clas san-name> <managed-bean-class>br.com.debugjsf.mb.MyBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Vamos recapitular o que temos até agora:
  • Configuramos o nosso PhaseListener para escutar as alterações de fase do JSF
  • Criamos uma aplicação exemplo para testar nosso PhaseListener, onde essa aplicação é composta por: 1 view (teste.xhtml), 1 ManagedBean (MyBean.java), 1 Converter e 1 Validator. Então vamos agorar criar nosso Converter e nosso Validator.
Listagem 7: Criando o Converter da nossa aplicação
package br.com.debugjsf.util;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
blic class MyConverter implements Conv
import javax.faces.convert.Converter; p uerter {
c Object getAsObject(FacesContext context, UIComponent component, String value) {
publ iSystem.out.println("MyConverter getAsObject: " + value); return value; }
{ System.out.println("MyConverter getAsString: " + value); return (Strin
public String getAsString(FacesContext context, UIComponent component, Object value )g) value; }
}
Listagem 8: Criando o Validator da nossa aplicação
package br.com.debugjsf.util;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
mport javax.faces.validator.ValidatorExc
import javax.faces.validator.Validator; ieption; public class MyValidator implements Validator {
component, Object value) throws ValidatorException { System.o
public void validate(FacesContext context, UIComponent ut.println("MyValidator validate: " + value); } }
Enfim temos nossa aplicação totalmente criada e configurada para escutar as fases do JSF, é óbvio que você pode adaptar o PhaseListener para sua aplicação, colocamos esta apenas para exemplificar o uso deste.

Conclusão

Enfim, o objetivo deste artigo não é explicar com detalhes o ciclo de vida do JSF, e sim configurar um depurador para acompanhar na prática o ciclo de vida deste framework, pois melhor que a teoria, é a prática. Tendo o conhecimento básico de cada ciclo de vida e acompanhando este depurador, você conseguirá ter uma visão melhor de como funciona tal mecanismo e verá a teoria se aplicando na prática.
Isso porque muitos desenvolvedores sentem dificuldade de “ver” como funciona o ciclo de vida do JSF, pois este é totalmente transparente ao desenvolvedor.

SHARE ON:

Hello guys, I'm Tien Tran, a freelance web designer and Wordpress nerd. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae.

    Blogger Comment

0 comentários :

Postar um comentário

Observação: somente um membro deste blog pode postar um comentário.