Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Persistence with JPF

2010-08-05
2013-05-02
  • Cobus Stroebel
    Cobus Stroebel
    2010-08-05

    Hi all

    I am trying to use toplink persistence with my java plugin framework application but I keep getting this error:

    javax.persistence.PersistenceException: No resource files named META-INF/services/javax.persistence.spi.PersistenceProvider were found. Please make sure that the persistence provider jar file is in your classpath.

    I have added the toplink-essentials.jar and toplink-essentials-agent.jar to my plugin.xml libraries and it does pick it up but not the META-INF of the jars.

    Please help.

     
  • Cobus Stroebel
    Cobus Stroebel
    2011-01-11

    Okay I've used a temporary workaround until now but it does not work in web applications.
    The toplink libraries use Thread.getContextClassLoader() which is not the plugin classloader and therefor gives the error for not finding the correct persistence provider. To solve this I changed the context classloader with:

    Thread.setContextClassLoader(pluginClassLoader);

    But in web applications I get an error when changing the classloader. Even when changing it back it still gives an error.
    Please can someone provide a solution.

     
  • Slychief
    Slychief
    2011-01-11

    You need to write your own classloader, that extends from the standard classloader and thus having all references to the libs provided in the classpath.

    public class PluginClassloader extends ClassLoader {
        private Set<ClassLoader> classloaders;
        public PluginClassloader(ClassLoader p) {
            super(p);
            classloaders = new HashSet<ClassLoader>();
        }
        public void addPluginClassloader(ClassLoader loader) {
            classloaders.add(loader);
        }
        public void removePluginClassloader(ClassLoader loader) {
            classloaders.remove(loader);
        }
        @Override
        public Class findClass(String name) throws ClassNotFoundException {
            Class result = null;
            try {
                result = super.findClass(name);
            } catch (ClassNotFoundException ex) {
            }
            if (result == null) {
                for (ClassLoader classLoader : classloaders) {
                    try {
                        result = classLoader.loadClass(name);
                    } catch (ClassNotFoundException ex) {
                    }
                }
            }
            if (result == null) {
                throw new ClassNotFoundException(name);
            }
            return result;
        }
    }
    

    In your main-class you instanciate the custom classloader and set it as the new Context classloader

    pClassloader = new PluginClassloader(Thread.currentThread().getContextClassLoader());
    Thread.currentThread().setContextClassLoader(pClassloader);
    

    Then you have to supply your custom classloader with the plugin classloaders:

    ClassLoader cl = pluginManager.getPluginClassLoader(descr);
    pClassloader.addPluginClassloader(cl);
    
     
  • Cobus Stroebel
    Cobus Stroebel
    2011-01-12

    Hi slychief

    Thanks alot for the reply. I have implemented your solution but I still get the error.
    The find class method is never called to obtain the persistence provider, neither is the find library nor the find resource.

    Unfortunately I don't have the source of JPA to see exactly how the persistence provider is obtained.
    Should I just implement all the methods similar to the find class or is there another way?

    Thanks for your help.

     
  • Slychief
    Slychief
    2011-01-12

    At the moment I don't have the time to explain it in detail, but I can give you some hints:

    Ejb3Configuration cfg = new Ejb3Configuration();
    cfg.addAnnotatedClass(Entity1.class);
    cfg.addAnnotatedClass(Entity2.class);
    cfg.addAnnotatedClass(...);
    // load entity classes from plugin
    for("Class p : pluginEntities") {
       cfg.addAnnotatedClass(p);
    }
    cfg.configure("name.of.persistence.unit", properties);
    EntityManagerFactory factory = cfg.buildEntityManagerFactory();
    // ...
    
     
  • Cobus Stroebel
    Cobus Stroebel
    2011-01-12

    Hi slychief

    Thanks alot! I have managed with the first solution. I obtained the toplink-essentials source and found that they were using the getResources method so I just implemented that in my classloader.

    Thanks again!

     
  • Cobus Stroebel
    Cobus Stroebel
    2011-01-12

    Aaaaaaaaahhh! =(

    Now I get a java.lang.LinkageError:
    Message: loader constraint violation in interface itable initialization: when resolving method "org.eclipse.persistence.jpa.PersistenceProvider.createContainerEntityManagerFactory(Ljavax/persistence/spi/PersistenceUnitInfo;Ljava/util/Map;)Ljavax/persistence/EntityManagerFactory;" the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader) of the current class, org/eclipse/persistence/jpa/PersistenceProvider, and the class loader (instance of com/sun/appserv/server/util/ASURLClassLoader) for interface javax/persistence/spi/PersistenceProvider have different Class objects for the type javax/persistence/spi/PersistenceUnitInfo used in the signature

    I think this is more a problem of Glassfish containing a library that also contains javax.persistence.spi.PersistenceUnitInfo

    Will this be solved if I try the other solution?

     
  • Cobus Stroebel
    Cobus Stroebel
    2011-01-27

    Hi All

    I have managed to get my persistence working. Seems all that was need was to move the persistence.xml file to WEB-INF/classes/META-INF/persistence.xml

    I have written my own class loader and adding all the plugin class loaders to it, but whenever I set it as the context class loader eg.

    <code>
    Thread.currentThread().setContextClassLoader(myClassLoader);
    </code>

    the persistence loads fine but I get an error with Faces Context Factory:

    <code>
    java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
            at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:256)
            at javax.faces.webapp.FacesServlet.init(FacesServlet.java:142)
            at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1194)
            at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1023)
            at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4917)
            at org.apache.catalina.core.StandardContext.start(StandardContext.java:5324)
            at com.sun.enterprise.web.WebModule.start(WebModule.java:353)
            at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:989)
            at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:973)
            at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:704)
            at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1627)
            at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1232)
            at com.sun.enterprise.server.WebModuleDeployEventListener.moduleDeployed(WebModuleDeployEventListener.java:182)
            at com.sun.enterprise.server.WebModuleDeployEventListener.moduleDeployed(WebModuleDeployEventListener.java:278)
            at com.sun.enterprise.admin.event.AdminEventMulticaster.invokeModuleDeployEventListener(AdminEventMulticaster.java:1005)
            at com.sun.enterprise.admin.event.AdminEventMulticaster.handleModuleDeployEvent(AdminEventMulticaster.java:992)
            at com.sun.enterprise.admin.event.AdminEventMulticaster.processEvent(AdminEventMulticaster.java:470)
            at com.sun.enterprise.admin.event.AdminEventMulticaster.multicastEvent(AdminEventMulticaster.java:182)
            at com.sun.enterprise.admin.server.core.DeploymentNotificationHelper.multicastEvent(DeploymentNotificationHelper.java:308)
            at com.sun.enterprise.deployment.phasing.DeploymentServiceUtils.multicastEvent(DeploymentServiceUtils.java:231)
            at com.sun.enterprise.deployment.phasing.ServerDeploymentTarget.sendStartEvent(ServerDeploymentTarget.java:298)
            at com.sun.enterprise.deployment.phasing.ApplicationStartPhase.runPhase(ApplicationStartPhase.java:132)
            at com.sun.enterprise.deployment.phasing.DeploymentPhase.executePhase(DeploymentPhase.java:108)
            at com.sun.enterprise.deployment.phasing.PEDeploymentService.executePhases(PEDeploymentService.java:966)
            at com.sun.enterprise.deployment.phasing.PEDeploymentService.start(PEDeploymentService.java:609)
            at com.sun.enterprise.deployment.phasing.PEDeploymentService.start(PEDeploymentService.java:653)
            at com.sun.enterprise.admin.mbeans.ApplicationsConfigMBean.start(ApplicationsConfigMBean.java:773)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at com.sun.enterprise.admin.MBeanHelper.invokeOperationInBean(MBeanHelper.java:381)
            at com.sun.enterprise.admin.MBeanHelper.invokeOperationInBean(MBeanHelper.java:364)
            at com.sun.enterprise.admin.config.BaseConfigMBean.invoke(BaseConfigMBean.java:477)
            at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:836)
            at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:761)
            at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at com.sun.enterprise.admin.util.proxy.ProxyClass.invoke(ProxyClass.java:90)
            at $Proxy1.invoke(Unknown Source)
            at com.sun.enterprise.admin.server.core.jmx.SunoneInterceptor.invoke(SunoneInterceptor.java:304)
            at com.sun.enterprise.interceptor.DynamicInterceptor.invoke(DynamicInterceptor.java:174)
            at com.sun.enterprise.deployment.client.DeploymentClientUtils.startApplication(DeploymentClientUtils.java:159)
            at com.sun.enterprise.deployment.client.DeployAction.run(DeployAction.java:538)
            at java.lang.Thread.run(Thread.java:662)
    </code>

    What am I doing wrong?

    Please help

     
  • Cobus Stroebel
    Cobus Stroebel
    2011-01-27

    By the way I am using glassfish v2.1