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

Posted

技术标签:

【中文标题】jdo/OSGi:捆绑更新后构建 JDO PersistenceManagerFactory 时出错【英文标题】:jdo/OSGi: error building JDO PersistenceManagerFactory after bundle update 【发布时间】:2013-10-31 17:12:11 【问题描述】:

我在 karaf 2.2.10 之上使用带有 datanucleus-mongodb 3.2.3 和 spring 3.0.7 的 JDO。

在全新的 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)。

前一个包的上下文似乎已正确关闭,“旧”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 />

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

任何提示将不胜感激!

【问题讨论】:

【参考方案1】:

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

【讨论】:

谢谢阿奇姆。实际上只需刷新 javax.jdo 捆绑包即可解决问题!【参考方案2】:

对于那些不能简单地刷新javax.jdo 的用户,请确保在重新创建PersistenceManagerFactory 的同时重新创建自定义ClassLoader。如果ClassLoader 没有改变,Datanucleus 不会尝试加载同一个类两次。你最终会让ClassCastExceptionsEntity.class 不能转换为Entity.class

【讨论】:

以上是关于jdo/OSGi:捆绑更新后构建 JDO PersistenceManagerFactory 时出错的主要内容,如果未能解决你的问题,请参考以下文章

由于捆绑包 ID,iPhone 应用程序更新无法验证

XCode 4.4 捆绑包版本更新直到后续构建才获得

对于基于(以前免费的)App Engine 构建的 Java/JDO 应用程序,有啥更实惠的托管选项? [关闭]

传递 iOS 应用更新时出错。 “此捆绑包无效。Apple 目前不接受使用此版本 SDK 构建的应用程序。”

传递 iOS 应用更新时出错。 “此捆绑包无效。Apple 目前不接受使用此版本 SDK 构建的应用程序。”

有没有办法在构建完成后将捆绑资源复制到应用程序文件夹?