problem with lazy loading - unittest project attached

#1

hi,

i'm still testing objectdb together with spring-data-jpa.

i made a test which should simulate 4 requests

1. save entity

2. read an existing entity, add onetomany relation

3. read an existing entity, add another onetomany relation

4. read entity, get relations.

i have the feeling this is not the optional way to test this, because of the differnt transaction behavior.

the test is not transactional, but the spring repository methods are.

anyway, the expected result is in the database, one entity with 2 related entities.

if i use EAGER the test pass, if not the related entity list is empty.

what am i doing wrong?

#2

It seems that a repository is missing in the pom.xml file:

5/4/11 10:46:52 AM IDT: Missing artifact org.springframework.data:spring-data-jpa:jar:1.0.0.M2:compile

 

ObjectDB Support
#3

sorry, that's right, i'm using a central artifactory repository which is defined in my m2 settings.xml
please add the spring milestone repo in the POM
 

    <repositories>
        <repository>
            <id>spring-maven-milestone</id>
            <url>http://maven.springframework.org/milestone</url>
        </repository>
    </repositories>

 

#4

Now the testAddBars generates the following strange exception:

java.lang.IllegalStateException: Failed to load ApplicationContext
 at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308) ~[spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) ~[spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) ~[spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) ~[spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220) [spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301) [spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) [junit-4.8.2.jar:na]
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303) [spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) [spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) [junit-4.8.2.jar:na]
 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) [junit-4.8.2.jar:na]
 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) [junit-4.8.2.jar:na]
 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) [junit-4.8.2.jar:na]
 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) [junit-4.8.2.jar:na]
 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) [junit-4.8.2.jar:na]
 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.junit.runners.ParentRunner.run(ParentRunner.java:236) [junit-4.8.2.jar:na]
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) [spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) [.cp/:na]
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:na]
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) [.cp/:na]
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) [.cp/:na]
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) [.cp/:na]
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) [.cp/:na]
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [test/LazyLoadingTests-context.xml]; nested exception is java.io.FileNotFoundException: class path resource [test/LazyLoadingTests-context.xml] cannot be opened because it does not exist
 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:212) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:81) ~[spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1) ~[spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280) ~[spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304) ~[spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 ... 24 common frames omitted
Caused by: java.io.FileNotFoundException: class path resource [test/LazyLoadingTests-context.xml] cannot be opened because it does not exist
 at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:158) ~[spring-core-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:328) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
 ... 33 common frames omitted

 

ObjectDB Support
#5

hmm, strange, which maven goal did you use? or do you use an IDE? i use STS 2.6.0.
i have checked the zip content again and the test resource file

spring-data-jpa-lazy-loading/src/test/resources/test/LazyLoadingTests-context.xml
exists

i have attached my output of "mvn test"

#6

I had some problems in using Maven with the test in Eclipse but it runs well from the console.

I don't know much about Spring Data JPA but I noticed that after adding @Transactional (org.springframework.transaction.annotation.Transactional) to testAddBars both tests pass.

ObjectDB Support
#7

I think that when the test is not annotated with @Transactional - an ad hoc EntityManager instance is prepared for running findOne, and when the query execution completes that EntityManager is closed and the result object becomes detached.

Since the relationship between Foo And Bar is lazy - it is unavailable in a detached Foo instance and the collection looks empty.

ObjectDB Support
#8

thanks for your help

this is a little version of my real test, which uses a service layer with @Transactional annotated methods to add the relationships.

i didn't used @Tranactional for test classes/methods because that caused other problems, f.e.

with @Transactional testAddBars fails in line
foo = this.fooRepository.findOne(foo.getId());
because foo.id is null.

without the annotation the transaction should be valid for each repository method, so i guess after the commit the id is assigned?!

like i said, this is properbly not the best way to test it, it's more like an integration test.

i try to test 4 requests in one test, but each should have his own transaction.

spring does not allow me to call entityManager.getTransaction().begin()/commit() and i also can not set the isolation to READ_UNCOMMITTED

so i think if have to simplifiy my repository/service layer test and rethink how to test these multirequest scenarios.

i'm convinced that this is not a problem caused by objectdb.

thanks for your time and support.

#9

You are welcome.

To get an object ID before commit - please consider:

  • a different GeneratedValue's strategy (in ObjectDB the SEQUENCE and TABLE strategies generate automatic values as soon as new entity objects are persisted, i.e. before commit).
  • Using EntityManager's flush during the transaction.
ObjectDB Support

Reply