Spring e JPA

Olá!!

Estou tentando fazer o spring fazer a criação do EntityManagerFactory pra mim… só que tá dando erro, dizendo que não foi instanciada a classe TipoService, ou seja, nullPointer exception. vejam o código:

O meu applicationContext: (coloquei ele no WEB-INF é lá que tem que colocar?)


  <bean
        class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="tipoService" class="service.TipoServiceImpl" />

	<bean id="entityManagerFactory"

        class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">

        <property name="persistenceUnitName"

               value="persistencia" />

	</bean>

    <bean id="transactionManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

o meu action que usa o serviço:

private List<Tipo> tipos;
	
	private String tipo;
	
	private TipoService tipoService;
	
	public String execute() throws Exception {
		tipos = tipoService.findAll();
        return SUCCESS;
    }

	public List<Tipo> getTipos() {
		return tipos;
	}

o serviço:

private EntityManager em;

    @PersistenceContext(name="persistencia")
    public void setEntityManager(EntityManager em) {
        this.em = em;
    }

    @SuppressWarnings("unchecked")
    public List<Tipo> findAll() {
        Query query = getEntityManager().createQuery("select p FROM Person p");
        return query.getResultList();
    }

o persistence.xml

<persistence-unit name="persistencia" transaction-type="RESOURCE_LOCAL">
   	  <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="create"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
        <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
        <property name="hibernate.connection.url" value="jdbc:mysql://localhost/DataSource" />
        <property name="hibernate.connection.username" value="root" />
        <property name="hibernate.connection.password" value="senha" />
      </properties>
   </persistence-unit>

Como eu faço pra usar o spring com jpa???

valeu!!

Tenho um tutorialzinho pra baixar aki, qualquer duvida é so postar!

Comecei à fazer esse tutorial e implementei usando o seguinte no applicationContext:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    <bean
        class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean>
		<jee:jndi-lookup id="entityManagerFactory"
			jndi-name="persistence/persistencia"/>
	</bean>

    <bean id="transactionManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <bean id="tipoService" class="service.TipoServiceImpl" />
</beans>

a implementação da service ficou assim:

~@Transactional
public class TipoServiceImpl implements TipoService {

    @PersistenceContext
	private EntityManager em;

    public void setEntityManager(EntityManager em) {
        this.em = em;
    }

    @SuppressWarnings("unchecked")
    public List<Tipo> findAll() {
        Query query = getEntityManager().createQuery("select p FROM Person p");
        return query.getResultList();
    }
}

aí na action eu simplesmente chamei a service e tentei usar… mas dá nullPointer Exception… como se nem tivesse achado o applicationContext, será que o arquivo está no lugar errado? coloquei no WEB-INF junto com o web.xml… falta alguma coisa? o que tá de errado pra dar nullPointer Exception?

public class loginAction extends ActionSupport {

	private List<Tipo> tipos;
	
	private String tipo;

	private TipoService tipoService;
	
	public String execute() throws Exception {
		tipos = tipoService.findAll();
        return SUCCESS;
    }
}

será que falta alguma coisa no web.xml? eu não acrescentei nada lá pro spring… precisa?

Em que parte do código está dando NullPointerException?

Como está o seu web.xml? No web.xml vc deve informar o Listener que inicia o ApplicationContext do Spring.

     &lt;listener&gt;  
         &lt;listener-class&gt;  
             org.springframework.web.context.ContextLoaderListener  
         &lt;/listener-class&gt;  
     &lt;/listener&gt;  
   
     &lt;listener&gt;  
         &lt;listener-class&gt;  
             org.springframework.web.context.request.RequestContextListener  
         &lt;/listener-class&gt;  
     &lt;/listener&gt;  

Também no contexto-param vc pode indicar quais serão os seus arquivos xml que vc irá usar para configuração dos beans, por convenção é usado o nome do seu servlet + -servlet precindido de -sevlet:

   &lt;context-param&gt;  
         &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;  
         &lt;param-value&gt;  
             /WEB-INF/spring-config.xml, /WEB-INF/spring-security.xml, /WEB-INF/spring-core.xml  
         &lt;/param-value&gt;  
     &lt;/context-param&gt;  

Sobre os listeners eu entendi, parece que foi encontrado o applicationContext.xml e deu um outro erro:

SEVERE: Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unnamed bean definition specifies neither 'class' nor 'parent' nor 'factory-bean' - can't generate bean name
Offending resource: ServletContext resource [/WEB-INF/applicationContext.xml]

Mas sobre configuração de beans, eu não entendi pra que serve, e nem como faz! Pode me explicar?!!

