Unable to create a relationship with save method of Neo4jRepository

Hello,
I am trying to create a set of CRUD REST APIs for Neo4j. Everything works fine except I am unable to create a new relationship. These are the entities:

@Node("Movie")
@Getter @Setter  @AllArgsConstructor @ToString
public class Movie {

    @Id
    @GeneratedValue
    //@JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private Long id;

    @Property("title")
    private String title;

    @Property("description")
    private String description;

    @Relationship(type = "ACTED_IN", direction = Relationship.Direction.INCOMING)
    private List<Roles actorsAndRoles;

    @Relationship(type = "DIRECTED", direction = Relationship.Direction.INCOMING)
    private List<Person directors;
}

 @Node("Person")
 @Getter @Setter @AllArgsConstructor @ToString
 public class Person {
 
     @Id @GeneratedValue
     private Long id;
 
     @Property("name")
     private String name;
 
     @Property("born")
     private String born;
 
 }

 @Getter @Setter @AllArgsConstructor @ToString
 @RelationshipProperties
 public class Roles{
 
     @RelationshipId
     private Long id;
 
     @TargetNode
     private Person person;
 
     @Property("roles")
     private List<String roles;
 }

This is the controller (the class is called MovieController) method I am calling:

@PostMapping
    public ResponseEntity create(@RequestBody Movie movie){
        try {
            movie.setId(null);
            return ResponseEntity.ok(movieService.save(movie));
        }
        catch(Exception e){
            return ResponseEntity.internalServerError().body(e.getMessage());
        }
    }

I have uploaded the code here: https://github.com/RosarioB/spring-boot-crud-rest-api-neo4j/tree/basic_crud

This is an example of a body of a POST request at: http://localhost:8080/api/movies

{
    
   "title":"Matrix",
   "description":"Science fiction",
   "actorsAndRoles":[
       {
           "person":{
               "name":"Keanu Reeves",
               "born":"27-01-1963"
           }
       }
   ]
   

}

And this is the response:

{
    "id": 16,
    "title": "Matrix",
    "description": "Science fiction",
    "actorsAndRoles": [
        {
            "id": null,
            "person": {
                "id": 17,
                "name": "Keanu Reeves",
                "born": "27-01-1963"
            },
            "roles": null
        }
    ],
    "directors": null
}

Unfortunately on the database only the 2 nodes (one Person and one Movie) got created but not the relationship. I would have expected the relationship ACTED_IN to be created too.

What am I doing wrong? Thank you very much!

I just did the same thing in a micro service I am building for my application. I decided to use SDN in this micro service because I am managing entire domain objects and I wanted to get experience. It worked out of the box for me, so I was confused after downloading and reviewing your code why it was not working. You did similar stuff to what I did and mine worked. After trying many adjustments that did not resolve the issue, I downgraded your spring version of 3.1 to the one I was using 3.0.6. With that change it worked! I then upgraded my project to 3.1 and it stopped working, no relationships.

If you review your debug logs you will see instructions for creating both relationships, but they are not created. There is a condition to match on the relationship's id. I suspect this is not being met in the 3.1 code base.

Maybe you should open an issue.

Spot on. We moved towards more usage of elementId() in the SDN 7.1 release. Those change should have happened more transparent than it actually was.
Good news: it has already been fixed in Relationships not stored/deleted on update of node (Release >=7.1.0) · Issue #2728 · spring-projects/spring-data-neo4j · GitHub

Some background:
The CypherDSL uses a 4.4 (Neo4j LTS version) dialect as default. There is no "stable" elementId() available, so it falls back to toString(id(node/relationship)). This creates a condition that can never be fulfilled.
This is actually not a bug because CypherDSL has been told to talk 4.4.-syntax but you connect to a version 5 instance that happily returns elementIds from the nodes and relationship via the driver. So the unified id type is the elementId-String. And given the huge test base in SDN, we did not see this coming. Why? Because we configured the CypherDSL to use the NEO4J_5 dialect.
You can / should also do this by defining a CypherDSL configuration bean:

@Bean
Configuration cypherDslConfiguration() {
	return Configuration.newConfig().withDialect(Dialect.NEO4J_5).build();
}

Where I miserably failed was on mentioning this anywhere in the documentation of Spring Data Neo4j.
Even though we are getting more lenient with the bug fix regarding the given default dialect configuration, you should consider defining the dialect in your database.

I added the bean to my spring boot application and I still received the warning about id being deprecated on each save.

The query used a deprecated function. ('id' is no longer supported)
2023-06-10T10:05:01.739-04:00  WARN 69532 --- [           main] org.springframework.data.neo4j.cypher    : Neo.ClientNotification.Statement.FeatureDeprecationWarning: This feature is deprecated and will be removed in future versions.
	UNWIND $__relationships__ AS relationship WITH relationship MATCH (startNode:`StoreOrder`) WHERE startNode.key = relationship.fromId MATCH (endNode) WHERE id(endNode) = relationship.toId MERGE (startNode)-[relProps:`HAS_ITEM`]->(endNode) RETURN id(relProps) AS __internalNeo4jId__, elementId(relProps) AS __elementId__

I updated to SpringBoot 3.1.1. The log warnings are no longer produced when I have the Configuration bean. The relationships are also created.

1 Like