Olá pessoal, estou tentando utilizar o Spring com o JPA, porém não estou conseguindo fazer a injeção de dependencia do entityManagerFactory, estou urilizando uma aplicação web, será que alguem pode me ajudar?
public class Teste implements Controller{
protected final Log logger = LogFactory.getLog(getClass());
@Override
public ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
ProductDAO productDAO = new ProductDAO();
Product product = new Product();
product.setName("Teste");
productDAO.insert(product);
String now = (new Date()).toString();
logger.info("Returning hello view with " + now);
return new ModelAndView("hello", "now", now);
}
}
O Spring é um framework poderoso. Você realmente precisa injetar o EntityManagerFactory nos seus beans?
Você já ouviu falar no conceito “Open Session/EntityManager in View”?
O Spring pode fazer isso por você: org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
E colocar a Annotation @Transactional nos métodos que dependem de uma transação (se não souber o suficiente sobre transactions no Spring, da uma olhada na net).
@Transactional
public void delete(EntityClass entity) {
entityManager.remove(entity);
}
Outra coisa, existe uma GRANDE diferença entre isso:
Olá Guilherme, estou iniciando no spring agora, então não tenho experiência com este framework, preciso fazer a integração do Spring com JPA, estou me baseando nesta parte da documentação http://static.springframework.org/spring/docs/2.0.x/reference/orm.html e em alguns pequenos tutoriais que vi na net, porem nao vi nenhum exemplo completo e pouca coisa falando de JPA puro com Spring.
Como já te disse tenho pouco conhecimento do Spring, até agora tinha entendido que ele funciona desta maneira, gerenciando as dependências através dos beans, não sabia que teria outra forma além desta.
Não tenho o conhecimento deste conceito, e como devo utilizar além de mapear os filtros no web.xml? Ele vai criar o EntityManagerFactory Automaticamente, vai ser necessários o mesmo mapeamento nos beans?
Quando comecei a estudar Spring fiz exempos utilizando aplicações desktop e utilizei a primiera forma pra fazer as injeções de dependência necessárias, agora que comecei a utilizar a parte web vi que isso é feito de forma diferente.
Tentei implementar mas ocorreu a seguinte exception:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tomcat.util.IntrospectionUtils.callMethod1(IntrospectionUtils.java:922)
at org.apache.tomcat.util.digester.SetNextRule.end(SetNextRule.java:193)
at org.apache.tomcat.util.digester.Rule.end(Rule.java:229)
at org.apache.tomcat.util.digester.Digester.endElement(Digester.java:1140)
....
....
....
Caused by: java.lang.IllegalArgumentException: Filter mapping specifies an unknown filter name inview
at org.apache.catalina.core.StandardContext.addFilterMap(StandardContext.java:2160)
... 37 more
04/05/2009 10:41:08 org.apache.catalina.startup.ContextConfig applicationWebConfig
SEVERE: Parse error in application web.xml file at jndi:/localhost/jpa/WEB-INF/web.xml
java.lang.IllegalArgumentException: Filter mapping specifies an unknown filter name inview
at org.apache.tomcat.util.digester.Digester.createSAXException(Digester.java:2808)
at org.apache.tomcat.util.digester.Digester.createSAXException(Digester.java:2834)
at org.apache.tomcat.util.digester.Digester.endElement(Digester.java:1143)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1774)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2930)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
....
....
....
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
04/05/2009 10:41:08 org.apache.catalina.startup.ContextConfig applicationWebConfig
SEVERE: Occurred at line 31 column 20
Você disse uma coisa muito importante, o Spring faz Injeção de Dependencias. Mas como ele pode fazer uma injeção de dependencia com você fazendo ProductDAO dao = new ProductDAO()?
Você deve chamar o Spring para pegar o DAO.
Usando o web.xml para declarar o XML do Spring, no meu caso é o seguinte:
E nesses XMLs você declara as suas classes e suas dependencias (ou usa as annotations). Assim, quando algum Bean for acessado, a injeção de dependencia será automatica.
Agora, se estiver acessando seus beans via uma servlet você terá um problema, pois servlets são criadas pelo ServletContainer (Tomcat, Jetty, …). O jeito mais facil de acessar um bean via servlet é fazendo o seguinte:
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
ProductDAO dao = (ProductDAO) context.getBean("ProductDAO ");
Existe uma servlet do spring que da forwarding pra sua servlet e todo um esquema que eu num gostei muito e não lembro mais como faz ^^
Se quiser, pode dar uma pesquisada por isso.
Então Guilherme, como estou fazendo apenas um exemplo primeiro, estou usando apenas o arquivo spring-servlet.xml que pelo que eu vi é default, é o que ele vai procurar caso nao seja especificado nenhum no context-param, correto?
Neste arquivo como eu ja postei acima eu declarei a minha DAO e o entityManagerFactory e também estou declarando a minha pagina que vai chamar a minha classe de “controle” onde eu chamo a DAO. É neste ponto que não estou conseguindo fazer a implementação acho que não é desta maneira que devo fazer, não sei se consegui expressar meu problema, mas ai qdo eu chamo a DAO da um NullPointer pois, a injeção não é feita, na minha coloquei as Annotation na DAO @PersistenceUnit no entityManagerFactory e @PersistenceContext em cima da declaração da minha classe, desta maneira qdo eu chama a aplicação como se fosse uma aplicação desktop, pelo método main funciona, mas qdo eu rodo com o Tomcat, pelo server a injeção não é feita.
no meu caso estou utilizando o persistence.xml para configuração do dataSource, mesmo assim eu preciso declarar de novo na configuração do Spring como vc fez? E este property chamado persistenceProvider pra que que serve?
Você não precisa declarar as propriedades no arquivo do spring caso esteja usando o persistence.xml. No meu caso, preferi declarar tudo no spring por uma questão de centralização de informações referentes ao banco.
Mas, mesmo que você utilize o persistence.xml, você precisa declarar a entityManagerFacory como o código que postei.
Quanto ao PersistenceProvider que postei, é uma solução que eu encontrei na internet para conseguir usar o Provider do Hibernate e ainda assim usar um interceptor com ele, injetado pelo Spring, com o provider padrão do hibernate não dá, tem que inserir via propriedades…
Fiz as configurações e alterações, apareceu a seguinte exception:
Será que é algum jar faltando?
SEVERE: Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/jpa-servlet.xml]; nested exception is java.lang.NoSuchMethodError: org.springframework.aop.config.AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(Lorg/springframework/beans/factory/xml/ParserContext;Lorg/w3c/dom/Element;)V
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:420)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:124)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:92)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:123)
...
Caused by: java.lang.NoSuchMethodError: org.springframework.aop.config.AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(Lorg/springframework/beans/factory/xml/ParserContext;Lorg/w3c/dom/Element;)V
at org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser$AopAutoProxyConfigurer.configureAutoProxyCreator(AnnotationDrivenBeanDefinitionParser.java:109)
at org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.parse(AnnotationDrivenBeanDefinitionParser.java:80)
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:69)
...
04/05/2009 14:19:41 org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/jpa-servlet.xml]; nested exception is java.lang.NoSuchMethodError: org.springframework.aop.config.AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(Lorg/springframework/beans/factory/xml/ParserContext;Lorg/w3c/dom/Element;)V
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:420)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:124)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:92)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:123)
...
Caused by: java.lang.NoSuchMethodError: org.springframework.aop.config.AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(Lorg/springframework/beans/factory/xml/ParserContext;Lorg/w3c/dom/Element;)V
at org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser$AopAutoProxyConfigurer.configureAutoProxyCreator(AnnotationDrivenBeanDefinitionParser.java:109)
at org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.parse(AnnotationDrivenBeanDefinitionParser.java:80)
Ele está procurando pelo metodo registerAutoProxyCreatorIfNecessary na classe AopNamespaceUtils, pois alguem esta chamando, mas não existe. Problema de incompatibilidade de versões.
Olá Guilherme consegui resolver a exception que postei e outras que vieram depois… agora ta dando essa que não estou conseguindo entender, parece que estou injetando o entityManagerFacoty no EntityManager, mas acho que não estou fazendo isso eu fiz o código da maneira que vc postou.
EVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManagerFactory] is incompatible with resource type [javax.persistence.EntityManager]
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.checkResourceType(InjectionMetadata.java:159)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.<init>(PersistenceAnnotationBeanPostProcessor.java:560)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$1.doWith(PersistenceAnnotationBeanPostProcessor.java:359)
at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:523)
at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:500)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:351)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:296)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:745)
código da DAO
public class ProductDAO {
private EntityManager _entityManager = null;
@PersistenceContext
private EntityManagerFactory _entityManagerFactory = null;
public ProductDAO() {
}
@Transactional
public void insert(Product product) {
_entityManager = _entityManagerFactory.createEntityManager();
_entityManager.getTransaction().begin();
_entityManager.persist(product);
_entityManager.getTransaction().commit();
}
// getters and setters
A annotation PersistenceContext vai no EntityManager e o próprio Spring injeta um EntityManager para você, esse é o erro. Ele está tentando injetar um entitymanager em um entitymanagerfactory.
pois agora aquele erro acabou mas tanto entityManager como o EntityManagerFactory estão dando NullPointerException
java.lang.NullPointerException
at orm.dataaccess.dao.ProductDAO.insert(ProductDAO.java:28)
at orm.controller.Teste.handleRequest(Teste.java:34)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
é tirei, mas o NullPointer continua, parece que ele nao fez a injeção.
SEVERE: Servlet.service() for servlet jpa threw exception
java.lang.NullPointerException
at orm.dataaccess.dao.ProductDAO.insert(ProductDAO.java:24)
at orm.controller.Teste.handleRequest(Teste.java:34)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
ProductDAO
public class ProductDAO {
@PersistenceContext
private EntityManager _entityManager = null;
public ProductDAO() {
}
@Transactional
public void insert(Product product) {
_entityManager.getTransaction().begin();
_entityManager.persist(product);
_entityManager.getTransaction().commit();
}
public EntityManager getEntityManager() {
return _entityManager;
}
public void setEntityManager(EntityManager entityManager) {
_entityManager = entityManager;
}
Creio que o problema seja que você chamou seu EntityManager de _entityManager, então ele procura o setter set_entityManager() ou algo do tipo, tente mudar o nome da variavel apenas para entityManager e ele vai procurar pelo setEntityManager().
Eu configurei no eclipse que todos os atributos teriam underline, entao acho que quando ele encontra os metodos getters ou setters ele o desconsidera. Porém tirei pra ver e mesmo assim nao foi injetado. Ta bem complicado