valeu!

qdo eu digo arquivo para configuração dos beans eu extou falando no arquivo applicationContext msm, mas por default e pra melhor organização, ao em vez de usar o applicationContext.xml mude o nome para xxx-servlet.xml, no seu web.xml configure o servlet do Spring, e no seu arquivo xxx-servlet.xml mude para nomeDoServlet-servlet.xml, este é o arquivo default, caso vc queira criar outros arquivos é só vc declarar no ContextConfigLocation :

  &lt;servlet&gt;
  	&lt;servlet-name&gt;nomeDoServlet&lt;/servlet-name&gt; 
  	&lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt; 
  	&lt;load-on-startup&gt;1&lt;/load-on-startup&gt; 
  &lt;/servlet&gt;
 
  &lt;servlet-mapping&gt;
 	 &lt;servlet-name&gt;nomeDoServlet&lt;/servlet-name&gt; 
 	 &lt;url-pattern&gt;*.htm&lt;/url-pattern&gt; 
  &lt;/servlet-mapping&gt;

O que essa configuração do servlet que vc falou pra colocar web.xml faz? (Eu não entendi porque eu só tô querendo usar o spring pra gerenciar o jpa, por que eu preciso usar servlet?)

Beleza, os erros estão melhorando!! rsrs

erro:

Error creating bean with name 'entityManagerFactory': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name persistence is not bound in this Context

isso aí é porque ele não reconheceu o jndi-name que eu coloquei no applicationContext.xml!

 <bean>  
         <jee:jndi-lookup id="entityManagerFactory"  
             jndi-name="persistence/persistencia"/>

que nome tem que ser aí? sendo que o nome da persistenceunit eu coloquei persistencia!

Vc precisou configurar o Servlet? Pois fiquei em duvida se vc precisava depois que vc falou que so esta usando o Spring para fazer integração com JPA, pois eu estou usando o spring em outras camadas tbm.

Então de acordo com a documentação vc deve colocar o nome do persistence e depois o nome do seu PersistenceUnit msm:

&lt;beans&gt;

    &lt;jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/myPersistenceUnit"/&gt;

&lt;/beans&gt;

Vc precisa msm usar jndi ?

Na verdade eu só quero fazer uma conexão com o banco usando jpa e com o spring auxiliando… só isso!!

Ok, vou colocar as partes mais importantes do meu código aki, espero que te ajude:

Os beans para configuração do Spring, como eu estou configurando todo o meu dataSource no persistence.xml aqui eu não preciso especificar nada relacionado a ele, nem o o proprio persistence.xml:

	
	&lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
		&lt;property name="loadTimeWeaver"&gt;
			&lt;bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="productDAO" class="orm.dataaccess.dao.ProductDAO" /&gt;

	&lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /&gt;

	&lt;tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" /&gt;

	&lt;bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
		&lt;property name="entityManagerFactory" ref="entityManagerFactory" /&gt;
	&lt;/bean&gt;

web.xml:

 &lt;context-param&gt;
	&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
	&lt;param-value&gt;
		/WEB-INF/jpa-servlet.xml
	&lt;/param-value&gt;
  &lt;/context-param&gt;

  &lt;filter&gt;  
     &lt;filter-name&gt;transactionFilter&lt;/filter-name&gt;  
         &lt;filter-class&gt;org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter&lt;/filter-class&gt;  
     &lt;/filter&gt;  
       
  &lt;filter-mapping&gt;  
      &lt;filter-name&gt;transactionFilter&lt;/filter-name&gt;  
         &lt;url-pattern&gt;/*&lt;/url-pattern&gt;  
  &lt;/filter-mapping&gt;
  
  &lt;listener&gt;  
      &lt;listener-class&gt;  
          org.springframework.web.context.ContextLoaderListener  
      &lt;/listener-class&gt;  
  &lt;/listener&gt;  
   
  &lt;listener&gt;  
      &lt;listener-class&gt;  
           org.springframework.web.context.request.RequestContextListener  
      &lt;/listener-class&gt;  
  &lt;/listener&gt;  

Na sua DAO, ou na classe que vc esta injetando o entityManager:

@PersistenceContext
private EntityManager _entityManager = null;

public EntityManager getEntityManager() {
		return _entityManager;
	}
	
	public void setEntityManager(EntityManager entityManager) {
		_entityManager = entityManager;
	}

No método que vc depende de uma transação:

	@Transactional
	public void insert(Entity entity) {
		_entityManager.persist(entity);
	}

Não esqueça que onde vc for usar a sua DAO ela também deverá ser injetada pelo Spring