Uploaded image for project: 'Ignite'
  1. Ignite
  2. IGNITE-16056

Using polymorphic schema leads to ClassCastException

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Blocker
    • Resolution: Fixed
    • 3.0.0-alpha3
    • 3.0.0-alpha4
    • None

    Description

      Using polymorphic schema can lead to ClassCastException.
      Let's consider the following configuration example:

          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();
      

      where polymorphic schemas are defined as follows:

          @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;
          }
      

      This example results in ClassCastException

      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
      

      In addition, the following incorrect configuration throws NullPointerException. In my understanding, we need to throw something useful instead of NPE.

          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();
      
      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
      

      Attachments

        Issue Links

          Activity

            People

              ktkalenko@gridgain.com Kirill Tkalenko
              slava.koptilin Vyacheslav Koptilin
              Ivan Bessonov Ivan Bessonov
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 50m
                  50m