-
Notifications
You must be signed in to change notification settings - Fork 620
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