Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
02-23-2021 08:35 AM
In the AdditionalTypes class from Spring Data, there's a converter for Float:
On line 77/78
hlp.add(ConverterBuilder.reading(Value.class, Float.class, AdditionalTypes::asFloat).andWriting(AdditionalTypes::value));
hlp.add(ConverterBuilder.reading(Value.class, float.class, AdditionalTypes::asFloat).andWriting(AdditionalTypes::value));
Then later on, as this method is called in line 312:
static Float asFloat(Value value) {
return Float.parseFloat(value.asString());
}
It does an asString on the ValueAdapter, which in turn throws an exception:
@Override
public String asString()
{
throw new Uncoercible( type().name(), "Java String" );
}
This is using the following:
implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.hibernate:hibernate-spatial:5.4.22.Final'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
testImplementation('org.hamcrest:hamcrest:2.2')
testCompile (group: 'org.neo4j.test', name: 'neo4j-harness', version: '4.0.11'){
exclude group: 'org.slf4j', module: 'slf4j-nop'
}
testImplementation 'org.testcontainers:neo4j'
testCompile 'org.neo4j.procedure:apoc:4.0.0.18'
I believe instead of the AsString this method could've called toString and it would've been fine?
Note that I'm stuck on org.neo4j.test 4.0.x as it's the only version that allows installing the apoc plugin.
Solved! Go to Solution.
02-25-2021 02:51 AM
Hello.
Neo4j the database doesn't support java.lang.float
or java.lang.Float
. What is called Float
in Neo4j matches the Double
range.
We (SDN 6) stores Java Floats as String.
See Chapter conversions here: Spring Data Neo4j
Therefor, the converter is correct.
For things that are Neo4j double inside the database (doesn't matter if returned from APOC or actual properties), map them as Double inside your domain model.
OR converter them to valid ISO Float strings.
Cheers.
02-23-2021 09:37 AM
Can you please share the full stack trace?
Can you also please share the output of the Gradle equivalent of mvn dependency:tree
? (I believe it's gradle -q dependencies
).
Finally, can you elaborate on the issue with APOC? There 4.1.x and 4.2.x for APOC as well, so I don't see why they would not work with latest Neo4j versions (4.2.x).
Is there a reason you use testcontainers AND test-harness? It's usually one or the other.
Thanks!
02-24-2021 12:37 AM
Thanks for your swift reply.
To elobrate, 4.1.x and 4.2.x doesn't work with APOC 4.1.x or 4.2.x, I'm not the first one to notice this: cypher - Configuration of embedded Neo4j to run APOC procedures - Stack Overflow
Test containers are a relic, from trying things out. Removed them for now. And ran again.
Dependencies added as attachment, stack trace below.
Error mapping Record<{n: {__internalNeo4jId__: 1797, __paths__: [path[(1797)<-[2131:CONNECTED]-(251)], path[(1797)<-[2131:CONNECTED]-(251), (251)<-[295:ASSET_RELATIONSHIP]-(344)], path[(1797)<-[2131:CONNECTED]-(251), (251)<-[295:ASSET_RELATIONSHIP]-(344) - **path goes on**
org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.read(DefaultNeo4jEntityConverter.java:112)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.read(DefaultNeo4jEntityConverter.java:67)
at org.springframework.data.neo4j.core.mapping.Schema.lambda$getRequiredMappingFunctionFor$0(Schema.java:96)
at org.springframework.data.neo4j.core.PreparedQuery$AggregatingMappingFunction.apply(PreparedQuery.java:218)
at org.springframework.data.neo4j.core.PreparedQuery$AggregatingMappingFunction.apply(PreparedQuery.java:154)
at org.springframework.data.neo4j.core.DelegatingMappingFunctionWithNullCheck.apply(DelegatingMappingFunctionWithNullCheck.java:45)
at org.springframework.data.neo4j.core.DelegatingMappingFunctionWithNullCheck.apply(DelegatingMappingFunctionWithNullCheck.java:35)
at org.springframework.data.neo4j.core.DefaultNeo4jClient$DefaultRecordFetchSpec.one(DefaultNeo4jClient.java:285)
at org.springframework.data.neo4j.core.Neo4jTemplate$DefaultExecutableQuery.getSingleResult(Neo4jTemplate.java:584)
at org.springframework.data.neo4j.repository.query.Neo4jQueryExecution$DefaultQueryExecution.execute(Neo4jQueryExecution.java:53)
at org.springframework.data.neo4j.repository.query.AbstractNeo4jQuery.execute(AbstractNeo4jQuery.java:85)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:131)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at com.sun.proxy.$Proxy227.findOneById(Unknown Source)
at com.alliander.gpsapineo4jbatch.integration.Neo4jBatchTest.checkNeo4jObjects(Neo4jBatchTest.java:148)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy5.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:133)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: org.springframework.dao.TypeMismatchDataAccessException: Could not convert 4.430600166320801 into java.lang.Float; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [org.neo4j.driver.internal.value.FloatValue] to type [java.lang.Float] for value '4.430600166320801'; nested exception is org.neo4j.driver.exceptions.value.Uncoercible: Cannot coerce FLOAT to Java String
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jConversionService.readValueImpl(DefaultNeo4jConversionService.java:97)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jConversionService.readValue(DefaultNeo4jConversionService.java:74)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.lambda$populateFrom$3(DefaultNeo4jEntityConverter.java:365)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:360)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.lambda$map$2(DefaultNeo4jEntityConverter.java:270)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.map(DefaultNeo4jEntityConverter.java:289)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.map(DefaultNeo4jEntityConverter.java:239)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.read(DefaultNeo4jEntityConverter.java:110)
... 118 more
Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [org.neo4j.driver.internal.value.FloatValue] to type [java.lang.Float] for value '4.430600166320801'; nested exception is org.neo4j.driver.exceptions.value.Uncoercible: Cannot coerce FLOAT to Java String
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jConversionService.lambda$readValue$0(DefaultNeo4jConversionService.java:71)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jConversionService.readValueImpl(DefaultNeo4jConversionService.java:94)
... 125 more
Caused by: org.neo4j.driver.exceptions.value.Uncoercible: Cannot coerce FLOAT to Java String
at org.neo4j.driver.internal.value.ValueAdapter.asString(ValueAdapter.java:91)
at org.springframework.data.neo4j.core.convert.AdditionalTypes.asFloat(AdditionalTypes.java:313)
at org.springframework.data.convert.DefaultConverterBuilder$ConfigurableGenericConverter.convert(DefaultConverterBuilder.java:151)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
... 129 more
dependencies.txt (168.9 KB)
02-24-2021 01:41 AM
Can you upgrade to Spring Data Neo4j 6.0.5 and see if the error still occurs? There has been a few improvements with regards to path mapping.
02-24-2021 05:09 AM
Hi Florent,
Just upgraded to 6.0.5 by going to Spring Data 2.4.3, this gives the same behaviour.
Cheers,
Boyen
02-24-2021 09:35 AM
Can you edit your initial post to include the entities, the repositories and the test at play here? Thanks a lot!
02-25-2021 02:51 AM
Hello.
Neo4j the database doesn't support java.lang.float
or java.lang.Float
. What is called Float
in Neo4j matches the Double
range.
We (SDN 6) stores Java Floats as String.
See Chapter conversions here: Spring Data Neo4j
Therefor, the converter is correct.
For things that are Neo4j double inside the database (doesn't matter if returned from APOC or actual properties), map them as Double inside your domain model.
OR converter them to valid ISO Float strings.
Cheers.
02-25-2021 07:42 AM
@michael.simons1 thanks for the answer, that clears it up.
I would've expected to get an error if a type is not store-able. Now it's a silent failure that shows up when you try to read the value in a full round trip, values should always be round-trippable.
Also the error is quite cryptic in that you do have a FloatValue Neo4j object: org.neo4j.driver.internal.value.FloatValue
I have a hard time explaining to my peers why a FloatValue can not be converted to a Float at least.
We'll opt for the Double.
02-25-2021 08:42 AM
Hi. Thanks for your feedback. Sure, your 100% right. If you have stored the value from SDN 6, than of course you can read it back.
All the sessions of the conference are now available online