Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
02-13-2021 11:57 AM
So we are using
Spring Boot 2.4.2 and a desktop project of 4.2.3
The application ...
@SpringBootApplication
@EnableNeo4jRepositories
@Transactional
class DemoApplication{
@Bean
fun init (kennelRepository: KennelRepository, dogRepository:DogRepository): CommandLineRunner {
return CommandLineRunner {
kennelRepository.deleteAll()
dogRepository.deleteAll()
var dogFido: Dog = Dog(name = "fido")
dogRepository.save<Dog>(dogFido)
var dogRover: Dog = Dog(name = "rover")
var kennelForRover: Kennel = Kennel(dog = dogRover)
kennelRepository.save<Kennel>(kennelForRover)
print("complete")
}
}
}
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
the entities ...
@Node
data class Dog constructor(@Id @GeneratedValue val id: Long? = null, val name: String){
fun withId(id: Long): Dog {
return if (this.id == id) {
this
} else {
this.copy(id = id)
}
}
}
@Node
data class Kennel constructor (@Id @GeneratedValue val id: Long? = null, @Relationship val dog: Dog) {
fun withId(id: Long): Kennel {
return if (this.id == id) {
this
} else {
this.copy(id = id)
}
}
}
the repositories
@Repository
interface DogRepository : Neo4jRepository<Dog, Long>
@Repository
interface KennelRepository : Neo4jRepository<Kennel, Long>
So, the dog repository save of fido seems to work fine, but the kennel repository save gives an error ...
Caused by: java.lang.NullPointerException: null
at org.springframework.data.neo4j.core.Neo4jTemplate.convertIdValues(Neo4jTemplate.java:218) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.lambda$processNestedRelations$16(Neo4jTemplate.java:506) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:387) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.processNestedRelations(Neo4jTemplate.java:452) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.processRelations(Neo4jTemplate.java:442) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.saveImpl(Neo4jTemplate.java:254) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.save(Neo4jTemplate.java:225) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.repository.support.SimpleNeo4jRepository.save(SimpleNeo4jRepository.java:131) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:524) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:531) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:156) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:131) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.3.jar:5.3.3]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.3.jar:5.3.3]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.data.repository.core.support.MethodInvocationValidator.invoke(MethodInvocationValidator.java:98) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.3.jar:5.3.3]
at com.sun.proxy.$Proxy69.save(Unknown Source) ~[na:na]
at com.example.demo.DemoApplication$init$1.run(DemoApplication.kt:27) ~[main/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) ~[spring-boot-2.4.2.jar:2.4.2]
... 5 common frames omitted
I have written the equivalent code in Java and it all seems to work fine.
So I feel that I am missing something fairly fundamental here.
Any thoughts are very welcome.
Solved! Go to Solution.
02-18-2021 07:32 AM
Thanks for your very quick feedback.
You are defining the @Relationship
without any type. The type will default to an empty String in this case.
Leaving the @Relationship
definition completely out to generate the type from the parameter name is one option (but not recommended).
Providing the type explicitly is the better option: @Relationship("IS_HOME_OF")
02-17-2021 11:05 AM
02-17-2021 12:30 PM
The bug fix is also included in the 6.0.4.
02-18-2021 06:30 AM
Thanks @gerrit.meier
I replaced the
implementation("org.springframework.boot:spring-boot-starter-data-neo4j")
with the
implementation("org.springframework.data:spring-data-neo4j:6.0.4")
I can confirm that 6.0.4 no longer gives a NullPointerException
However, I am now receiving an exception
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:807) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.2.jar:2.4.2]
at com.example.demo.DemoApplicationKt.main(DemoApplication.kt:40) ~[main/:na]
Caused by: org.springframework.dao.InvalidDataAccessResourceUsageException: Exactly one relationship type must be specified for MERGE. Did you forget to prefix your relationship type with a ':'? (line 1, column 108 (offset: 107))
"MATCH (startNode) WHERE id(startNode) = $fromId MATCH (endNode) WHERE id(endNode) = $toId MERGE (startNode)-[relProps]->(endNode) RETURN id(relProps)"
^; Error code 'Neo.ClientError.Statement.SyntaxError'
at org.springframework.data.neo4j.core.Neo4jPersistenceExceptionTranslator.translateImpl(Neo4jPersistenceExceptionTranslator.java:105) ~[spring-data-neo4j-6.0.4.jar:6.0.4]
at org.springframework.data.neo4j.core.Neo4jPersistenceExceptionTranslator.translateExceptionIfPossible(Neo4jPersistenceExceptionTranslator.java:91) ~[spring-data-neo4j-6.0.4.jar:6.0.4]
at org.springframework.data.neo4j.core.DefaultNeo4jClient.potentiallyConvertRuntimeException(DefaultNeo4jClient.java:174) ~[spring-data-neo4j-6.0.4.jar:6.0.4]
at org.springframework.data.neo4j.core.DefaultNeo4jClient.access$400(DefaultNeo4jClient.java:55) ~[spring-data-neo4j-6.0.4.jar:6.0.4]
at org.springframework.data.neo4j.core.DefaultNeo4jClient$DefaultRecordFetchSpec.one(DefaultNeo4jClient.java:289) ~[spring-data-neo4j-6.0.4.jar:6.0.4]
when I try to save kennelForRover.
Once again, as before, dogFido was able to be saved.
I appreciate that with your efforts on Return related objects with ids set after save · Issue #2148 · spring-projects/spring-data-neo4j · G..., this whole area is a work in progress.
Still, this feels like a separate concern.
Indeed, I strongly suspect that I have just missed something obvious.
Please let me know if you want me to add this matter to Issue 2148 for reference or whether I should fire up a separate Github issue.
Many thanks.
02-18-2021 07:32 AM
Thanks for your very quick feedback.
You are defining the @Relationship
without any type. The type will default to an empty String in this case.
Leaving the @Relationship
definition completely out to generate the type from the parameter name is one option (but not recommended).
Providing the type explicitly is the better option: @Relationship("IS_HOME_OF")
02-18-2021 08:37 AM
And thanks for your rapid feedback.
Yes typing the relationship worked wonders.
Thank you for your help in giving a dog a home.
All the sessions of the conference are now available online