[ https://issues.apache.org/jira/browse/IGNITE-16056?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Ivan Bessonov updated IGNITE-16056: ----------------------------------- Fix Version/s: 3.0.0-alpha4 > Using polymorphic schema leads to ClassCastException > ---------------------------------------------------- > > Key: IGNITE-16056 > URL: https://issues.apache.org/jira/browse/IGNITE-16056 > Project: Ignite > Issue Type: Bug > Affects Versions: 3.0.0-alpha3 > Reporter: Vyacheslav Koptilin > Assignee: Kirill Tkalenko > Priority: Blocker > Labels: ignite-3 > Fix For: 3.0.0-alpha4 > > Time Spent: 40m > Remaining Estimate: 0h > > Using polymorphic schema can lead to ClassCastException. > Let's consider the following configuration example: > {code:java} > ConfigurationRegistry registry = new ConfigurationRegistry( > List.of(ThirdRootConfiguration.KEY), > Map.of(), > new TestConfigurationStorage(LOCAL), > List.of(), > List.of( > First0PolymorphicConfigurationSchema.class, > First1PolymorphicConfigurationSchema.class)); > registry.start(); > registry.getConfiguration(ThirdRootConfiguration.KEY).change(c -> { > c.changeEntity(entity -> { > entity.create("new entity", upd -> { > upd.changePolymorphicConfig(p -> { > p.create("key", polymorphicChange -> { > polymorphicChange.changeName("entity name"); > > polymorphicChange.convert(First0PolymorphicChange.class).changeTest0(12); > }); > }); > }); > }); > }).get(); > registry.stop(); > {code} > where polymorphic schemas are defined as follows: > {code:java} > @ConfigurationRoot(rootName = "third") > public static class ThirdRootConfigurationSchema { > @NamedConfigValue > public EntityConfigurationSchema entity; > } > @Config > public static class EntityConfigurationSchema { > @NamedConfigValue > public FirstPolymorphicConfigurationSchema polymorphicConfig; > } > @PolymorphicConfig > public static class FirstPolymorphicConfigurationSchema { > /** Polymorphic type id field. */ > @PolymorphicId > public String typeId; > @Value > public String name; > } > @PolymorphicConfigInstance("first0") > public static class First0PolymorphicConfigurationSchema extends > FirstPolymorphicConfigurationSchema { > @Value > public int test0; > } > @PolymorphicConfigInstance("first1") > public static class First1PolymorphicConfigurationSchema extends > FirstPolymorphicConfigurationSchema { > @Value > public long test1; > } > {code} > This example results in ClassCastException > {noformat} > java.util.concurrent.ExecutionException: > org.apache.ignite.configuration.ConfigurationChangeException: Failed to > change configuration > at > java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395) > at > java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999) > at > org.apache.ignite.internal.configuration.ConfigurationRegistryTest.testAAA(ConfigurationRegistryTest.java:140) > ... > Caused by: org.apache.ignite.configuration.ConfigurationChangeException: > Failed to change configuration > at > org.apache.ignite.internal.configuration.ConfigurationChanger.lambda$changeInternally$3(ConfigurationChanger.java:401) > ... > Caused by: java.lang.ClassCastException: class > org.apache.ignite.internal.configuration.First0PolymorphicConfigurationImpl > cannot be cast to class > org.apache.ignite.internal.configuration.DynamicConfiguration > (org.apache.ignite.internal.configuration.First0PolymorphicConfigurationImpl > is in unnamed module of loader > com.facebook.presto.bytecode.DynamicClassLoader @24313fcc; > org.apache.ignite.internal.configuration.DynamicConfiguration is in unnamed > module of loader 'app') > at > org.apache.ignite.internal.configuration.util.ConfigurationNotificationsUtil$2.visitNamedListNode(ConfigurationNotificationsUtil.java:625) > at > org.apache.ignite.internal.configuration.util.ConfigurationNotificationsUtil$2.visitNamedListNode(ConfigurationNotificationsUtil.java:563) > at > org.apache.ignite.internal.configuration.EntityNode.traverseChildren(Unknown > Source) > at > org.apache.ignite.internal.configuration.util.ConfigurationNotificationsUtil.notifyAnyListenersOnCreate(ConfigurationNotificationsUtil.java:563) > at > org.apache.ignite.internal.configuration.util.ConfigurationNotificationsUtil$1.visitNamedListNode(ConfigurationNotificationsUtil.java:298) > at > org.apache.ignite.internal.configuration.util.ConfigurationNotificationsUtil$1.visitNamedListNode(ConfigurationNotificationsUtil.java:139) > at > org.apache.ignite.internal.configuration.ThirdRootNode.traverseChildren(Unknown > Source) > at > org.apache.ignite.internal.configuration.util.ConfigurationNotificationsUtil.notifyListeners(ConfigurationNotificationsUtil.java:139) > at > org.apache.ignite.internal.configuration.util.ConfigurationNotificationsUtil.notifyListeners(ConfigurationNotificationsUtil.java:79) > at > org.apache.ignite.internal.configuration.ConfigurationRegistry$2.visitInnerNode(ConfigurationRegistry.java:283) > at > org.apache.ignite.internal.configuration.ConfigurationRegistry$2.visitInnerNode(ConfigurationRegistry.java:272) > at > org.apache.ignite.internal.configuration.SuperRoot.traverseChildren(SuperRoot.java:103) > at > org.apache.ignite.internal.configuration.ConfigurationRegistry.notificator(ConfigurationRegistry.java:272) > at > org.apache.ignite.internal.configuration.ConfigurationChanger.updateFromListener(ConfigurationChanger.java:484) > at > org.apache.ignite.internal.configuration.storage.TestConfigurationStorage.lambda$write$1(TestConfigurationStorage.java:115) > at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) > at > org.apache.ignite.internal.configuration.storage.TestConfigurationStorage.write(TestConfigurationStorage.java:115) > at > org.apache.ignite.internal.configuration.ConfigurationChanger.lambda$changeInternally0$7(ConfigurationChanger.java:444) > at > java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1072) > ... 8 more > {noformat} > In addition, the following incorrect configuration throws > NullPointerException. In my understanding, we need to throw something useful > instead of NPE. > {code:java} > ConfigurationRegistry registry = new ConfigurationRegistry( > List.of(ThirdRootConfiguration.KEY), > Map.of(), > new TestConfigurationStorage(LOCAL), > List.of(), > List.of( > First0PolymorphicConfigurationSchema.class, > First1PolymorphicConfigurationSchema.class)); > ... > registry.getConfiguration(ThirdRootConfiguration.KEY).change(c -> { > c.changeEntity(entity -> { > entity.create("new entity", upd -> { > upd.changePolymorphicConfig(p -> { > p.create("key", polymorphicChange -> { > polymorphicChange.changeName("entity name"); > }); > }); > }); > }); > }).get(); > {code} > {noformat} > Caused by: java.lang.NullPointerException > at > org.apache.ignite.internal.configuration.FirstPolymorphicNode.schemaType(Unknown > Source) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.lambda$doVisitNamedListNode$0(ConfigurationFlattener.java:194) > at > org.apache.ignite.internal.configuration.util.KeysTrackingConfigurationVisitor.withTracking(KeysTrackingConfigurationVisitor.java:131) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.doVisitNamedListNode(ConfigurationFlattener.java:176) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.doVisitNamedListNode(ConfigurationFlattener.java:82) > at > org.apache.ignite.internal.configuration.util.KeysTrackingConfigurationVisitor.visitNamedListNode(KeysTrackingConfigurationVisitor.java:67) > at > org.apache.ignite.internal.configuration.EntityNode.traverseChildren(Unknown > Source) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.visitAsymmetricInnerNode(ConfigurationFlattener.java:248) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.lambda$doVisitNamedListNode$0(ConfigurationFlattener.java:193) > at > org.apache.ignite.internal.configuration.util.KeysTrackingConfigurationVisitor.withTracking(KeysTrackingConfigurationVisitor.java:131) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.doVisitNamedListNode(ConfigurationFlattener.java:176) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.doVisitNamedListNode(ConfigurationFlattener.java:82) > at > org.apache.ignite.internal.configuration.util.KeysTrackingConfigurationVisitor.visitNamedListNode(KeysTrackingConfigurationVisitor.java:67) > at > org.apache.ignite.internal.configuration.ThirdRootNode.traverseChildren(Unknown > Source) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.doVisitInnerNode(ConfigurationFlattener.java:146) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener$FlattenerVisitor.doVisitInnerNode(ConfigurationFlattener.java:82) > at > org.apache.ignite.internal.configuration.util.KeysTrackingConfigurationVisitor.visitInnerNode(KeysTrackingConfigurationVisitor.java:55) > at > org.apache.ignite.internal.configuration.SuperRoot.traverseChildren(SuperRoot.java:103) > at > org.apache.ignite.internal.configuration.util.ConfigurationFlattener.createFlattenedUpdatesMap(ConfigurationFlattener.java:52) > at > org.apache.ignite.internal.configuration.ConfigurationChanger.lambda$changeInternally0$4(ConfigurationChanger.java:425) > at > java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700) > ... 6 more > {noformat} -- This message was sent by Atlassian Jira (v8.20.1#820001)