Search code examples
neo4jneo4j-ogm

Genericity on Relationship @EndNode


I have a relation named "AUTHORED", this relation links a User and a Tip or a Comment, or a Build.

To avoid creating one class per relation endnode type, I decided to write a generic Authored class:

@RelationshipEntity(type="AUTHORED")
public class Authored<T> {

    @GraphId Long id;

    @StartNode
    private User author;

    @EndNode
    private T entity;

    private Long date;

    public User getAuthor() {
        return author;
    }

    public T getEntity() {
        return entity;
    }

    public Long getDate() {
        return date;
    }

    public void setDate(Long date) {
        this.date = date;
    }
}

Here is a part of my User class:

@NodeEntity
public class User extends Entity{

    private String firstName;

    private String lastName;

    private String ign;

    @JsonIgnore
    private String password;

    private String email;

    @Relationship(type="AUTHORED", direction="OUTGOING")
    @JsonIgnore private Set<Authored<Tip>> tips = new HashSet<Authored<Tip>>();

    public Set<Tip> getTips() {
        Set<Tip> tips = new HashSet<Tip>();
        this.tips.forEach((t) -> {
            tips.add(t.getEntity());
        });
        return tips;
    }
...
...

Problem here is that I get a RunTimeException:

java.lang.RuntimeException: Cannot find a writer for the EndNode of relational entity com.bnstips.api.database.model.relation.Authored
    at org.neo4j.ogm.context.GraphEntityMapper.createRelationshipEntity(GraphEntityMapper.java:340) ~[neo4j-ogm-core-2.0.0-M02.jar:na]
    at org.neo4j.ogm.context.GraphEntityMapper.mapRelationshipEntity(GraphEntityMapper.java:280) ~[neo4j-ogm-core-2.0.0-M02.jar:na]
    at org.neo4j.ogm.context.GraphEntityMapper.mapRelationships(GraphEntityMapper.java:243) ~[neo4j-ogm-core-2.0.0-M02.jar:na]
    at org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:143) ~[neo4j-ogm-core-2.0.0-M02.jar:na]
    at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:117) ~[neo4j-ogm-core-2.0.0-M02.jar:na]
    at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:81) ~[neo4j-ogm-core-2.0.0-M02.jar:na]
    at org.neo4j.ogm.session.delegates.LoadOneDelegate.load(LoadOneDelegate.java:48) ~[neo4j-ogm-core-2.0.0-M02.jar:na]
    at org.neo4j.ogm.session.Neo4jSession.load(Neo4jSession.java:82) ~[neo4j-ogm-core-2.0.0-M02.jar:na]
    at com.bnstips.api.database.GenericService.find(GenericService.java:22) ~[classes/:na]
    at com.bnstips.api.endpoint.UserEndpoint.getUserTips(UserEndpoint.java:33) ~[classes/:na]
...........
...........     

So, is it really possible to create Generic relationships? Am I doing something wrong?

EDIT: If this is not possible, Should I create one classe per Authored endnode type, or should I create 3 relationships, one per authored endnode type (AUTHORED_TIP, AUTHORED_COMMENT and AUTHORED_BUILD).


Solution

  • The generic Authored isn't supported. Both your alternatives will work.

    You can either have a specific relationship type per end node type, so three relationship entity classes annotated with different relationship types (AUTHORED_TIP, AUTHORED_COMMENT and AUTHORED_BUILD).

    Or, use the same relationship type if that is what your model deems better. You still need three relationship entity classes, but annotated them with the same relationship type (AUTHORED). An example of this is the Pizza class that has references to two relationship entities represented by the same relationship HAS - PizzaSeasoning and PizzaCheese

    Note that for both options above, your start/end node are specific and do not use generics.