Bom dia, galera.
Estou fazendo um estudo com JSF 2.2, TomCat 7 e Weld 2.0
Na parte do weld, já foi criado o arquivo beans.xml e alterado o web.xml;
Da a seguinte exceção:
WARNING: #{cidadeBean.grava}: java.lang.NullPointerException
javax.faces.FacesException: #{cidadeBean.grava}: java.lang.NullPointerException
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:117)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:786)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1251)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.el.EvaluationException: java.lang.NullPointerException
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:101)
... 23 more
Caused by: java.lang.NullPointerException
at br.com.protech.officeManager.dao.DAO.adiciona(DAO.java:37)
at br.com.protech.officeManager.mb.CidadeBean.grava(CidadeBean.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.el.parser.AstValue.invoke(AstValue.java:278)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
... 24 more
Abaixo estão os Arquivos
public class JPAUtil {
private static EntityManagerFactory emf = Persistence
.createEntityManagerFactory("tributoProduto");
@Produces
@RequestScoped
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void close(@Disposes EntityManager em) {
em.close();
}
}
public class DAO<T> implements Serializable {
private static final long serialVersionUID = 1L;
private final Class<T> classe;
public DAO(Class<T> classe) {
this.classe = classe;
}
@Inject
private EntityManager em;
public void adiciona(T t) {
em.getTransaction().begin();
em.persist(t);
em.getTransaction().commit();
}
//restante do codigo
}
@Named
@ViewScoped
public class CidadeBean implements Serializable {
private Cidade cidade = new Cidade();
private LazyDataModel<Cidade> lista;
public void grava() {
DAO<Cidade> dao = new DAO<Cidade>(Cidade.class);
if (this.cidade.getId() != null)
dao.atualiza(this.cidade);
else
dao.adiciona(this.cidade);
this.cidade = new Cidade();
}
//Restante de codigo
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:composition template="/_template.xhtml">
<ui:define name="corpo">
<h:form id="cadastro">
<p:panel header="Cadastro">
<h:messages styleClass="erros" />
<h2>
<h:outputText value="Editando ICMS"
rendered="#{not empty cidadeBean.cidade.id}" />
<h:outputText vralue="Cadastrando ICMS"
rendered="#{empty cidadeBean.cidade.id}" />
</h2>
<h:outputLabel value="Cidade:" for="cidade" />
<h:inputText id="cidade" value="#{cidadeBean.cidade.cidade}"
required="true" />
<h:outputLabel value="Estado:" for="uf" />
<h:inputText id="uf" value="#{cidadeBean.cidade.uf}" required="true"
size="100" />
<p:commandButton value="Gravar" action="#{cidadeBean.grava}"
update=":cadastro " />
<p:commandButton value="Cancelar"
action="#{cidadeBean.limpaFormulario}" immediate="true"
update=":cadastro " />
</p:panel>
</h:form>
</ui:define>
</ui:composition>
</html>
Obrigado pela ajuda…
Não sei direito, mas Tomcat 7 não suporta a especificação CDI, suporta?
Lendo sobre, cheguei aqui, onde há uma resposta mais adequada para o que você está tentando fazer. O sujeito cita o Apache TomEE (pronuncie Tommy).
Talvez te ajude.
Posta o seu web.xml para ver se as configurações JNDI estão OK e dá uma olhada em como o Sergio Lopes exemplificou o ciclo de vida do CDI com JPA, ficou muito bom,
link http://blog.caelum.com.br/use-cdi-no-seu-proximo-projeto-java/ .
Pq você não injeta Cidade também ?
Suporta sim, mas é necessário fazer uma configuração em um arquivo context.xml, porque tanto o Tomcat quanto o Jetty trabalham de forma READ-ONLY com JNDI.
Muito Obrigado pelas respostas.
segue meu web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>OfficeManager</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
<resource-env-ref>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>
javax.enterprise.inject.spi.BeanManager
</resource-env-ref-type>
</resource-env-ref>
</web-app>
Segue o contexto.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Manager pathname=""/> <!-- disables storage of sessions across restarts -->
<Resource name="BeanManager"
auth="Container"
type="javax.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory"/>
</Context>
Quando resolver esse problema irei injetar a classe Cidade, e eu segui esse mesmo artigo da caelum, mesmo assim não deu certo.
@Named
@ViewScoped
public class CidadeBean implements Serializable {
private Cidade cidade = new Cidade();
private LazyDataModel<Cidade> lista;
public void grava() {
DAO<Cidade> dao = new DAO<Cidade>(Cidade.class); // se vc esta usando cdi vc não deve dar new
if (this.cidade.getId() != null)
dao.atualiza(this.cidade);
else
dao.adiciona(this.cidade);
this.cidade = new Cidade();
}
//Restante de codigo
}
se vc der new no seu DAO o cdi não vai injetar o entityManager
e consequentimente vc tomara um nullpointer
tenta assim
@Named
@ViewScoped
public class CidadeBean implements Serializable {
private Cidade cidade = new Cidade();
@Inject
private DAO<Cidade> dao ;
private LazyDataModel<Cidade> lista;
public void grava() {
if (this.cidade.getId() != null)
dao.atualiza(this.cidade);
else
dao.adiciona(this.cidade);
this.cidade = new Cidade();
}
//Restante de codigo
}
e crie tambem essa classe
import java.lang.reflect.ParameterizedType;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;
import javax.persistence.EntityManager;
public class DAOFactory {
@Inject
private EntityManager em;
public DAOFactory() {
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Produces @Dependent
public DAO create(final InjectionPoint injectionPoint){
ParameterizedType parameterizedType = (ParameterizedType) injectionPoint.getType();
Class classe = (Class) parameterizedType.getActualTypeArguments()[0];
return new DAO(classe, em);
}
}
[quote=ivandasilva]Posta o seu web.xml para ver se as configurações JNDI estão OK e dá uma olhada em como o Sergio Lopes exemplificou o ciclo de vida do CDI com JPA, ficou muito bom,
link http://blog.caelum.com.br/use-cdi-no-seu-proximo-projeto-java/ .
Pq você não injeta Cidade também ?[/quote]
não vejo necessidade alguma em se injetar a Classe Cidade.
[quote=DaniloAndrade][quote=ivandasilva]Posta o seu web.xml para ver se as configurações JNDI estão OK e dá uma olhada em como o Sergio Lopes exemplificou o ciclo de vida do CDI com JPA, ficou muito bom,
link http://blog.caelum.com.br/use-cdi-no-seu-proximo-projeto-java/ .
Pq você não injeta Cidade também ?[/quote]
não vejo necessidade alguma em se injetar a Classe Cidade.[/quote]
DaniloAndrade, porque você não vê ?
Fiz as Alterações de acordo com o DaniloAndrade e agora apareceu as seguintes exceções, pelo que pesquisei o DAOFactory era pra não aparecer essa exceção
Em qual pasta você colocou o beans.xml ?
Em um projeto web o correto é em WEB-INF, mas, comigo já ocorreu este mesmo erro em um projeto web, então eu coloquei dentro do META-INF e funcionou Ok.
Eu Coloquei no META-INF, mais coloquei no WEB-INF pra fazer um teste
tira o @RequestScoped do metodo dessa classe pra teste
public class JPAUtil {
private static EntityManagerFactory emf = Persistence
.createEntityManagerFactory("tributoProduto");
@Produces
//@RequestScoped //tire o requestscoped
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void close(@Disposes EntityManager em) {
em.close();
}
}
e vê se muda a mensagem
tirei o @RequestScoped e nada…
vou colocar as libs, só pra desencargo
o seu EntityManagerFactory está static ainda ?
se estiver, põe um @Producer… e de quebra põe ele com o @ApplicationScoped para ser criado uma só vez
private EntityManagerFactory emf;
@Produces @ApplicationScoped
public void createEMF(EntityManagerFactory emf){
this.emf = emf
}
e você pode também adicionar um @Dispose para fechar automágicamente a sua fábrica
public void createEMF(@Dispose EntityManagerFactory emf){
emf.close();
}
velhinho faz o seguinte
vc disse que esta usando a versão 2.0 do weld
troca pra versão 1.1 final
a versão 2.0 é um beta ainda
Voltei pro Weld 1.1, mais voltou o erro inicial do nullPointer.
Era pra ser tão difícil assim?
não era não,
coloca o log do erro atual e o codigo das classes apos as alterações
ok, valeu Danilo, você está me ajudando muito.
public class JPAUtil {
private static EntityManagerFactory emf = Persistence
.createEntityManagerFactory("tributoProduto");
@Produces
@RequestScoped
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void close(@Disposes EntityManager em) {
em.close();
}
}
public class DAO<T> implements Serializable {
private static final long serialVersionUID = 1L;
private final Class<T> classe;
public DAO(Class<T> classe) {
this.classe = classe;
}
@Inject
private EntityManager em;
public void adiciona(T t) {
em.getTransaction().begin();
em.persist(t);
em.getTransaction().commit();
}
}
public class DAOFactory {
@Inject
private EntityManager em;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Produces
@Dependent
public DAO create(final InjectionPoint injectionPoint) {
ParameterizedType parameterizedType = (ParameterizedType) injectionPoint
.getType();
Class classe = (Class) parameterizedType.getActualTypeArguments()[0];
return new DAO(classe);
}
}
Acabei de notar que esse bean, no método getulista(), passa um DAO pra outra Classe;
@Named
@ViewScoped
public class CidadeBean implements Serializable {
@Inject
private Cidade cidade;
@Inject
private DAO<Cidade> dao;
private LazyDataModel<Cidade> lista;
public void grava() {
if (this.cidade.getId() != null)
dao.atualiza(this.cidade);
else
dao.adiciona(this.cidade);
this.cidade = new Cidade();
}
public LazyDataModel<Cidade> getLista() {
if (lista == null) {
lista = new DataModel<Cidade>(dao);
}
return lista;
}
public class DataModel<T> extends LazyDataModel<T> {
private static final long serialVersionUID = 1L;
private List<T> lista;
private DAO<T> dao;
public DataModel(DAO<T> dao) {
this.dao = dao;
}
//Restante da Classe
}
cria um novo construtor aqui no DAO que vai receber a Classe e o EntityManager
public class DAO<T> implements Serializable {
private static final long serialVersionUID = 1L;
private final Class<T> classe;
public DAO(Class<T> classe, EntityManager em) { // construtor com o entitymanager
this.classe = classe;
this.em = em;
}
@Inject // pode tirar o inject daqui ele não sera mais necessario
private EntityManager em;
public void adiciona(T t) {
em.getTransaction().begin();
em.persist(t);
em.getTransaction().commit();
}
}
na fabrica usa o novo construtor
public class DAOFactory {
@Inject
private EntityManager em;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Produces
@Dependent
public DAO create(final InjectionPoint injectionPoint) {
ParameterizedType parameterizedType = (ParameterizedType) injectionPoint
.getType();
Class classe = (Class) parameterizedType.getActualTypeArguments()[0];
return new DAO(classe, em);
}
}
lembra o que eu falei antes, quando vc da new o conteiner não vai injetar as dependências que a classe venha precisar por isso vc deve passar pra classe essa dependência
se agente parar pra analisar vamos perceber que o cdi não tem como construir a classe DAO sozinha porque ele vai depender de onde vai ser injetada por isso criamos a fabrica
mas não adianta vc construir o dao passando a classe não passar o entitymanager tambem por que como estamos dando new no dao o cdi não vai injetar o entitymanager
Agora que eu entendi, funcionou Certinho…
Muito Obrigado pela ajuda de todos em especial o DaniloAndrade.
Abraços!