OpenJPA
  1. OpenJPA
  2. OPENJPA-1962

openjpa uses application ClassLoader for resolving BrokerFactory (revisited again)

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Invalid
    • Affects Version/s: 2.1.0
    • Fix Version/s: None
    • Component/s: None
    • Labels:

      Description

      Previous references to the "The named BrokerFactory 'org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory' is not valid." exception thrown in Bootstrap.getFactoryClass() have applied to OSGi environments. We're having the same problem, although we are not using OSGi.

      Our environment may be a bit non-standard, but I think it is (or should be) a valid use case. It is also possible that I'm missing a classloader subtlety, but I don't think so.

      We developed a very simple application that uses openjpa to insert a couple items into a database. We jar the application, including the openjpa-all-2.1.0.jar, and deploy it on a webserver. We then use a URLClassLoader from a host program to access a class from this jar. For example, in the host program:

      URLClassLoader loader = new URLClassLoader(new URL[]

      {new URL(URL_OF_JAR)}

      , this.getClass().getClassLoader());
      Class<Runnable> clazz = (Class<Runnable>) loader.loadClass("test.CustomerTestRunner");
      clazz.newInstance().run();

      The application accessing the jar on the webserver knows nothing about openjpa. The test.CustomerTestRunner uses openjpa to create and persist a couple entities. This causes the error:
      Exception in thread "main" javax.persistence.PersistenceException: Explicit persistence provider error(s) occurred for "testjpa" after trying the following discovered implementations: org.apache.openjpa.persistence.PersistenceProviderImpl from provider: org.apache.openjpa.persistence.PersistenceProviderImpl

      which is ultimately caused by

      Caused by: java.lang.ClassNotFoundException: org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory
      at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
      at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:247)
      at org.apache.openjpa.kernel.Bootstrap.getFactoryClass(Bootstrap.java:164)
      ... 11 more

      Putting the jar directly on the classpath fixes the problem, but defeats the purpose.

        Activity

        Hide
        Joshua Shrader added a comment -

        Sorry... this isn't a bug. It was a problem with the classloader and JNDI, as explained here http://download.oracle.com/javase/jndi/tutorial/beyond/misc/classloader.html.

        For future reference, my chunk of code really needs to be
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        URLClassLoader loader = new URLClassLoader(new URL[]

        {new URL(URL_OF_JAR)}

        , this.getClass().getClassLoader());
        try

        { Thread.currentThread().setContextClassLoader(loader); Class<Runnable> clazz = (Class<Runnable>) loader.loadClass("test.CustomerTestRunner"); clazz.newInstance().run(); }

        finally

        { Thread.currentThread().setContextClassLoader(contextClassLoader); }
        Show
        Joshua Shrader added a comment - Sorry... this isn't a bug. It was a problem with the classloader and JNDI, as explained here http://download.oracle.com/javase/jndi/tutorial/beyond/misc/classloader.html . For future reference, my chunk of code really needs to be ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); URLClassLoader loader = new URLClassLoader(new URL[] {new URL(URL_OF_JAR)} , this.getClass().getClassLoader()); try { Thread.currentThread().setContextClassLoader(loader); Class<Runnable> clazz = (Class<Runnable>) loader.loadClass("test.CustomerTestRunner"); clazz.newInstance().run(); } finally { Thread.currentThread().setContextClassLoader(contextClassLoader); }

          People

          • Assignee:
            Unassigned
            Reporter:
            Joshua Shrader
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development