mmwaikar
mmwaikar

Reputation: 665

Does Neo4j OGM work well with interfaces?

I've developed two sets of classes - the first one are just classes, whereas in the second set, the classes derive from interfaces. Both the sets of classes mimic each other. The repositories for them are also similar. However, the repository works well for the first set of classes (nodes and relationships). For the second set of classes though, the repository is able to insert records, but the findAll method fails and doesn't return me any records.

Here's the first set of classes with the repository -

public abstract class Entity {
    @GraphId
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || id == null || getClass() != o.getClass()) return false;

        Entity entity = (Entity) o;
        if (!id.equals(entity.id)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return (id == null) ? -1 : id.hashCode();
    }
}

public abstract class GenericRepository<T> implements IGenericRepository<T> {
    private static final int DEPTH_LIST = 1;

    private static final int DEPTH_ENTITY = 2;

    private Session session;

    public GenericRepository(String url, String username, String password) {
        super();
        session = Neo4jSessionFactory.getInstance().getNeo4jSession(url, username, password);
    }

    public Iterable<T> findAll() {
        return session.loadAll(getEntityType(), DEPTH_LIST);
    }

    public T findOne(Long id) {
        return session.load(getEntityType(), id, DEPTH_ENTITY);
    }

    public void delete(T entity) {
        session.delete(session.load(getEntityType(), ((Entity) entity).getId()));
    }

    public T createOrUpdate(T entity) {
        session.save(entity, DEPTH_ENTITY);
        return findOne(((Entity) entity).getId());
    }

    public abstract Class<T> getEntityType();
}

@RelationshipEntity(type="MY_ROLE")
public class ARole extends Entity {
    @Property
    private String title;

    @StartNode
    private HomoSapiens start;

    @EndNode
    private HomoSapiens end;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public HomoSapiens getStart() {
        return start;
    }

    public void setStart(HomoSapiens start) {
        this.start = start;
    }

    public HomoSapiens getEnd() {
        return end;
    }

    public void setEnd(HomoSapiens end) {
        this.end = end;
    }

    public ARole() {}
    public ARole(String title) {
        this.title = title;
    }
}

@NodeEntity
 public class HomoSapiens extends Entity {
    private String name;

    @Relationship(type = "MY_ROLE", direction = Relationship.INCOMING)
    private ARole aRole;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ARole getaRole() {
        return aRole;
    }

    public void setaRole(ARole aRole) {
        this.aRole = aRole;
    }

    public HomoSapiens() {}
    public HomoSapiens(String name) {
        this.name = name;
    }
}

public class ARoleDao extends GenericRepository<ARole> implements IARoleDao {
    public ARoleDao(String url, String username, String password) {
        super(url, username, password);
    }

    @Override
    public Class<ARole> getEntityType() {
        return ARole.class;
    }
}

Here's the second set of classes -

public interface IARole {
    String getTitle();
    void setTitle(String title);

    IHomoSapiens getStart();
    void setStart(IHomoSapiens start);

    IHomoSapiens getEnd();
    void setEnd(IHomoSapiens end);
}

public interface IHomoSapiens {
    String getName();
    void setName(String name);

    IARole getARole();
    void setARole(IARole aRole);
}

@RelationshipEntity(type="MY_DERIVED_ROLE")
public class DerivedARole extends Entity implements IARole {
    @Property
    private String title;

    @StartNode
    private IHomoSapiens start;

    @EndNode
    private IHomoSapiens end;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public IHomoSapiens getStart() {
        return start;
    }

    public void setStart(IHomoSapiens start) {
        this.start = start;
    }

    public IHomoSapiens getEnd() {
        return end;
    }

    public void setEnd(IHomoSapiens end) {
        this.end = end;
    }

    public DerivedARole() {}
    public DerivedARole(String title) {
        this.title = title;
    }
}

@NodeEntity
public class DerivedHomoSapiens extends Entity implements IHomoSapiens {
    private String name;

    @Relationship(type = "MY_DERIVED_ROLE", direction = Relationship.INCOMING)
    private IARole aRole;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public IARole getARole() {
        return aRole;
    }

    public void setARole(IARole aRole) {
        this.aRole = aRole;
    }

    public DerivedHomoSapiens() {}
    public DerivedHomoSapiens(String name) {
        this.name = name;
    }
}

public class DerivedARoleDao extends GenericRepository<DerivedARole> {
    public DerivedARoleDao(String url, String username, String password) {
        super(url, username, password);
    }

    @Override
    public Class<DerivedARole> getEntityType() {
        return DerivedARole.class;
    }
}

public class DerivedARoleDaoSpecs {
    private DerivedARoleDao derivedARoleDao;

    @Before
    public void setUp() throws Exception {
        derivedARoleDao = new DerivedARoleDao(DomainHelper.NEO_URL, DomainHelper.NEO_USERNAME,
                DomainHelper.NEO_PASSWORD);
    }

    public void should_insert_data() {
        IHomoSapiens start = new DerivedHomoSapiens("d-start");
        IHomoSapiens end = new DerivedHomoSapiens("d-end");
        IARole aRole = new DerivedARole("parent");

        start.setARole(aRole);
        end.setARole(aRole);

        aRole.setStart(start);
        aRole.setEnd(end);

        IARole created = derivedARoleDao.createOrUpdate((DerivedARole)aRole);
        assertThat(created, is(notNullValue()));
    }

    public void should_find_all() {
        Iterable<DerivedARole> derivedARoles = derivedARoleDao.findAll();
        assertThat(derivedARoles, is(notNullValue()));
        assertThat(Iterables.isEmpty(derivedARoles), is(false));
        assertTrue(Iterables.size(derivedARoles) > 0);
        System.out.println(Iterables.size(derivedARoles));
    }

    @Test
    public void should_do_crud() {
//        should_insert_data();
        should_find_all();
//        should_find_by_id();
    }
}

Am I missing something here? Or does the Neo4j OGM works well with classes (not implementing interfaces)?

The entire source code is at - https://github.com/mmwaikar/java-neo-ogm-ex (in case, it helps). Thanks, Manoj.

Upvotes: 0

Views: 208

Answers (1)

Luanne
Luanne

Reputation: 19373

This should be fixed in 1.1.3

Till that is released, please try your code example with 1.1.3-SNAPSHOT.

You'll need to include

 <repository>
        <id>neo4j-snapshots</id>
        <url>http://m2.neo4j.org/content/repositories/snapshots</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>

Upvotes: 2

Related Questions