2012-05-10 24 views
17

postępowałem zgodnie z instrukcją here, aby uzyskać podstawową aplikację do pracy z Spring Data JPA. Teraz, jak mam rozumieć, wykorzystując konfiguracjęWiosenne dane JPA - iniekcja kończy się niepowodzeniem - BeanCreationException: Nie można przetłumaczyć pola

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

powinno skutkować tym pakiecie beeing skanowanego wiosennym Danych WZP interfejsów rozciągających JpaRepository i stworzyć concreate fasoli z niego, więc może być stosowany wszędzie w moich klasach serwisowych za pomocą prostych Wiosna @Autowired. Ale nie powiedzie się, mówiąc, że nie może znaleźć komponentu bean o nazwie className (która jest domyślną nazwą, którą komponent bean otrzymuje po utworzeniu, po prostu używając zdekapitalizowanej nazwy klasy).

Jednak, kiedy skonfigurować fasoli manualy w moim ApplicationContext tak:

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

Wiosna jest w stanie znaleźć Bean. Wtedy oczywiście dostaję błąd, ponieważ chcę utworzyć komponent z interfejsu, który oczywiście nie może działać. ALE chodzi o to, że wydaje się, że Spring Data JPA "automatyczne tworzenie fasoli" wydaje się jakoś zawieść.

Dołączyłem odpowiedni kod, abyś mógł na niego spojrzeć. Btw, powinienem wspomnieć, że rozwijam portlet, więc nie zastanawiam się, dlaczego nie mam konfiguracji wiosennej. Obecnie używam tylko applicationConfig oraz MyPortlet-Portlet.xml dla konfiguracji portletów (ale to nie powinno być odpowiednie dla tego problemu). Dodałem instrukcje importowania tylko po to, aby upewnić się, że nie używam złych adnotacji/klas.

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 - po prostu interfejsem dla customerservice

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

customerservice - klasy używane przez mojego logiki aplikacji do pobierania/ustawiania danych 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 - repozytorium Wiosna danych WZP

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); 
} 

Klienta - moja jednostka próbka

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; 
    } 
} 

Właśnie wróciłem ze ścieżki klasy diabła z WebSphere (cholera, co za fu * * ed up product) i teraz jestem tutaj. Mam nadzieję, że ktoś może mi w tym pomóc.

Podstawowe wyjaśnienie tego, co dzieje się nie tak i może lepsze zrozumienie funkcji sprężynowych funkcji automatycznego wtrysku byłoby wspaniale. Czytałem dokumentację źródłową, ale mówiąc prawdę: jest tak wiele sposobów na skonfigurowanie czegoś i nie jest to dla mnie widoczne, CO jest naprawdę potrzebne przy wyborze jednego ze stylów konfiguracji.

EDIT

Po próbuje zaktualizować projekt nadal jestem uzyskiwanie błąd.zgodnie z prośbą o trochę więcej szczegółów (śladowych):

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) 

EDIT # 2 compleate applicationContext.xml (includeing zmiany zrobiłem w oparciu o toczącej się dyskusji) dodaje się jako wniosek

<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

Twój CustomerRepository nie potrzebuje adnotacji o zasobach. Ponadto, findById powinien już być dostarczony przez JpaRepository. Zakładam, że twoja encja Manager jest stworzona dobrze bez błędów. Z powinno wystarczyć. Włącz dziennik debugowania dla klas wiosennych i sprawdź, czy jest tam jakiś błąd. – Luciano

+0

Dlaczego Twoja CustomerService ma adnotację repozytorium zamiast adnotacji Service? – Luciano

+0

sprawdź moje komentarze na temat odpowiedzi Ryana Stewarta. przede wszystkim dlatego, że postępowałem zgodnie z samouczkiem, który wydaje się być niekompletny. – masi

Odpowiedz

19

Problem jest prawdopodobnie w niektórych konfiguracjach, których nie pokazałeś. Byłoby dobrze, gdybyś opublikował błąd, który otrzymujesz. To może być coś innego, niż myślisz.

