2
votes

Using Spring Boot and Neo4J, I've created two @NodeEntity's. They are User and Right. In my model, when you create a relationship between a User and Right, I call it a Privilege

I cannot save the @RelationshipEntity, Privilege (from within either of the @NodeEntity's or the RelationshipEntity).

Example Code

User.java (backed by interface UserRepository extends GraphRepository)

@NodeEntity
public class User {

    @Autowired Neo4jTemplate template;

    @GraphId Long id;
    String fullName;
    @Indexed(unique=true) String email;

    @Fetch @RelatedTo(type="HAS_RIGHT")
    Set<Right> rights;

    public void addRight(Right r) {
        Privilege p = new Privilege (this, r)
        template.save(p)  // This always throws a NullPointerException
    }

    /*** Getters and Setters ***/

}

Right.java (backed by interface RightRepository extends GraphRepository)

@NodeEntity
public class Right {

    @GraphId Long id;
    String name;

    /*** Getters and Setters ***/

}

Privilege.java (Not backed by a repository interface) - PROBLEM CLASS

@RelationshipEntity(type="HAS_RIGHT")
public class Privilege {

    @Autowired
    Neo4jTemplate template; // This is always null

    @GraphId Long id;
    @StartNode User user;
    @EndNode Right right;

    public Privilege() {}

    public Privilege(User user, Right right) {
        this.user = user;
        this.right = right;
    }

    public void save() {
        template.save(this); // Always throws a NullPointerException
    }
}

In my test case I can call (this works):

User user = userRepository.findByEmail("[email protected]");
Right adminRight = rightRepository.findByName("ADMINISTRATOR");
Privilege adminPrivilege = new Privilege(user, adminRight);
template.save(adminPrivilege);

But I'd prefer to call (this does not work):

User user = userRepository.findByEmail("[email protected]");
User.addRight (rightRepository.findByName("ADMINISTRATOR"));

But I also can't access template from within either of the NodeEntities.

2

2 Answers

1
votes

You can create relationship by using Neo4jTemplate Or Neo4jOperations.

Change it to constructor injection.

@Autowired
public Constructor(Neo4jOperations operations) {
    this.neo4jOperations = operations;
}

Once you have both the nodes by calling the repository, do something like:

Relation relation = neo4jOperations.createRelationshipBetween(user, right, Relationship.class, "RELATION_NAME", true);
neo4jOperations.save(relation);
1
votes

My mistake was that I was instantiating the class manually, therefore it was not spring managed. Adding the @Component annotation to the class and asking Spring to give me the class resolved the problem.

@Component // This is the line that saved the day!
@RelationshipEntity(type="HAS_RIGHT")
public class Privilege {

    @Autowired
    Neo4jOperations operations;

    @GraphId Long id;
    @StartNode User user;
    @EndNode Right right;

    public Privilege() {
        ;;
    }

    public void createRelationship(User user, Right right) {
        this.user = user;
        this.right = right;
        this.save();
    }

    /*** Getters and Setters ***/
}

Then to instantiate it:

...
@Autowired ApplicationContext applicationContext;
...
Privilege privilege = applicationContext.getBean(Privilege.class);
privilege.createRelationship(user, ADMINISTRATOR);