2012-05-10 10 views
17

seguí el tutorial publicado here para obtener una aplicación base para trabajar con Spring Data JPA. Ahora, como lo entendí, utilizando la configuraciónSpring Data JPA - falla la inyección - BeanCreationException: no se pudo autoconectar el campo

<jpa:repositories base-package="my.package.to.scan" /> 

debe dar lugar a que el paquete beeing escaneada en la primavera de datos JPA para las interfaces que se extienden JpaRepository y crear un grano concreate de ella para que pueda ser utilizado en cualquier lugar en mis clases de servicio usando simples Spring @Autowired. Pero falla, diciendo que no puede encontrar un bean con className (que es el nombre predeterminado que recibe el bean cuando se lo crea, simplemente usando ClassName sin capitalizar).

Sin embargo, cuando configuro el grano manualy en mi applicationContext así:

<bean id="ClassName" class="my.package.to.scan.ClassName"/> 

primavera es capaz de encontrar el grano. Entonces, por supuesto, obtengo un error porque quiero crear un bean desde una interfaz, lo que obviamente no puede funcionar. PERO el punto es que parece que la JPA de Spring Data "creación automática de frijoles" parece fallar de alguna manera.

He adjuntado el código correspondiente para que pueda verlo. Por cierto, debería mencionar que estoy desarrollando un portlet, por lo que no me pregunto por qué no tengo un Spring-Config. Actualmente estoy usando solo una aplicaciónConfig más un MyPortlet-Portlet.xml para las configuraciones de portlet (pero eso no debería ser relevante para este problema). Agregué las declaraciones de importación solo para asegurarme de que no estoy usando las anotaciones/clases incorrectas.

applicationContext.xml

<beans *** ALL MY XMLN's and XSI's *** /> 
<context:annotation-config /> 
<jpa:repositories base-package="model.repositories" /> 

// JPA specific configuration here: dataSource, persistenceUnitManager exceptionTranslator, entityManagerFactory, SessionFactory, transactionManager - should not be relevant for this problem, tell me if i'm wrong 

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

ICustomerService - sólo una interfaz para el CustomerService

import model.entities.Customer; 
public interface ICustomerService { 
     // example method 
    public Customer getCustomer(Long customerId); 
} 

a Cliente - la clase utilizada por mi lógica de la aplicación para obtener/conjunto de datos ORM

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.Pageable; 
import org.springframework.stereotype.Repository; 
import org.springframework.transaction.annotation.Transactional; 
import model.entities.Customer; 
import model.repositories.CustomerRepository; 
import model.service.interfaces.ICustomerService; 
@Repository 
@Transactional(readOnly = true) 
public class CustomerService implements ICustomerService{ 
    @Autowired 
    private CustomerRepository repository; 

    // example method 
    @Override 
    public Customer getCustomer(Long customerId){ 
     return repository.findById(customerId); 
    } 

CustomerRepository - el repositorio para la primavera de datos JPA

import javax.annotation.Resource; 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.transaction.annotation.Transactional; 
import model.entities.Customer; 
@Resource 
@Transactional(readOnly = true) 
public interface CustomerRepository extends JpaRepository<Customer, Long>{ 

    public Customer findById(Long id); 
} 

cliente - mi entidad muestra

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.Table; 

@Entity 
@Table(name = "Customers") 
public class Customer{ 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name = "ID_CUSTOMER") 
    private Long id; 

    @Column(name = "dbfirstname") 
    private String firstName; 

    @Column(name = "dbname") 
    private String lastName; 

    public Long getId(){ 
     return id; 
    } 

    public String getFirstName(){ 
     return firstName; 
    } 

    public void setFirstName(String firstName){ 
     this.firstName = firstName; 
    } 

    public String getLastName(){ 
     return lastName; 
    } 

    public void setLastName(String lastName){ 
     this.lastName = lastName; 
    } 
} 

