Reputation: 7649
Apparently this is a common exception but, all the questions asked here seem to be related to CSV
hence, why this question.
I have a domain
object that make use of uuid
as unique id and is declared as follow
@NodeEntity(label = "TNODE")
public class TestNode {
@Id @GeneratedValue(strategy = UuidStrategy.class)
@Convert(UuidStringConverter.class)
private UUID uuid;
private String name;
@Relationship(type = "TEST_REL_IS", direction = Relationship.OUTGOING) private TestNodeTarget testTarget;
public TestNode() {}
public TestNode(String name, TestNodeTarget target) {
this.name = name;
this.testTarget = target;
}
//getters and setters
}
And the TestNodeTarget
is as follow
@NodeEntity(label = "TNODE_TARGET")
public class TestNodeTarget {
private Long id;
private String name;
public TestNodeTarget() {}
public TestNodeTarget(String name) {
this.name = name;
}
//getters and setters
}
I am using Spring Boot 2.0.3.RELEASE
with sprng-boot-data-neo4j
starter which pulls down neo4j-ogm-core-3.1.0
, neo4j-ogm-bolt-driver-3.1.0
, neo4j-ogm-api-3.1.0
and The mysterious neo4j-java-driver-1.5
.
I am using the Neo4j OGM SessionFactory
to build my own generic DAO layer instead of Spring Data Repository that restricts me from
I am able to perform CREATE
, READ
and DELETE
operations. The PUT
operations with following assumptions
tn:TestNode
, t1:TestNodeTarget
and t2:TestNodeTarget
tn
node has a relationship with t1
nodetn
node, t1 & t2
nodes tn
node relationship to t2
from t1
session.save
The exception is
Caused by: org.neo4j.driver.v1.exceptions.ClientException: Cannot merge node using null property value for uuid
at org.neo4j.driver.internal.util.ErrorUtil.newNeo4jError(ErrorUtil.java:62)
at org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher.handleFailureMessage(InboundMessageDispatcher.java:137)
at org.neo4j.driver.internal.messaging.PackStreamMessageFormatV1$Reader.unpackFailureMessage(PackStreamMessageFormatV1.java:432)
at org.neo4j.driver.internal.messaging.PackStreamMessageFormatV1$Reader.read(PackStreamMessageFormatV1.java:396)
at org.neo4j.driver.internal.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:83)
at org.neo4j.driver.internal.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:35)
at org.neo4j.driver.internal.shaded.io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284)
at org.neo4j.driver.internal.async.inbound.MessageDecoder.channelRead(MessageDecoder.java:40)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:297)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:413)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at org.neo4j.driver.internal.shaded.io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1336)
at org.neo4j.driver.internal.shaded.io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1127)
at org.neo4j.driver.internal.shaded.io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1162)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at org.neo4j.driver.internal.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1359)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at org.neo4j.driver.internal.shaded.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:935)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
Caused by: org.neo4j.driver.v1.exceptions.ClientException: Cannot merge node using null property value for uuid
message? The node uuid
value is not null. bolt-driver
and neo4j-java-driver
communicate with each other? I was surprised to see neo4j-java-driver
.Neo4j OGM
in favour of Spring Data's Repository
then can I ditch the spring-boot-starter-data-neo4j
? If yes, what happens to the @Transactional
and transaction management? Upvotes: 2
Views: 386
Reputation: 7649
Using a UUID
field annotated with @Id
is not a replacement to private Long id
field (or is it?). Add the id
field to the class and the exception disappears.
I couldn't wait and decided to debug this issue myself and share my findings
At first, the PUT
operation worked (without the private Long id
field) without exception but failed to delete the old relationship and based on this Github issue I wrapped the operations in @Transactional
and I got the exception. Some progress.
In ORM
context, the above would work fine. In other words, I can retrieve
the entity from @Transactional
annotated service layer, make necessary changes in a non-transactional
layer and then persist
the entity using another service layer method that is annotated with @Transactional
. For OGM
you gotta do it all in same transaction layer. Hum!
As shown in the question above, the TestNode
entity makes use of UUID
as follow
@Id @GeneratedValue(strategy = UuidStrategy.class)
@Convert(UuidStringConverter.class)
private UUID uuid;
I had to update the TestNode
class to include a
private Long id;
And after this the PUT
operation works as expected and the old relationship gets removed.
Why lack of private Long id;
only cause exception during update? Why not when you retrieve
, delete
, or create
the entity?
Upvotes: 2