PostBack no JSF

Java EE, Programação 2 Comments

Um grande problema com o JSF é que na especificação 1.1 não existe algum método para saber se a página está sendo executada no postback (quando você reenvia os dados para ela mesma). Mas existe o seguinte workaround:

package web.jsf.vh;

import java.io.IOException;
import java.util.Locale;
import java.util.Map;

import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;

public class PostBackViewHandler extends ViewHandler {

  protected ViewHandler baseViewHandler;

  public CustomViewHandler(ViewHandler viewHandler) {
    super();
    this.baseViewHandler = viewHandler;
  }

  public Locale calculateLocale(FacesContext facesContext) {
    return baseViewHandler.calculateLocale(facesContext);
  }

  public String calculateRenderKitId(FacesContext facesContext) {
    return baseViewHandler.calculateRenderKitId(facesContext);
  }

  public UIViewRoot createView(FacesContext facesContext, String arg1) {
    setPostback(facesContext, false);
    return baseViewHandler.createView(facesContext, arg1);
  }

  public String getActionURL(FacesContext facesContext, String arg1) {
    return baseViewHandler.getActionURL(facesContext, arg1);
  }

  public String getResourceURL(FacesContext facesContext, String arg1) {
    return baseViewHandler.getResourceURL(facesContext, arg1);
  }

  public void renderView(FacesContext facesContext, UIViewRoot arg1) throws IOException, FacesException {
    baseViewHandler.renderView(facesContext, arg1);
    
  }

  public UIViewRoot restoreView(FacesContext facesContext, String arg1) {
    setPostback(facesContext, true);
    return baseViewHandler.restoreView(facesContext, arg1);
  }

  public void writeState(FacesContext facesContext) throws IOException {
    baseViewHandler.writeState(facesContext);
  }
  
  public Map getRequestScope(FacesContext facesContext) {
    return (Map)facesContext.getApplication().createValueBinding(“#{requestScope}”).getValue(facesContext);
  }
  
  public void setPostback(FacesContext facesContext, boolean value) {
    getRequestScope(facesContext).put(“ispostback”, new Boolean(value));
  }

}

O código acima é um View Handler do JSF, agora basta registrá-lo no “facesconfig.xml”:

<application>
   <view-handler>web.jsf.vh.PostBackViewHandler</view-handler>
</application>

E para saber em sua página se é um postback:

public boolean isPostback() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    Map requestScope = (Map)facesContext.getApplication().createValueBinding(“#{requestScope}”).getValue(facesContext);
    boolean ispostback = ((Boolean)requestScope.get(“ispostback”)).booleanValue();
    return ispostback;
}

Obs.: Esse workaround só funciona se o estado da view não é salva no servidor.

JSF – Duplicate componentID

Java EE, Programação 4 Comments

Utilizando o DataTable do RichFaces em uma simples página, após um reload na página sempre era retornado o seguinte erro:

Duplicate component ID '_id0:_dataTable:_id1' found in view.

Segue abaixo o código da página que causava o erro:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
	xmlns:rich="http://richfaces.ajax4jsf.org/rich">

	<h:form binding="#{UserConsultPage.component}">
		<rich:dataTable id="dataTable"
			binding="#{UserConsultPage.dataTable}" var="item">
			<rich:column>
				<f:facet name="header">
					<h:outputText value="Name" />
				</f:facet>
				<h:outputText value="#{item.name}" />
			</rich:column>
			<rich:column>
				<f:facet name="header">
					<h:outputText value="Email" />
				</f:facet>
				<h:outputText value="#{item.email}" />
			</rich:column>
		</rich:dataTable>

		<h:commandButton id="btnLoad" actionListener="#{UserConsultPage.load}" />
	</h:form>

</ui:composition>

A solução foi colocar id’s em todos os componentes “outputText”. Segue abaixo a página modificada:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
	xmlns:rich="http://richfaces.ajax4jsf.org/rich">

	<h:form binding="#{UserConsultPage.component}">
		<rich:dataTable id="dataTable"
			binding="#{UserConsultPage.dataTable}" var="item">
			<rich:column>
				<f:facet name="header">
					<h:outputText id="headerNameValue" value="Name" />
				</f:facet>
				<h:outputText id="nameValue" value="#{item.name}" />
			</rich:column>
			<rich:column>
				<f:facet name="header">
					<h:outputText id="headerEmailValue" value="Email" />
				</f:facet>
				<h:outputText id="emailValue" value="#{item.email}" />
			</rich:column>
		</rich:dataTable>

		<h:commandButton id="btnLoad" actionListener="#{UserConsultPage.load}" />
	</h:form>

</ui:composition>