i acaba de llegar del infierno ruta de clases con WebSphere (maldito, lo que es un fu * * producto ed up) y ahora estoy aquí. Espero que alguien pueda ayudarme con esto.

Una explicación básica de lo que funciona incorrectamente y quizás proporcionar una mejor comprensión de la función de inyección automática de muelles sería excelente. He leído la documentación de la primavera, pero a decir verdad: hay muchas maneras de configurar algo y no es del todo visible para mí. ¿QUÉ es realmente necesario al elegir uno de los estilos de configuración?

EDITAR

Después de tratar de actualizar el proyecto todavía estoy recibiendo el error.conforme a lo solicitado aquí un poco más de detalles (trazas):

Exception created : org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private model.repositories.CustomerRepository model.service.CustomerService.repository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerRepository': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106) 
    [...] 
     at com.ibm.ws.http.HttpConnection.run(HttpConnection.java:522) 
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1563) 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private model.repositories.CustomerRepository model.service.CustomerService.repository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerRepository': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284) 
    ... 96 more 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerRepository': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException 
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:149) 
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1442) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:248) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:848) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:790) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478) 
    ... 98 more 
Caused by: java.lang.NullPointerException 
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:73) 
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:115) 
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.java:149) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1215) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:177) 
    at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:89) 
    at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:179) 
    at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:174) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:600) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:376) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:517) 
    at $Proxy325.createEntityManager(Unknown Source) 

    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:234) 
    at $Proxy328.createNamedQuery(Unknown Source) 
    at org.springframework.data.jpa.repository.query.NamedQuery.<init>(NamedQuery.java:74) 
    at org.springframework.data.jpa.repository.query.NamedQuery.lookupFrom(NamedQuery.java:96) 
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:128) 
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:162) 
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:71) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:303) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:157) 
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:120) 
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:39) 
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142) 

editar # 2 compleate applicationContext.xml (includeing los cambios que hice basado en el debate en curso) que se añade a lo solicitado

<context:annotation-config /> 

<jpa:repositories base-package="model.repositories" /> 

<context:component-scan base-package="model,model.repositories,model.service,controller" /> 

<bean class="model.service.CustomerService"/> 
<bean class="model.service.OrderService"/> 
<bean class="model.repositories.CustomerRepository"/> 
<bean class="model.repositories.OrderRepository"/> 


<bean id="myExceptionTranslator" class="org.springframework.orm.hibernate4.HibernateExceptionTranslator" /> 

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/mydata" 
    resource-ref="true" cache="true" /> 


<bean id="pum" 
    class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"> 
    <property name="persistenceXmlLocations"> 
     <list> 
      <value>classpath*:META-INF/OverridePersistence.xml</value> 
     </list> 
    </property> 
    <property name="defaultDataSource" ref="dataSource" /> 
</bean> 


<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="generateDdl" value="true" /> 
      <property name="database" value="MYSQL" /> 
     </bean> 
    </property> 
    <property name="persistenceUnitManager" ref="pum" /> 
    <property name="persistenceUnitName" value="default" /> 
</bean> 

<bean id="mySessionFactory" 
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="packagesToScan" value="model"/> 
    <property name="hibernateProperties"> 
     <value>hibernate.dialect=org.hibernate.dialect.MySQLDialect</value> 
    </property> 
</bean> 

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
    <property name="sessionFactory" ref="mySessionFactory" /> 
</bean> 

<tx:annotation-driven /> 

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

Su CustomerRepository no necesita la anotación de recursos. Además, findById ya debería estar provisto por JpaRepository. Supongo que tu entityManager está bien creado sin errores. Con debería ser suficiente. Encienda su registro de depuración para las clases de Spring y verifique si hay algún error allí. – Luciano

+0

¿Por qué su CustomerService tiene la anotación del repositorio en lugar de la anotación del servicio? – Luciano

+0

revisa mis comentarios sobre la respuesta de Ryan Stewart. Básicamente porque seguí el tutorial que parece ser incompleto. – masi

Respuesta

19

