- Notifications
You must be signed in to change notification settings - Fork 619
Closed
Labels
type: bugA general bugA general bug
Description
SDN 6.3.18 returns incorrect instance type when a dynamic label is set on a node.
I have an example repo but here is a summary of the problem.
Entities
Given the following entity types
@Getter @Setter @NoArgsConstructor @Node(primaryLabel = "Fruit") public abstract class Fruit { @Id protected String id; @JsonIgnore @DynamicLabels protected Set<String> labels = Set.of(); } Subclass of Fruit
@Getter @Setter @NoArgsConstructor @Node(primaryLabel = "MagicalFruit") public class MagicalFruit extends Fruit { @Serial private static final long serialVersionUID = -8776591636750117301L; @Property(name = "volume") private double volume; @Property(name = "color") private String color; @Override public int hashCode() { return new HashCodeBuilder().append(id).hashCode(); } @Override public boolean equals(Object obj) { return obj == this || (obj instanceof MagicalFruit other && Objects.equals(id, other.id)); } } Sub classes of MagicalFruit
@Getter @Setter @NoArgsConstructor @Node(primaryLabel = "Apple") public class Apple extends MagicalFruit { @Override public boolean equals(Object obj) { return obj == this || (obj instanceof Apple other && Objects.equals(id, other.id)); } } and
@Getter @Setter @NoArgsConstructor @Node(primaryLabel = "Orange") public class Orange extends MagicalFruit { @Override public boolean equals(Object obj) { return obj == this || (obj instanceof Orange other && Objects.equals(id, other.id)); } } Repository
@Repository public interface FruitRepository extends Neo4jRepository<Fruit, String> { @Query("MATCH (f:Fruit) RETURN f") List<Fruit> findAllFruits(); } Test
@DataNeo4jTest class FruitRepositoryTest( val fruitRepository: FruitRepository, ) { @Test fun `debug dynamic label and deserialization`() { val applesWithDynamicLabel = List(2) { Apple().apply { volume = it.toDouble() color = "Red" labels = setOf("Apple_$it") } } val applesWithoutDynamicLabel = List(2) { Apple().apply { volume = it.toDouble() color = "Blue" } } val orangesWithDynamicLabel = List(2) { Orange().apply { volume = it.toDouble() color = "Red" labels = setOf("Orange_$it") } } val orangesWithoutDynamicLabel = List(2) { Orange().apply { volume = it.toDouble() color = "Yellow" } } fruitRepository.saveAll( applesWithDynamicLabel + applesWithoutDynamicLabel + orangesWithDynamicLabel + orangesWithoutDynamicLabel) val fruits = fruitRepository.findAllFruits() assertThat(fruits.filterIsInstance<Apple>()).hasSize(4) assertThat(fruits.filterIsInstance<Orange>()).hasSize(4) } } The above test fails because fruits contains instances of MagicalFruit when dynamic labels are set.
Other Findings
When I change MagicalFruit class to an abstract class, the same test pass.
#2529 is very similar bug but that example has abstract on Feline class.
Is this required to have only one concrete class as a leaf node of the inheritance hierarchy for dynamic label to work?
Metadata
Metadata
Assignees
Labels
type: bugA general bugA general bug