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

时间:2013-10-22 17:27:58

标签: java spring osgi jdo datanucleus

我正在使用JDO与datanucleus-mongodb 3.2.3和spring 3.0.7在karaf 2.2.10之上。

在新的OSGi软件包安装上,我能够毫无问题地在mongodb上保留,但在重新安装软件包后,我在构建新的JDO PersistenceManagerFactory时出现以下错误:

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

ID(242)引用捆绑的第一个分配ID(换句话说,旧捆绑的ID)。

上一个bundle的上下文似乎已正确关闭,以及“旧”JDO PersistenceManagerFactory。

我的本​​地持久性管理器工厂bean类(基于example provided in the dn site):

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;
    }
}

一些持久性与上下文摘录相关:

<!-- 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 />

错误消息似乎指向了类加载问题,但是,为什么它只在重新部署期间失败?

任何提示都将不胜感激!

2 个答案:

答案 0 :(得分:2)

确保您还刷新了依赖捆绑包,因为这些捆绑包通常会粘贴到旧的已卸载捆绑包中。它仍然存在,直到所有引用被清除。 在Karaf shell中,您只需要在没有ID的情况下发出刷新或简单刷新,这将导致整个容器重新布线:)

答案 1 :(得分:0)

对于那些无法简单刷新javax.jdo的用户,请确保在重新创建ClassLoader时重新创建自定义PersistenceManagerFactory。如果Datanucleus未更改,ClassLoader将不会尝试两次加载同一个类。您最终会ClassCastExceptionsEntity.class无法投放到Entity.class