Uploaded image for project: 'Magnolia'
  1. Magnolia
  2. MAGNOLIA-6378

Allow yaml based configuration to make use of groovy

XMLWordPrintable

    • Icon: Improvement Improvement
    • Resolution: Fixed
    • Icon: Major Major
    • 5.4.5
    • 5.4.2
    • configuration
    • Basel 28
    • 5

      I am not able to use groovy model classes in yaml based templates definitions.

      2015-09-15 12:31:42,701 WARN  agnolia.config.source.yaml.YamlConfigurationSource: Problem while registering TEMPLATE from LayeredResource{path='/workshop-module/templates/pages/hello.yaml', layeredResources=[FileSystemResource{origin=filesystem,path=/workshop-module/templates/pages/hello.yaml,file}]}: Conversion: Error converting from 'String' to 'Class' info.magnolia.groovy.models.HelloModel
      org.apache.commons.beanutils.ConversionException: Error converting from 'String' to 'Class' info.magnolia.groovy.models.HelloModel
      	at org.apache.commons.beanutils.converters.AbstractConverter.handleError(AbstractConverter.java:282)
      	at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:177)
      	at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:61)
      	at org.apache.commons.beanutils.ConvertUtilsBean.convert(ConvertUtilsBean.java:491)
      	at org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:1000)
      	at info.magnolia.config.map2bean.Map2BeanTransformer.readOutObject(Map2BeanTransformer.java:184)
      	at info.magnolia.config.map2bean.Map2BeanTransformer.readComplexValue(Map2BeanTransformer.java:151)
      	at info.magnolia.config.map2bean.Map2BeanTransformer.readValue(Map2BeanTransformer.java:114)
      	at info.magnolia.config.map2bean.Map2BeanTransformer.toBean(Map2BeanTransformer.java:101)
      	at info.magnolia.config.source.yaml.YamlConfigurationSource.loadAndRegister(YamlConfigurationSource.java:94)
      	at info.magnolia.config.source.yaml.AbstractFileResourceConfigurationSource$LoadAndRegisterFunction.doWith(AbstractFileResourceConfigurationSource.java:132)
      	at info.magnolia.config.source.yaml.AbstractFileResourceConfigurationSource$LoadAndRegisterFunction.doWith(AbstractFileResourceConfigurationSource.java:113)
      	at info.magnolia.resourceloader.util.VoidFunction.apply(VoidFunction.java:49)
      	at info.magnolia.resourceloader.util.VoidFunction.apply(VoidFunction.java:46)
      	at info.magnolia.resourceloader.util.PredicatedResourceVisitor.visitFile(PredicatedResourceVisitor.java:117)
      	at info.magnolia.resourceloader.layered.RelayerResourceVisitor.visitFile(RelayerResourceVisitor.java:61)
      	at info.magnolia.resourceloader.file.VisitorFunction.apply(VisitorFunction.java:58)
      	at info.magnolia.resourceloader.file.VisitorFunction.apply(VisitorFunction.java:46)
      	at info.magnolia.resourceloader.file.FileWatcherCallback.doIt(FileWatcherCallback.java:78)
      	at info.magnolia.resourceloader.file.FileWatcherCallback.modified(FileWatcherCallback.java:66)
      	at info.magnolia.dirwatch.DirectoryWatcher.processEvent(DirectoryWatcher.java:247)
      	at info.magnolia.dirwatch.DirectoryWatcher.run(DirectoryWatcher.java:199)
      	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
      	at java.util.concurrent.FutureTask.run(FutureTask.java:262)
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
      	at java.lang.Thread.run(Thread.java:745)
      Caused by: java.lang.ClassNotFoundException: info.magnolia.groovy.models.HelloModel
      	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1858)
      	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1709)
      	at org.apache.commons.beanutils.converters.ClassConverter.convertToType(ClassConverter.java:104)
      	at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:169)
      	... 25 more
      

      CAUSE AND PROPOSED SOLUTION

      Basically in Map2Bean resolving model classes is delegated to BeanUtils which uses its default class converter org.apache.commons.beanutils.converters.ClassConverter. Code eventually ends up at ClassConverter.convertToType(..) where the context class loader for the current thread is not aware of Groovy classes and thus fails. One way to fix this could be adding a check at Map2BeanTransformer.readSimpleValue(Object, TypeDescriptor)

       private <T> T readSimpleValue(Object source, TypeDescriptor defaultTargetTypeDescriptor) throws ClassNotFoundException {
              // we need to convert classes here else org.apache.commons.beanutils.converters.ClassConverter (which isn't aware of Groovy classes) would be used and an exception thrown, e.g. in case of a Groovy class model. Basically we need to do here something similar to what is done at Node2BeanTransformerImpl.convertPropertyValue(..)  
              if (defaultTargetTypeDescriptor.getType().isAssignableFrom(Class.class)) {
                  return (T) Classes.getClassFactory().forName((String) source);
              }
              return (T) source;
          }
      

      One problem I see with this approach is that we throw CNFE which eventually must be thrown by the public API method Map2BeanTransformer.toBean(..) meaning not being binary compatible (unless we catch the exception and just log it or rethrow it wrapped in some exception already thrown by toBean(..))

        Acceptance criteria

              fgrilli Federico Grilli
              rgange Richard Gange
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved:

                  Task DoD

                    Estimated:
                    Original Estimate - Not Specified
                    Not Specified
                    Remaining:
                    Remaining Estimate - 0d
                    0d
                    Logged:
                    Time Spent - 0.5d
                    0.5d