Results 1 to 5 of 5

Thread: Understanding Entity Persistent State

  1. #1
    Join Date
    Jul 2010
    Posts
    139

    Default SDG: Understanding Entity Persistent State

    I'm trying to understand the nature of Node persistent states for running my unit tests. I've setup a helper class that generates domain objects for testing purposes. I only want a limited number of objects created in order to easily see that the relationships are getting created correctly in the graph. So to do this, once I create them in my helper class, I'm storing them in a Map for later access. The issue I'm having is I occasionally get a org.neo4j.graphdb,NotFoundException in my tests, which I've tracked down to be related to the stored Domain objects in my helper class no longer having a corresponding Node entity in the graph. I wouldn't think this to be an issue, since my tests are transactional and I assume the nodes lifecycle are managed within the transaction - rolled back with the transaction once the unit test ends. I've attached my project files for further clarity.

    Here's my helper class:

    Code:
    @Component
    public class DomainObjectsAccessor
    {
      private String[] personNames = new String[]
      {
          "Joe Smith", "John Doe", "Jimmy Jones", "Paul Henry", "Sam Adams",
          "Glen Dale"
      };
      private Map<Integer, Person> mapOfPeople = new HashMap<Integer, Person>(
          personNames.length);
    
      public Person getPerson()
      {
        Random random = new Random(System.currentTimeMillis());
        int nameIndex = random.nextInt(personNames.length - 1);
    
        Person retVal = null;
    
        // prefer map if key exists
        if (mapOfPeople.containsKey(nameIndex))
        {
          retVal = mapOfPeople.get(nameIndex);
        }
        // else create new person, add to map for later
        else
        {
          retVal = new Person(UUID.randomUUID().toString(), personNames[nameIndex]);
          mapOfPeople.put(nameIndex, retVal);
        }
    
        return retVal;
      }
    }
    Here's my 2 Domain Objects:

    Code:
    @NodeEntity
    public class Person
    {
      private String id;
      private String name;
    
    ...
    }
    
    @NodeEntity
    public class Manager
    {
      private String id;
    
      @RelatedTo(elementClass = Person.class)
      private Set<Person> employees;
    ...
    }

    And finally my test that fails:

    Code:
    @TestExecutionListeners(TransactionalTestExecutionListener.class)
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class, value = "org.mycompany.graph.config.AppConfig")
    public class DomainObjectTests extends AbstractJUnit4SpringContextTests
    {
      @Autowired
      private DomainObjectsAccessor accessor;
    
      @Test
      @Transactional
      @Repeat(10)
      public void tests() throws Exception
      {
        Person person = accessor.getPerson();
        Set<Person> employees = new HashSet<Person>();
        employees.add(person);
        Manager manager = new Manager(UUID.randomUUID().toString(), employees);
        manager.persist();
      }
    }
    Stack Trace from failed Unit Test:
    Code:
    org.neo4j.graphdb.NotFoundException: Node[71] not found.
    	at org.neo4j.kernel.impl.core.NodeManager.getNodeForProxy(NodeManager.java:447)
    	at org.neo4j.kernel.impl.core.NodeProxy.hasProperty(NodeProxy.java:139)
    	at org.springframework.data.graph.neo4j.fieldaccess.PropertyFieldAccessorFactory$PropertyFieldAccessor.doGetValue(PropertyFieldAccessorFactory.java:93)
    	at org.springframework.data.graph.neo4j.fieldaccess.PropertyFieldAccessorFactory$PropertyFieldAccessor.getValue(PropertyFieldAccessorFactory.java:88)
    	at org.springframework.data.graph.neo4j.fieldaccess.PropertyFieldAccessorFactory$PropertyFieldAccessor.getValue(PropertyFieldAccessorFactory.java:1)
    	at org.springframework.data.graph.neo4j.fieldaccess.DefaultEntityState.getValue(DefaultEntityState.java:90)
    	at org.springframework.data.graph.neo4j.fieldaccess.DetachedEntityState.getValue(DetachedEntityState.java:80)
    	at org.mycompany.graph.model.common.Person.id_aroundBody13$advice(Person.java:255)
    	at org.mycompany.graph.model.common.Person.toString(Person.java:46)
    	at java.lang.String.valueOf(String.java:2826)
    	at java.lang.StringBuilder.append(StringBuilder.java:115)
    	at java.util.AbstractCollection.toString(AbstractCollection.java:422)
    	at java.lang.String.valueOf(String.java:2826)
    	at java.lang.StringBuilder.append(StringBuilder.java:115)
    	at org.springframework.data.graph.neo4j.fieldaccess.DetachedEntityState.flushDirty(DetachedEntityState.java:163)
    	at org.springframework.data.graph.neo4j.fieldaccess.DetachedEntityState.persist(DetachedEntityState.java:238)
    	at org.springframework.data.graph.neo4j.support.node.Neo4jNodeBacking.ajc$interMethod$org_springframework_data_graph_neo4j_support_node_Neo4jNodeBacking$org_springframework_data_graph_core_NodeBacked$persist(Neo4jNodeBacking.aj:120)
    	at org.mycompany.graph.model.common.Manager.persist(Manager.java:1)
    	at org.springframework.data.graph.neo4j.support.node.Neo4jNodeBacking.ajc$interMethodDispatch1$org_springframework_data_graph_neo4j_support_node_Neo4jNodeBacking$org_springframework_data_graph_core_NodeBacked$persist(Neo4jNodeBacking.aj)
    	at org.mycompany.graph.DomainObjectTests.tests(DomainObjectTests.java:37)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:597)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
    	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
    	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    	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)
    Attached Files Attached Files
    Last edited by jzcfk9; May 3rd, 2011 at 07:15 AM.

  2. #2
    Join Date
    Jul 2010
    Posts
    139

    Default

    Has anyone else run into this issue? As a programmer working with POJOs that are NodeEntities, do I need to be aware of persistent state of the underlying Neo4j nodes backing my POJOs?

    I would think SDG is trying to eliminate the need for understanding how POJOs are associated to the underlying Neo4j nodes. I'm thinking all I need to be aware of is that NodeEntities have a persistent state, and that they are either attached or detached.

    In the case of my unit test that I'm running, I can see that the underlying Neo4j Node is removed from the graph, but shouldn't the NodeEntity's corresponding EntityState be cleared once the transaction is rolled back?
    Last edited by jzcfk9; May 4th, 2011 at 06:02 AM.

  3. #3
    Join Date
    Jul 2010
    Posts
    139

    Default

    I've been slowly trying to debug this test case, and I'm currently seeing that the DefaultEntityState of the NodeEntity doesn't seem to be getting cleared correctly after a transaction rollback. I'm attaching a snapshot of my debugger after a rollback, but before a cascading persist on my Manager NodeEntity. The debugger shows the "dirty" node state for my Person NodeEntity.
    Attached Images Attached Images

  4. #4
    Join Date
    Jul 2010
    Posts
    139

    Default

    JIRA DataGraph-87 has been created to investigate the issue.

  5. #5
    Join Date
    Jan 2011
    Location
    Dresden, Germany
    Posts
    525

    Default

    Thanks for investigating and pointing that out, will look into it the next days. You're right that those nodes should be cleared out. Sorry for not getting back earlier, kids are sick and had conference talk this week.

    Cheers

    Michael

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •