June 6, 2008
Java EE, Programação
No 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.
May 23, 2008
Java EE, Programação
No 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>
May 21, 2008
Java EE, Programação
1 Comment
Ao tentar fazer o deploy de uma aplicação utilizando JSF, Spring e JPA (com implementação do hibernate) é recebida a seguinte exception:
javax.persistence.PersistenceException: org.hibernate.SessionException: Session is closed!
Para resolver este problema, basta apenas adicionar o seguinte filtro no “web.xml”:
<filter>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
May 14, 2008
Java EE, Programação
No Comments
Para rodar um debug remoto no tomcat 5.5 no Ubuntu, basta editar o arquivo “/etc/init.d/tomcat5.5″ e colocar a seguinte linha:
-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
antes das linhas:
# Define other required variables
CATALINA_PID="/var/run/$NAME.pid"
BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap
JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar"
May 13, 2008
Java EE, Programação
No Comments
O botão back do navegador é muito útil ao usuário para ele conseguir navegar entre diferentes páginas e websites. Entretanto, o botão back pode trazer diversos problemas aos sites. Uma maneira de “travar” o botão é desabilitar completamente o cache das páginas que não devem permitir que sejam acessadas através do botão back.
Para se fazer isso no Java EE basta apenas criar um filtro e mapeá-lo para as url’s necessárias.
Segue abaixo o código do filtro:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
public class ClearCacheFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Expires", "Sat, 1 Jan 1990 12:00:00 GMT");
httpResponse.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
httpResponse.addHeader("Cache-Control", "post-check=0, pre-check=0");
httpResponse.setHeader("Pragma", "no-cache");
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}
Basicamente o que o filtro faz é setar as diretivas de cache para o navegador. Primeiro ele seta a data de expiração da página para uma data passada. Depois, o código seta 3 diretivas para desabilitar o cache:
- no-store: não armazena o conteúdo no cache
- no-cache: o browser deve enviar o request para o servidor mesmo se ele possuir uma cópia do que será enviado
- must-revalidate: revalida o cache em outro request, se estiver expirado
Depois, são setadas duas diretivas específicas do Internet Explorer. Estas diretivas indicam que o conteúdo sempre deve ser atualizado. E por último, é desabilitado o cache para o protocolo HTTP/1.0 (já que as outras 3 são específicas do HTTP/1.1).
Por último é preciso configurar o filtro na aplicação web. Segue abaixo o trecho de código referente à configuração para o filtro, bem como para ele ser aplicado a todas as páginas da aplicação:
<filter>
<filter-name>ClearCacheFilter</filter-name>
<filter-class>br.com.uol.ps.common.web.ClearCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ClearCacheFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>