Results 1 to 7 of 7

Thread: SDN getting base class instead of subclass (bug?)

Hybrid View

  1. #1
    Join Date
    Aug 2011
    Posts
    22

    Default 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. #2
    Join Date
    Jan 2011
    Location
    Dresden, Germany
    Posts
    525

    Default

    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 at 07:31 PM.

  3. #3
    Join Date
    Aug 2011
    Posts
    22

    Default

    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.

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

    Default

    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

  5. #5
    Join Date
    Aug 2011
    Posts
    22

    Default

    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.

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

    Default

    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

Tags for this Thread

Posting Permissions

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