Uploaded image for project: 'Spring Data Commons'
  1. Spring Data Commons
  2. DATACMNS-1422

ClassGeneratingPropertyAccessorFactory needs custom ClassLoader for defineClass()

    XMLWordPrintable

    Details

      Description

      The ClassGeneratingPropertyAccessorFactory fails to generate classes in an OSGi environment, where the ClassLoader for the model project, the store implementation and Spring Data is different. Here is the error we are facing:

      java.lang.RuntimeException: java.lang.IllegalStateException: org.springframework.cglib.core.CodeGenerationException: java.lang.NoClassDefFoundError-->org/springframework/data/mapping/PersistentPropertyAccessor
      	at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.createAccessorClass(ClassGeneratingPropertyAccessorFactory.java:197)
      	at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.potentiallyCreateAndRegisterPersistentPropertyAccessorClass(ClassGeneratingPropertyAccessorFactory.java:181)
      	at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.getPropertyAccessor(ClassGeneratingPropertyAccessorFactory.java:91)
      	at org.springframework.data.mapping.model.BasicPersistentEntity.getPropertyAccessor(BasicPersistentEntity.java:455)
      	at com.example.storeimpl.CustomEntityConverter.read(Unknown Source)
      [...]
      Caused by: java.lang.IllegalStateException: org.springframework.cglib.core.CodeGenerationException: java.lang.NoClassDefFoundError-->org/springframework/data/mapping/PersistentPropertyAccessor
      	at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.generateCustomAccessorClass(ClassGeneratingPropertyAccessorFactory.java:323)
      	at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.createAccessorClass(ClassGeneratingPropertyAccessorFactory.java:195)
      	... 61 common frames omitted
      Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.NoClassDefFoundError-->org/springframework/data/mapping/PersistentPropertyAccessor
      	at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:526)
      	at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.generateCustomAccessorClass(ClassGeneratingPropertyAccessorFactory.java:321)
      	... 62 common frames omitted
      Caused by: java.lang.NoClassDefFoundError: org/springframework/data/mapping/PersistentPropertyAccessor
      	at java.lang.ClassLoader.defineClass1(Native Method)
      	at java.lang.ClassLoader.defineClass(Unknown Source)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      	at java.lang.reflect.Method.invoke(Unknown Source)
      	at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:523)
      	... 63 common frames omitted
      Caused by: java.lang.ClassNotFoundException: org.springframework.data.mapping.PersistentPropertyAccessor cannot be found by custom-model_1.2.3
      	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:511)
      	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
      	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:414)
      	at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:153)
      	at java.lang.ClassLoader.loadClass(Unknown Source)
      	... 70 common frames omitted
      

      The problem seems to be that PropertyAccessorClassGenerator.generateBytecode() adds the interface PersistentPropertyAccessor which lives in Spring Data. In generateCustomAccessorClass() the ClassLoader of the model entity is used. Therefore the ClassLoader of the custom model project needs access to all classes which are added by the factory (especially the package org.springframework.data.mapping).

      To resolve this problem, a child ClassLoader of the entity should be used that is able to access both projects: Spring Data and the custom entity model. Else this has to fail because different classes are mixed which cannot be accessed by a single ClassLoader.

        Attachments

          Activity

            People

            Assignee:
            mp911de Mark Paluch
            Reporter:
            raap Daniel Raap
            Last updater:
            Mark Paluch
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: