2013-05-07 7 views
6

Ich schreibe Tests für meine DAO-Klassen mit JPA, mit Hibernate als JPA-Anbieter und Spring 3.2. Ich bin nicht in der Lage, den Entity Manager korrekt zu injizieren, ich bekomme eine NullPointerException, wenn ich versuche, darauf zuzugreifen. Meine GenericDAO Implementierung sieht wie folgt aus:Spring schlägt fehl Entity Manager Factory

@Repository 
public class GenericDAOImpl implements GenericDAO { 

    @PersistenceContext(unitName="unitname") 
    private EntityManager entityManager; 

    public EntityManager getEntityManager() { 
     return entityManager; 
    } 


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

    // NullPointerException when calling this, entityManager is null 
    public Query createNamedQuery(String name) { 
     return entityManager.createNamedQuery(name); 
    }   

    // many other methods.... 
} 

Die Klasse des Tests sieht wie folgt aus:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "/com/main/resources/root-context.xml", "/com/main/resources/servlet-context.xml"}) 
public class TestModel { 

    @Before 
    public void setUp() throws Exception{ 
     ... 
    } 

    @Test 
    public void test(){ 
     ... 
    } 
} 

Mein Wurzel-context.xml ist folgende:

<?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:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation=" 
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.0.xsd 
     http://www.springframework.org/schema/mvc 
     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd   
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
     " 
> 

    <!-- Root Context: defines shared resources visible to all other web components --> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
     <property name="username" value="root" /> 
     <property name="password" value="root" /> 
    </bean> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="unitname" /> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="packagesToScan" value="com.main" /> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
       <property name="showSql" value="true" /> 
       <property name="generateDdl" value="false" /> 
       <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" /> 
      </bean> 
     </property> 
    </bean> 

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

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



    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false" /> 
    <context:component-scan base-package="com.main" /> 
    <context:annotation-config /> 

</beans> 

Ich habe versuchte mehrere Ansätze ohne Erfolg, sogar die PersistenceAnnotationBeanPostProcessor, wie in anderen SO Fragen vorgeschlagen. Alle anderen Dinge scheinen gut zu funktionieren: Hibernate erstellt die Datenbanktabellen, der Kontext wird geladen usw. Was mache ich falsch?

bearbeiten: Der Stack-Trace ist die folgende:

java.lang.NullPointerException 
    at com.main.model.dao.JPAImpl.GenericDAOImpl.createNamedQuery(GenericDAOImpl.java:119) 
    at com.main.model.bo.DescriptorBO.persist(DescriptorBO.java:52) 
    at com.main.webmodule.JSONSerializer.deserialize(JSONSerializer.java:149) 
    at com.main.tests.TestModel.test(TestModel.java:86) 
    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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

Und hier ist der persistence.xml:

<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="unitname" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 
     <mapping-file>META-INF/jpql/NamedQueries.xml</mapping-file> 


     <class>com.main.model.Account</class> 
     <class>com.main.model.Action</class> 
     <class>com.main.model.Device</class> 
     <class>com.main.model.DeviceDescriptor</class> 
     <class>com.main.model.Event</class> 
     <class>com.main.model.File</class> 
     <class>com.main.model.Rule</class> 
     <class>com.main.model.StateVar</class> 
     <class>com.main.model.Argument</class> 
     <exclude-unlisted-classes>false</exclude-unlisted-classes> 


     <properties> 

      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> 
      <property name="hibernate.connection.username" value="root"/> 
      <property name="hibernate.connection.password" value="root"/> 
      <property name="hibernate.connection.provider_class" value="org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" /> 
      <property name="hibernate.connection.autocommit" value="true"/> 
      <property name="hibernate.connection.release_mode" value="auto"/> 
      <property name="hibernate.connection.url" value="jdbc:mysql://127.0.0.1:3306/testweb"/> 
      <property name="hibernate.hbm2ddl.auto" value="create"/> 

      <property name="hibernate.c3p0.min_size" value="1" /> 
      <property name="hibernate.c3p0.max_size" value="10" /> 
      <property name="hibernate.c3p0.acquire_increment" value="1" /> 
      <property name="hibernate.c3p0.idle_test_period" value="300" /> 
      <property name="hibernate.c3p0.max_statements" value="0" /> 
      <property name="hibernate.c3p0.timeout" value="100" /> 

      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> 

     </properties> 




    </persistence-unit> 
</persistence> 
+0

Veröffentlichen Sie Ihren Stacktrace. –

+0

Zeigen Sie uns Ihre 'persistence.xml' – falsarella

+0

Haben Sie die' root-context.xml' und 'ContextLoaderListener' in Ihrer web.xml konfiguriert? Siehe http://stackoverflow.com/q/9856721/1064325 und http://stackoverflow.com/q/1132565/1064325 – falsarella

Antwort

7

ich es endlich geschafft habe, das Problem zu lösen. Zu instanziieren GenericDAO benutzen ich eine autowired Anmerkung, auf diese Weise:

@Autowired 
private GenericDAO genericDao; 

aber die Klasse, in dem dies geschieht, genannt DescriptorBO, instanziiert wurde auf diese Weise:

DescriptorBO descrBO = new DescriptorBO(...); 

und damit entkam vollständig von der Kontrolle über die Frühlingscontainer. Dies zu ändern in:

@Autowired 
private DescriptorBO descrBO; 

und um die entsprechenden bean Definitionen an die Wurzel-context.xml:

<bean name="descriptorBO" class="com.main.model.bo.DescriptorBO"> 
    <property name="genericDao" ref="genericDao" /> 
</bean> 

<bean name="genericDao" class="com.main.model.dao.JPAImpl.GenericDAOImpl" /> 

das Problem gelöst. Jetzt wird der EntityManager richtig eingefügt.

Lektion gelernt: Wenn Spring den EntityManager (oder ein anderes injiziertes Objekt) nicht injiziert, überprüfen Sie, ob die gesamte Objekthierarchie über Ihrem Objekt von Spring verwaltet wird, d. e. instanziiert von Beans im Anwendungskontext, entweder direkt oder unter Verwendung der Autowired-Annotation. Stellen Sie sicher, dass Sie den neuen Operator nicht verwenden, um eines dieser Objekte zu instanziieren !!

Verwandte Themen