简体   繁体   English

jdo / OSGi:在更新捆绑包后构建JDO PersistenceManagerFactory时出错

[英]jdo/OSGi: error building JDO PersistenceManagerFactory after bundle update

I'm using JDO with datanucleus-mongodb 3.2.3 and spring 3.0.7 on top of karaf 2.2.10. 我正在使用JDO与datanucleus-mongodb 3.2.3和spring 3.0.7在karaf 2.2.10之上。

On a fresh OSGi bundle install I'm able to persist on mongodb without issues, but after a bundle reinstall, I get the following error while building a new JDO PersistenceManagerFactory: 在一个新的OSGi捆绑安装上,我能够在没有问题的情况下持久存在mongodb,但在重新安装捆绑包后,我在构建新的JDO PersistenceManagerFactory时出现以下错误:

ERROR: Bundle [my_bundle] [242] Unable to get module class path.
(java.lang.IllegalStateException: zip file closed)      

Where the ID (242) refers to the first assigned ID to the bundle (in other words, the ID of the old bundle). ID(242)指的是第一个分配给捆绑的ID(换句话说,旧捆绑的ID)。

The context of the previous bundle seems to be properly closed, as well as the "old" JDO PersistenceManagerFactory. 上一个bundle的上下文似乎已正确关闭,以及“旧”JDO PersistenceManagerFactory。

My local persistence manager factory bean class (based on the example provided in the dn site ): 我的本地持久性管理器工厂bean类(基于dn站点中提供示例 ):

public class OSGiLocalPersistenceManagerFactoryBean
    extends LocalPersistenceManagerFactoryBean implements BundleContextAware {

    public static final String JDO_BUNDLE_NAME    = "org.datanucleus.api.jdo";
    public static final String JDO_PMF_CLASS_NAME = "org.datanucleus.api.jdo.JDOPersistenceManagerFactory";

    private BundleContext bundleContext;

    @Override
    protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
        return JDOHelper.getPersistenceManagerFactory(name, getClassLoader());
    }

    @Override
    protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
        ClassLoader classLoader = getClassLoader();

        props.put("datanucleus.primaryClassLoader", classLoader);

        if (FrameworkUtil.getBundle(this.getClass()) != null) { // running in OSGi
            props.put("datanucleus.plugin.pluginRegistryClassName", "org.datanucleus.plugin.OSGiPluginRegistry");
        }

        PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props, classLoader);

        return pmf;
    }

    private ClassLoader getClassLoader() {
        ClassLoader classLoader = null;
        Bundle thisBundle = FrameworkUtil.getBundle(this.getClass());

        if (thisBundle != null) { // on OSGi runtime
            Bundle[] bundles = bundleContext.getBundles();

            for (Bundle bundle : bundles) {
                if (JDO_BUNDLE_NAME.equals(bundle.getSymbolicName())) {
                    try {
                        classLoader = bundle.loadClass(JDO_PMF_CLASS_NAME).getClassLoader();
                    } catch (ClassNotFoundException e) {
                        // do something fancy here ...
                    }
                    break;
                }
            }
        } else { // somewhere else
            classLoader = this.getClass().getClassLoader();
        }
        return classLoader;
    }

    @Override
    public void setBundleContext(BundleContext bundleContext) {
        this.bundleContext = bundleContext;
    }
}

Some persistence related excerpts from the context: 一些持久性相关的摘录来自上下文:

<!-- persistence manager factory -->
<bean id="pmf" class="[my_package].OSGiLocalPersistenceManagerFactoryBean">
    <property name="configLocation" value="classpath:datanucleus.properties" />
</bean>

<!-- persistence manager factory proxy -->
<bean id="persistenceManagerFactoryProxy"
      class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
    <property name="targetPersistenceManagerFactory" ref="pmf" />
</bean>

<!-- transactions -->
<bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
    <property name="persistenceManagerFactory" ref="persistenceManagerFactoryProxy" />
</bean>

<tx:annotation-driven />

The error message seems to point to a classloading issue, but then, why does it fail only during re-deployment? 错误消息似乎指向类加载问题,但是,为什么它只在重新部署期间失败?

Any hint would be appreciated! 任何提示将不胜感激!

Make sure you also refresh the depending bundles, cause those usually stick to the old uninstalled bundle. 确保您还刷新依赖捆绑包,因为这些捆绑包通常会粘贴到旧的已卸载捆绑包。 It's still there until all references are cleared. 它仍然存在,直到所有引用被清除。 In the Karaf shell you'll just need to issue refresh or simple refresh without the ID, this will cause the complete container to do a re-wiring :) 在Karaf shell中你只需要在没有ID的情况下发出刷新或简单刷新,这将导致整个容器重新连接:)

For those who cannot simply refresh javax.jdo make sure you recreate your custom ClassLoader while recreating the PersistenceManagerFactory . 对于那些不能简单刷新javax.jdo确保在重新创建PersistenceManagerFactory时重新创建自定义ClassLoader Datanucleus will not try to load the same class twice if the ClassLoader has not changed. 如果ClassLoader没有改变, Datanucleus将不会尝试加载相同的类两次。 You will end up having ClassCastExceptions saying Entity.class cannot be cast to Entity.class . 您最终会遇到ClassCastExceptionsEntity.class无法Entity.classEntity.class

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM