OpenJPA
  1. OpenJPA
  2. OPENJPA-2227

OpenJPA doesn't find custom SequenceGenerators

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: 2.0.0, 2.1.0, 2.2.0
    • Fix Version/s: 2.1.2, 2.2.1, 2.3.0
    • Component/s: kernel
    • Labels:
      None
    • Environment:
      WebSphere Application Server V8.0 and V8.5

      Description

      I'm trying to use a custom SequenceGenerator within an enterprise application using openJPA (providing by WebSphere).

      When defining a custom Sequence a ClassNotFoundException (for the Sequence class) will be thrown when trying to insert data into the database.

      ExampleConfiguration:

      @Entity
      @SequenceGenerator(name="MySequence", sequenceName="org.apache.openjpa.generator.UIDGenerator()")
      public class Customer implements Serializable {
          @Id
          @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MySequence")
          private long id;
      

      The example will produce the stacktrace attached.

      It seems that the wrong class loader is used to instantiate the custom sequence class. A very similar issue seems to be: OPENJPA-758. With JavaSE (JUnit) all is working fine, but after deploying into WAS the Exception will occur.

      I think within the method SequenceMetaData.instantiate(Classloader envLoader) the JavaTypes.classForName() -method with parameter mustExist=false should be used instead of the pure Class.forName() call. But I'm not sure about the Metadata-parameter needed for this method call.

      1. ClassNotFoundException.txt
        3 kB
        Jens Leisenberg
      2. OPENJPA-2227-2.2.x.patch
        1 kB
        Jody Grassel

        Activity

        Jens Leisenberg created issue -
        Jens Leisenberg made changes -
        Field Original Value New Value
        Attachment ClassNotFoundException.txt [ 12535725 ]
        Jody Grassel made changes -
        Assignee Jody Grassel [ fyrewyld ]
        Jody Grassel made changes -
        Status Open [ 1 ] In Progress [ 3 ]
        Hide
        Jody Grassel added a comment -

        This problem doesn't show up in the JSE (which likely applies to JUnits) environment because the application ClassLoader would be the ClassLoader responsible for loading both the OpenJPA and JUnit/JSE application classes. In a JEE environment, you have a hierarchy of ClassLoaders - in the WebSphere case, OpenJPA would be loaded by one of the OSGi ClassLoaders, application code lives in Application ClassLoaders which are children of the OSGi ClassLoaders.

        When SequenceMetaData initializes, it attempts to perform a Class.forName() lookup for the class denoted in the sequenceName entry. However, it scopes the lookup to the ClassLoader responsible for loading the OpenJPA classes, so it would never be able to check child ClassLoaders for application-custom SequenceGenerators.

        Curiously, the SequenceMetaData.instantiate() method takes a ClassLoader envLoader argument (which, tracking back a couple frames in the stack trace, originates with a call to StoreContext.getClassloader() – which returns the Thread Context ClassLoader that was current when the StoreContext was created.) A modification to instantiate() to first perform the original Class.forName() lookup, falling back to a Class.forName() lookup using envLoader if the first call results in a ClassNotFoundException seems to resolve the issue in my test environment.

        Show
        Jody Grassel added a comment - This problem doesn't show up in the JSE (which likely applies to JUnits) environment because the application ClassLoader would be the ClassLoader responsible for loading both the OpenJPA and JUnit/JSE application classes. In a JEE environment, you have a hierarchy of ClassLoaders - in the WebSphere case, OpenJPA would be loaded by one of the OSGi ClassLoaders, application code lives in Application ClassLoaders which are children of the OSGi ClassLoaders. When SequenceMetaData initializes, it attempts to perform a Class.forName() lookup for the class denoted in the sequenceName entry. However, it scopes the lookup to the ClassLoader responsible for loading the OpenJPA classes, so it would never be able to check child ClassLoaders for application-custom SequenceGenerators. Curiously, the SequenceMetaData.instantiate() method takes a ClassLoader envLoader argument (which, tracking back a couple frames in the stack trace, originates with a call to StoreContext.getClassloader() – which returns the Thread Context ClassLoader that was current when the StoreContext was created.) A modification to instantiate() to first perform the original Class.forName() lookup, falling back to a Class.forName() lookup using envLoader if the first call results in a ClassNotFoundException seems to resolve the issue in my test environment.
        Hide
        Jody Grassel added a comment -

        Uploaded copy of the patch for 2.2.x, as integration for this branch needs to be delayed.

        Show
        Jody Grassel added a comment - Uploaded copy of the patch for 2.2.x, as integration for this branch needs to be delayed.
        Jody Grassel made changes -
        Attachment OPENJPA-2227-2.2.x.patch [ 12538556 ]
        Jody Grassel made changes -
        Status In Progress [ 3 ] Resolved [ 5 ]
        Fix Version/s 2.1.2 [ 12317142 ]
        Fix Version/s 2.3.0 [ 12319463 ]
        Fix Version/s 2.2.1 [ 12319943 ]
        Resolution Fixed [ 1 ]
        Jody Grassel made changes -
        Status Resolved [ 5 ] Closed [ 6 ]

          People

          • Assignee:
            Jody Grassel
            Reporter:
            Jens Leisenberg
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development