Es muy probable que el problema esté en alguna configuración que no haya mostrado. También sería bueno si publicaras el error que estás recibiendo. Puede ser algo diferente de lo que piensas que es.

Una cosa que noto sobre su configuración es que está usando context:annotation-config en lugar de context:component-scan. Este último detectará automáticamente y creará beans basados ​​en la familia de anotaciones @Component. El primero no hace eso.

Aparte de eso, todo lo que publicaste parece que debería funcionar, aunque hay varias cosas raras, que veré en un momento. Copié todo el código publicado en un proyecto de muestra y rellené algunos detalles, como maven pom, persistence.xml y las piezas faltantes de the applicationContext.xml. También agregué un método de "creación" al servicio para que realmente hiciera algo. Con esos en su lugar y una clase principal para conducirlo todo, es un ejemplo ejecutable. Puede browse the code on github, o puede clonar y ejecutarlo con:

git clone git://github.com/zzantozz/testbed tmp 
cd tmp/stackoverflow/10539417-basic-spring-data-jpa 
mvn -q compile exec:java -Dexec.mainClass=rds.testbed.springDataJpa.SpringDataJp 

ya por las rarezas que he notado. Desde la parte superior:

  • Con el código como se da, no hay necesidad de que el PersistenceAnnotationBeanPostProcessor que ha agregado a la applicationContext.xml. No está haciendo nada por ti. Por supuesto, bien puede haber otro código que lo necesite que usted no haya mostrado.
  • La anotación @Repository en su CustomerService es supposed to be used on DAO classes, o las clases que interactúan con una base de datos. La anotación adecuada para un servicio es @Service.
  • La anotación @Resource en su ICustomerRepository es en su mayoría used for marking fields and methods for autowiring. No estoy seguro de qué te hizo pensar en ponerlo en tu interfaz de repositorio, pero no está haciendo nada allí.
  • Su repositorio no debe ser @Transactional. Eso pertenece a su servicio, y ya lo tiene, así que está bien. Tenga en cuenta que todavía funciona con el @Transactional en el repositorio porque simplemente se une a la transacción existente iniciada por el servicio.
  • Vale la pena señalar de nuevo que no está utilizando component scanning, aunque tiene una anotación relacionada con @Component (en su servicio). Eso podría estar causando algunos problemas. En lugar de activar el escaneo de componentes, creé manualmente el bean de servicio usando XML en el proyecto de muestra.

Así que ... si esto no te ha explicado algo, si me das un error específico, probablemente pueda explicar por qué lo recibes y te diga qué hacer para hacerlo bien.

+0

voy a revisar tu código y echar un vistazo. hasta ahora a sus preguntas: - a la derecha, parece que no necesito el PersistenceAnnotationBeanPostProcessor. Para la eliminación de errores me fui con "intente más y elimine lo que no necesita después de que funcione" - Lo del repositorio es extraño, lo sé. pero el tutorial que publiqué (primera oración en mi pregunta) establece que es correcto ya que la clase ES un repositorio incluso si se llama Service - Eliminé la anotación Resource de IFace - La anotación Transcational también se establece en el tutorial - no sabía que se suponía que debía usar el escaneo de componentes insted del anno conf – masi

+0

La etiqueta 'component-scan' [es un superconjunto de' annotation-config'] (http://static.springsource.org/spring/ docs/3.0.x/spring-framework-reference/html/beans.html # beans-java-combining-xml-centric-componente-scan). Lo hace, además escanea para las clases anotadas por cualquier anotación '@ Component'. –

+0

La publicación de blog que estaba siguiendo argumentó que el "servicio" era un repositorio porque tenía un EntityManager insertado en él, por lo que es un "repositorio" tradicional. También mencionó la intención de introducir un repositorio verdadero más adelante, aunque no parece estar a la vuelta de la esquina. Su ClienteServicio está inyectado con un CustomerRepository, por lo que claramente se trata de un '@ Service' y el otro es un' @ Repository'. –

Cuestiones relacionadas