Jedną z rzeczy, które zauważyłem w twojej konfiguracji, jest to, że używasz context:annotation-config zamiast context:component-scan. Ta ostatnia automatycznie wykryje i utworzy ziarno w oparciu o rodzinę adnotacji @Component. Ten pierwszy tego nie robi.

Poza tym wszystko, co napisałeś, wygląda na to, że powinno działać, chociaż jest kilka dziwnych rzeczy, do których doszedłem za chwilę. Skopiowałem cały opublikowany kod do przykładowego projektu i wypełniłem kilka szczegółów, takich jak maven pom, persistence.xml i brakujących elementów the applicationContext.xml. Dodałem też do usługi metodę "tworzenia", aby faktycznie coś zrobiła. Z tymi na miejscu i główną klasą, która napędza to wszystko, jest to działający przykład. Można browse the code on github, czy można sklonować i uruchomić go z:

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 

Teraz o osobliwości zauważyłem. Od góry:

  • z kodem jak podano, nie ma potrzeby, aby PersistenceAnnotationBeanPostProcessor, które dodałeś do applicationContext.xml. To nic dla ciebie nie robi. Oczywiście może istnieć inny kod, który tego wymaga, którego nie pokazałeś.
  • Adnotacja @Repository w witrynie CustomerService to supposed to be used on DAO classes lub klasy interakcji z bazą danych. Odpowiednia adnotacja do usługi to @Service.
  • Adnotacja w Twoim ICustomerRepository to głównie used for marking fields and methods for autowiring. Nie jestem pewien, co skłoniło cię do umieszczenia go w twoim interfejsie repozytorium, ale nic tam nie robi.
  • Twoje repozytorium nie powinno być @Transactional. To należy do twoich usług, a ty już to tam masz, więc to w porządku. Zauważ, że nadal działa z @Transactional w repozytorium, ponieważ po prostu łączy się z istniejącą transakcją rozpoczętą przez usługę.
  • Warto ponownie zauważyć, że nie używasz component scanning, nawet jeśli masz przypisaną adnotację @Component (@Repository w usłudze). To może powodować pewne problemy. Zamiast włączać skanowanie komponentów, ręcznie utworzyłem komponent bean usługi przy użyciu XML w przykładowym projekcie.

Więc ... jeśli to ci nie wyjaśniło, jeśli podasz mi konkretny błąd, prawdopodobnie pomogę ci wyjaśnić, dlaczego to robisz i powiedzieć, co zrobić, aby było dobrze.

+0

przejdę przez twój kod i zobaczę. jak dotąd na twoje pytania: - prawda, wydaje się, że nie potrzebuję PersistenceAnnotationBeanPostProcessor. Do debugowania poszedłem z "spróbuj więcej i usuń to, czego nie potrzebujesz po pracy" - Rzecz repozytoryjna jest dziwna wiem. ale samouczek, który napisałem (pierwsze zdanie w moim pytaniu) stwierdza, że ​​to prawda, ponieważ klasa JEST repozytorium, nawet jeśli jego nazwana Usługa - usunąłem adnotację o zasobach z IFace - Adnotację Transcational również podano w tutorialu - nie wiedziałem, że powinienem użyć skanowania składników insted z anno conf – masi

+0

Tag 'component-scan' [jest nadzbiorem' adnotacji-config'] (http://static.springsource.org/spring/ docs/3.0.x/spring-framework-reference/html/beans.html # beans-java-combining-xml-centric-component-scan). Czyni to, a także skanuje dla klas adnotowanych przez adnotację "@ Component". –

+0

Wpis na blogu, który obserwowałeś, argumentował, że "usługa" była repozytorium, ponieważ została wprowadzona do EntityManager, co czyni go tradycyjnym "repozytorium". Wspomniał także o zamiarze wprowadzenia prawdziwego repozytorium w późniejszym czasie, choć wydaje się, że się do niego nie zbliża. Twoja CustomerService jest wstrzykiwany w CustomerRepository, więc wyraźnie jest to '@ Service', a druga to' @ Repository'. –

Powiązane problemy