January 27, 2011
Java EE, Programação
11 Comments
Ao se colocar o JSF 2.0 no Weblogic 10.3.0.0, os EJB’s não são injetados nos manageds beans do JSF através da anotação @EJB.
Para corrigir esse problema, basta utilizar a classe abaixo:
import java.lang.reflect.Field;
import java.util.*;
import javax.ejb.EJB;
import javax.el.*;
import javax.naming.NamingException;
import com.sun.faces.el.ManagedBeanELResolver;
public class VariableResolver extends CompositeELResolver {
private final Map, List> ejbFields;
public VariableResolver() {
this.ejbFields = new HashMap, List>();
add(new ManagedBeanELResolver());
}
private void preencherEjbFields(List fields, Class clazz, Set> visitados) {
if (clazz != null && !visitados.contains(clazz)) {
visitados.add(clazz);
for (Field field : clazz.getDeclaredFields()) {
EJB ejb = field.getAnnotation(EJB.class);
if (ejb != null) {
field.setAccessible(true);
fields.add(new EJBField(field, ejb.mappedName(), field.getType()));
}
}
preencherEjbFields(fields, clazz.getSuperclass(), visitados);
for (Class i : clazz.getInterfaces()) {
preencherEjbFields(fields, i, visitados);
}
}
}
private List getEjbFields(Object obj) {
List fields = ejbFields.get(obj.getClass());
if (fields == null) {
fields = new ArrayList();
Set> visitados = new HashSet>();
preencherEjbFields(fields, obj.getClass(), visitados);
synchronized (ejbFields) {
ejbFields.put(obj.getClass(), fields);
}
}
return fields;
}
private void processarEjbs(Object obj) throws IllegalAccessException, ClassCastException, NamingException, IllegalArgumentException {
for (EJBField field : getEjbFields(obj)) {
if (field.getField().get(obj) == null) {
Object ejb = ServiceLocator.lookup(field.getType(), field.getMappedName());
field.getField().set(obj, ejb);
}
}
}
@Override
public Object getValue(ELContext arg0, Object arg1, Object arg2) {
try {
Object obj = super.getValue(arg0, arg1, arg2);
if (obj != null) {
processarEjbs(obj);
}
return obj;
} catch (IllegalArgumentException ex) {
throw new ELException(ex.getMessage(), ex);
} catch (IllegalAccessException ex) {
throw new ELException(ex.getMessage(), ex);
} catch (NamingException ex) {
throw new ELException(ex.getMessage(), ex);
}
}
private class EJBField {
private Field field;
private String mappedName;
private Class type;
public EJBField(Field field, String mappedName, Class type) {
this.field = field;
this.mappedName = mappedName;
this.type = type;
}
public Field getField() {
return field;
}
public String getMappedName() {
return mappedName;
}
public Class getType() {
return type;
}
}
}
E declarar o el-resolver no faces-config.xml:
<faces-config>
<application>
<el-resolver>VariableResolver</el-resolver>
</application>
</faces-config>
January 27, 2011
Java, Java EE, Programação
No Comments
Ao tentar efetuar o deploy de uma aplicação com JPA (implementação: Hibernate), ocorre o seguinte erro:
org.springframework.orm.hibernate3.HibernateQueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken [SELECT p FROM PARAMETRO p WHERE UPPER(RTRIM(p.parametroPK.parametroGeral)) = :parametroGeral AND UPPER(RTRIM(p.parametroPK.codigo)) = :codigo]; nested exception is org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken [SELECT p FROM PARAMETRO p WHERE UPPER(RTRIM(p.parametroPK.parametroGeral)) = :parametroGeral AND UPPER(RTRIM(p.parametroPK.codigo)) = :codigo]
Caused by: org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken [SELECT p FROM PARAMETRO p WHERE UPPER(RTRIM(p.parametroPK.parametroGeral)) = :parametroGeral AND UPPER(RTRIM(p.parametroPK.codigo)) = :codigo]
at org.hibernate.hql.ast.HqlLexer.panic(HqlLexer.java:57)
at antlr.CharScanner.setTokenObjectClass(CharScanner.java:340)
at org.hibernate.hql.ast.HqlLexer.setTokenObjectClass(HqlLexer.java:31)
at antlr.CharScanner.<init>(CharScanner.java:51)
at antlr.CharScanner.<init>(CharScanner.java:60)
at org.hibernate.hql.antlr.HqlBaseLexer.<init>(HqlBaseLexer.java:56)
at org.hibernate.hql.antlr.HqlBaseLexer.<init>(HqlBaseLexer.java:53)
at org.hibernate.hql.antlr.HqlBaseLexer.<init>(HqlBaseLexer.java:50)
at org.hibernate.hql.ast.HqlLexer.<init>(HqlLexer.java:26)
at org.hibernate.hql.ast.HqlParser.getInstance(HqlParser.java:44)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:242)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)
at org.springframework.orm.hibernate3.HibernateTemplate$29.doInHibernate(HibernateTemplate.java:837)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:367)
at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:835)
at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:827)
at db.ProductManagerDaoHB.getProductList(ProductManagerDaoHB.java:14)
at bus.ProductManager.getProducts(ProductManager.java:25)
at web.controllers.SpringappController.handleRequest(SpringappController.java:33)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:819)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:754)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:399)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:354)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:971)
at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:402)
at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:305)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:6350)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:317)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:118)
at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3635)
at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2585)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:197)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:170)
Para resolver este problema basta alterar o persistence.xml e adicionar a seguinte linha:
<property name="hibernate.query.factory_class" value="org.hibernate.hql.classic.ClassicQueryTranslatorFactory"/>
Fonte: http://forum.springsource.org/showthread.php?t=36860
September 23, 2009
Java, Java EE, Programação, Uncategorized
No Comments
Este post foi traduzido e alterado deste link:
http://blog.cherouvim.com/the-stupidest-things-ive-done-in-my-programming-job/
Observação: Não fui eu quem escreveu este post. Apenas fiz a tradução e alteração pois achei muito interessante.
As coisas estúpidas feitas quando se trabalho com programação
- ORM
- Estupidez
Construir um framework próprio de ORM.
- Consequências
O projeto vira uma bagunça depois de 2 anos de manutenção com gambiarras para passar pelo meu framework ORM desenvolvido e chamar comandos SQL’s customizados.
- O que deveria ter sido feito?
Usar hibernate, iBATIS, Cayenne ou outros parecidos.
- EAV
- Estupidez
Usar uma modelagem de banco de dados do tipo Entity-Attribute-Value model.
- Consequências
Solução não escalável e impossibilidade de rodar queries úteis no banco de dados.
- O que deveria ter sido feito?
Usar uma modelagem de banco de dados normalizada.
- Acesso ao Banco de dados
- Estupidez
Sincronizar o acesso ao banco de dados com uma conexão compartilhada.
- Consequências
Escalabilidade zero. Tempos de respostas muito lentos quando mais de 10 usuários estavam utilizando a aplicação.
- O que deveria ter sido feito?
Não fazer isto e utilizar um pool de conexões como c3p0 e usar uma “nova” (reutilizada) conexão retornada do pool para cada ciclo de request / response.
- IDE
- Estupidez
Evitar aprender e utilizar uma IDE.
- Consequências
Falta de habilidade de compilar, testar e fazer o deploy da aplicação rapidamente e / ou geralmente fazer qualquer coisa útil.
- O que deveria ter sido feito?
Familiarizar-me com uma IDE. Ex.: NetBeans, eclipse, etc.
- Transações
- Estupidez
Não usá-las.
- Consequências
Corromper os dados da aplicação.
- O que deveria ter sido feito?
Usar transações do banco de dados. No MySQL usar InnoDB.
- Prepared Statements
- Estupidez
Usar Statements, concatenação de strings e escapar caracteres para montar queries “seguras”.
- Consequências
Possibilidade de SQL Injections na aplicação. É possível logar utilizando por exemplo “or 1=1;delete from users;” e alterar o estado do banco de dados de uma forma muito desagradável.
- O que deveria ter sido feito?
Usar Prepared Statements que montam e escapam corretamente as queries dependendo do driver JDBC utilizado.
- Lógica de Negócios
- Estupidez
Fazer isto nos templates (JSP).
- Consequências
Aplicação de manutenção difícil.
- O que deveria ter sido feito?
Fazer isto utilizando o padrão MVC com servlets ou com um Front Controller. Melhor se utilizar um framework MVC open source como Struts, Spring MVC, etc.
July 21, 2009
Java EE
No Comments
Depois de muito tempo consegui fazer minha aplicação utilizando Freemarker (template engine) + Sitemesh (web page layout framework) + Spring (IOC, etc) funcionar.
Basicamente, basta configurar no web.xml o filtro do Sitemesh (com.opensymphony.sitemesh.webapp.SiteMeshFilter), a servlet do Freemarker que vem com o Sitemesh (com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet) e a servlet do Spring MVC (org.springframework.web.servlet.DispatcherServlet).
O filtro do Sitemesh é aplicado a todas as requisições, a servlet do freemarker às urls *.ftl e a servlet do Spring às urls *.html.
O problema que eu tive foi que os templates do Freemarker e do Sitemesh não eram encontrados. No web.xml, um dos parâmetros iniciais da servlet do Freemarker é o diretório dos templates (TemplatePath). Configurei este parâmetro para “/WEB-INF/templates/”. E no arquivo decorators.xml configurei que os templates do Sitemesh ficavam no diretório “/decorators”. O que acontecia é que o diretório dos templates do Sitemesh deveriam ficar dentro do diretório dos templates do Freemarker. Logo a estrutura de diretórios é dessa maneira: /WEB-INF/templates/decorators.
Segue abaixo o link com a aplicação de exemplo desta integração:
http://www.fnbrandao.com.br/blog/files/freemarker.tar.gz
June 6, 2008
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.
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
5 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>