neo4j / sdn-rx

Nextgen Spring Data module for Neo4j supporting (not only) reactive data access and immutable support
https://neo4j.github.io/sdn-rx
Apache License 2.0
65 stars 23 forks source link

Getting "MappingException: Error mapping Record<{s: node<4>}>" #241

Closed benkuly closed 4 years ago

benkuly commented 4 years ago

Description Running custom queries with nodes, that contains relationships aborts with an error: MappingException: Error mapping Record<{s: node<4>}>. Some debugging in Neo4jPersistenceExceptionTranslator shows the original exception: Failed to instantiate net.folivo.matrix.bridge.sms.mapping.SmsRoom using constructor fun <init>(kotlin.Int, net.folivo.matrix.bot.appservice.user.AppserviceUser, net.folivo.matrix.bot.appservice.room.AppserviceRoom): net.folivo.matrix.bridge.sms.mapping.SmsRoom with arguments 4,null,null.

Does my query needs something like a map projection (https://neo4j.github.io/sdn-rx/current/#load)? This feels a little inconvenient.

How to reproduce? Run one of the following tests: https://github.com/benkuly/matrix-sms-bridge/blob/2d3d3069f80b01aa9356f21f78955252dfab8af9/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/SmsRoomRepositoryIT.kt#L90 https://github.com/benkuly/matrix-sms-bridge/blob/2d3d3069f80b01aa9356f21f78955252dfab8af9/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/SmsRoomRepositoryIT.kt#L108

The repository with the queries: https://github.com/benkuly/matrix-sms-bridge/blob/2d3d3069f80b01aa9356f21f78955252dfab8af9/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/SmsRoomRepository.kt

meistermeier commented 4 years ago

in yourSmsRoom you defined user and bridgedRoom as val. To create an instant during mapping phase, SDN-RX needs the information to create a valid Kotlin object. Again you have multiple choices, either change your query to something like:

@Query("MATCH (au:AppserviceUser {userId:\$userId}) <- [rau:OWNED_BY] - (s:SmsRoom) - [rar:BRIDGED_TO] -> (ar:AppserviceRoom {roomId:\$roomId}) RETURN s, collect(ar), collect(au), collect(rar), collect(rau)")

Or make the constructor parameters var/optional.

Please keep in mind that the returned data above still does not reflect your more complex set up data in the test and will fail in the assertion.

benkuly commented 4 years ago

Thank you for your help!

Making constructor parameters var and optional (var user: AppserviceUser?,) didn't work. Then I get null user and brdigedRoom. I also do not have immutable data anymore with this change.

Changing the query and assertations helped for the first query, but the second query failed at first with org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate net.folivo.matrix.bridge.sms.mapping.SmsRoom using constructor fun <init>(kotlin.Int, net.folivo.matrix.bot.appservice.user.AppserviceUser, net.folivo.matrix.bot.appservice.room.AppserviceRoom): net.folivo.matrix.bridge.sms.mapping.SmsRoom with arguments 4,AppserviceUser(userId=someUserId1, rooms=[]),null.

I fixed this by changing the query to

@Query("MATCH (au:AppserviceUser {userId:\$userId}) <- [rau:OWNED_BY] - (s:SmsRoom {mappingToken:\$mappingToken}) - [rar:BRIDGED_TO] -> (ar:AppserviceRoom) RETURN s, collect(ar), collect(au), collect(rar), collect(rau)")

The need to change the query so heavily to get this working seems very inconvenient, because I thought this will be managed by sdn-rx like e. g. in sd-jpa. And what are the consequences for such queries? My model stays that simple, but I'm afraid to use snd-rx in large projects.

meistermeier commented 4 years ago

Oh, of course you can make SDN-RX handle this by you in a simpler way: Drop the custom query and replace the method name with findByBridgedRoomRoomIdAndUserUserId this will create the matching query and your tests are green. I thought that the custom query were create because you did want to fetch only a sub-graph of your domain model.