You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Consider the following class hierarchy: A4 -> A3 -> A2 -> A1, where all are annotate with @Node, and A3..A1 are abstract.
When getting all NodeDescriptions from the Neo4jMappingContext, and calling getChildNodeDescriptionsInHierarchy(), I get the following results:
(format: primary label, list of all labels, results of getChildNodeDescriptionsInHierarchy())
Most important, A2 and A3 "know" about the child NodeDescription A4, however A1 does not (it only knows about A2 and A3)
This behavior gets even more strange with the following example:
B3a -> B3 -> B2 -> B1
B2a -> B2 -> B1
where all classes are annotated with @Node, but only B2a and B3a are not abstract
When running this multiple times, I get the following results:
For the first example, when the NodeDescription for A4 is created, addChildNodeDescription is called on A3. This updates the childNodeDescriptionsInHierarchy for A3 and its parent A2, but not for A1.
The probabilistic behavior of the second example can be explained by the order of NodeDescription creation, if A2a is created after A3a, A2a gets added to A2, causing A2 and A1 to be updated, therefore A1 "knowing" about A3a, if A3a is created after A2a, only A3 and A2 are updated, but not A1.
A simple fix would be to make updateChildNodeDescriptionCache recursive:
This fixes the inconsistent behavior, however, for deeper hierarchies, performance may be impacted due to more unnecessary calls to updateChildNodeDescriptionCache. A more intelligent algorithm would probably only make the recursive call if a non-abstract NodeDefinition is added, however this assumes that for each abstract NodeDefinition, a non-abstract one exists (and I'm not sure if this is always given) (also, this optimization is most likely not necessary, however I wanted to mention it in case you are worried about the performance impact of the recursive call).
Last, I want to mention, that this might not even be a bug. The documentation of getChildNodeDescriptionsInHierarchy says Retrieve all direct child node descriptions which extend this entity., however, "InHierarchy" (and the actual behavior) imply to me, that in most cases, it also returns indirect children (or my understanding of direct children is incorrect).
However, NodeDescriptionStore.computeConcreteNodeDescription seems to depend on it also returning the indirect children. In fact, not returning indirect children (which is sometimes the case due to this bug) can cause MappingExceptions, as then a NodeDescription for an abstract superclass fits the returned labels best (as the even better fitting non-abstract class is unknown to the NodeDescriptionStore)
The text was updated successfully, but these errors were encountered:
Thanks for the detailed analysis. I don't have much to add to it, actually apart from labelling this as a bug:
the result must be consistent with a given set of entities (in all the cases the mapping context is set to strict and has a predefined set of entities)
if this is the case, the hierarchy must contain all entries
I will ponder a moment whether to make the scanning smarter, but I am reluctant to premature optimise it. We are hopefully not speaking about models with an inheritance tree in the 3 digits or so.
Hello,
I found some strange/inconsistent behavior of
Neo4jMappingContext.getChildNodeDescriptionsInHierarchy()
.Demo showcasing the behavior can be found here: https://github.com/nk-coding/sdn-nodedescription-bug
Consider the following class hierarchy: A4 -> A3 -> A2 -> A1, where all are annotate with
@Node
, and A3..A1 areabstract
.When getting all
NodeDescription
s from theNeo4jMappingContext
, and callinggetChildNodeDescriptionsInHierarchy()
, I get the following results:(format: primary label, list of all labels, results of
getChildNodeDescriptionsInHierarchy()
)Most important, A2 and A3 "know" about the child NodeDescription A4, however A1 does not (it only knows about A2 and A3)
This behavior gets even more strange with the following example:
where all classes are annotated with
@Node
, but only B2a and B3a are not abstractWhen running this multiple times, I get the following results:
As far as I know, this behavior is caused by how the initialization of the childNodes work on DefaultNeo4jPersistentEntity:
For the first example, when the NodeDescription for A4 is created,
addChildNodeDescription
is called on A3. This updates thechildNodeDescriptionsInHierarchy
for A3 and its parent A2, but not for A1.The probabilistic behavior of the second example can be explained by the order of NodeDescription creation, if A2a is created after A3a, A2a gets added to A2, causing A2 and A1 to be updated, therefore A1 "knowing" about A3a, if A3a is created after A2a, only A3 and A2 are updated, but not A1.
A simple fix would be to make
updateChildNodeDescriptionCache
recursive:This fixes the inconsistent behavior, however, for deeper hierarchies, performance may be impacted due to more unnecessary calls to
updateChildNodeDescriptionCache
. A more intelligent algorithm would probably only make the recursive call if a non-abstract NodeDefinition is added, however this assumes that for each abstract NodeDefinition, a non-abstract one exists (and I'm not sure if this is always given) (also, this optimization is most likely not necessary, however I wanted to mention it in case you are worried about the performance impact of the recursive call).Last, I want to mention, that this might not even be a bug. The documentation of
getChildNodeDescriptionsInHierarchy
saysRetrieve all direct child node descriptions which extend this entity.
, however, "InHierarchy" (and the actual behavior) imply to me, that in most cases, it also returns indirect children (or my understanding of direct children is incorrect).However,
NodeDescriptionStore.computeConcreteNodeDescription
seems to depend on it also returning the indirect children. In fact, not returning indirect children (which is sometimes the case due to this bug) can causeMappingException
s, as then a NodeDescription for an abstract superclass fits the returned labels best (as the even better fitting non-abstract class is unknown to theNodeDescriptionStore
)The text was updated successfully, but these errors were encountered: