Announcement Announcement Module
Collapse
No announcement yet.
SDN getting base class instead of subclass (bug?) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • SDN getting base class instead of subclass (bug?)

    I have a hierarchy like this:
    Code:
    @NodeEntity public class DummyBase {
    	@GraphId 	Long id;	
    	public Long getId() { return id; }
    }
    
    public class DummySub extends DummyBase {}
    And a repository for DummyBase:
    Code:
    public interface DummyBaseRepository extends GraphRepository<DummyBase> {}
    When I persist an instance of DummySub, I can get it back by its id:
    Code:
    DummySub dummySub = new DummySub().persist();
    Long id = dummySub.getId();
    DummyBase dummyBase = dummyBaseRepo.findOne(id);
    System.out.printf("%d %s\n", id, dummyBase.getClass().getName()); // it says: "123 DummySub"
    When I run the application once again and just try to get persisted entity by its known id, its type is DummyBase:
    Code:
    Long id = 123; // correct id here
    DummyBase dummyBase = dummyBaseRepo.findOne(id);
    System.out.printf("%s\n", dummyBase.getClass().getName()); // it now says: "DummyBase"
    I've also checked the database with Neoclipse and the type of that entity was DummySub, so it looks like problem is related with type mapping logic. I've also debugged it a little and it appeared that type alias is read correctly (the class name is DummySub), but then its base is used instead because Neo4jMappingContext::getPersistentEntity returns null (it only has DummyBase within its persistentEntities).

    It works fine within single application run/single application context, so the only way to reproduce it is to have 2 separate contexts both having the same configuration (one for writing and one for reading). I didn't manage to get 2 contexts work (after the first one is created, the second one fails to resolve dependencies), so I can only reproduce it in 2 application runs.

    I believe that workaround here is to persist at least one instance of each subclass in hierarchy on every application run, so that these types appear in persistentEntities and then resolved.

    Is this a bug?

  • #2
    Sounds pretty strange, so you have two application contexts?

    I think the "solution" is rather to have all node-entities registered with the mapping-context, in the first case it is registered during the save. but as you only have a repo for dummy-base the dummy-sub is never loaded so it never knows of that class. And also just casts this to just the supertype.

    I raised an issue in JIRA https://jira.springsource.org/browse/DATAGRAPH-234

    Thanks a lot

    Michael
    Last edited by MichaelHunger; May 10th, 2012, 07:31 PM.

    Comment


    • #3
      I mentioned two application contexts just in case you decide to add a test for this. In fact, scenario is pretty trivial. There's a web application that runs fine in case of clean run (mvn clean jetty:run) and has the described behavior in case database already exists (mvn jetty:run). Frankly, an older version of my application is based on SDN 1.1.0.RELEASE and this scenario works fine, so I think that behavior has changed since that version.

      Thanks Michael!

      Andrey.

      Comment


      • #4
        It changed b/c the type information in the graph must no longer be the class name it can be any kind of identification (also shorter ones). So it is not possible anymore to register the persistent entities from that (it rather tries to resolve an persistent entity with that identification).

        So I have to store the class-names of entities stored in the graph and use those at startup to register these classes.

        Michael

        Comment


        • #5
          Hmm. Are you absolutely sure about this approach? Just a couple of ideas:

          1. What about something like this:
          Code:
          @Polymorphic({DummySub1.class, DummySub2.class}) // just put these classes to mapping context
          interface DummyBaseRespository extends GraphRepository<DummyBase> {}
          ?

          2. Other idea is just to extend SDN app context configuration facilities:
          Code:
          <!-- will scan package and descendants for @NodeEntity-annotated classes and their subclasses -->
          <neo4j:entities base-package="com.stuff.myentities" />
          This looks like normal Spring solution, though I'm pretty new to Spring.

          Andrey.

          Comment


          • #6
            Yep probably #2, I thought about classpath scanning and will probably add it too.

            As a work-around just register your class with the mapping-context by for instance calling template.getMappingPolicy(class) or defining a repo for the subclass.

            Michael

            Comment


            • #7
              Thanks Michael

              I've already tried defining repositories for all types in hierarchy and it didn't help. Looks like mapping context gets populated lazily, so I have to do anything to them to make related classes appear in mapping context. Will check getMappingPolicy() workaround - thanks once again.

              Andrey.

              Comment

              Working...
              X