2013-09-25 27 views
0

我試圖在儘可能多的模塊化的OSGi環境(卡拉夫運行費利克斯)做持久性。我選擇了JDO來增加它的功能(主要是提取組),而不是JPA。實現是Datanucleus。我使用Maven構建整個項目。在使用Datanucleus JDO和藍圖的OSGi環境中的持久性

因爲我之前沒有任何JDO或OSGi的經驗,所以使它們中的任何一個都工作是一個相當大的挑戰。我目前能夠在Java SE環境中執行JDO持久化(單元測試工作沒有問題),並且我知道如何使用藍圖容器在OSGi環境中提供服務。但我無法讓這兩件事情一起工作。我有班加載問題。我無法構建一個簡單的應用程序,它能夠在Karaf上執行JDO持久化(我嘗試了下面的this tutorial,但它使用了Spring DM,我無法改寫它來使用OSGi藍圖)。

我現在最困惑的是:

  • 什麼樣的價值,我應該設置datanucleus.primaryClassLoader屬性?
  • 什麼類加載器作爲參數傳遞給JDOHelper.getPersistenceManagerFactory方法?
  • 什麼軟件包明確導入使用maven-bundle-plugin? (貌似至少javax.jdoorg.datanucleus.api.jdoorg.osgi.framework可能需要)
  • 做其他的包需要對之外的PersistenceManagerFactory 一個參考什麼?

此外:

  • 是否有可能獨立於價值類持久性的信息?如果我理解正確,那麼只有使用運行時增強纔是可能的,如果可行的話,這將會非常複雜。
  • 是否有可能在多個bundle中定義相互依賴的持久性能力類?如將用戶定義在一個包中,並在另一個包中定義地址?

我將非常感謝一個簡單的多包項目的例子,該項目只使用Datanucleus,JDO API和OSGi藍圖來實現持久性。

謝謝

回答

0

我只能提供有關獲取JDO/DataNucleus將到Karaf基礎上工作的一些基本提示。

正如本教程所指出的那樣,您需要擴展LocalPersistenceManagerFactoryBean,實現以及​​接口。

這裏的關鍵是類加載:LocalPersistenceManagerFactoryBean期望所有的類都被一個類加載器加載,而在OSGi運行時則不是這種情況。

爲了得到它的工作,你將需要:

  1. 在您的清單文件中明確導入org.datanucleus.api.jdo
  2. datanucleus.primaryClassLoader屬性可以設置爲你傳遞給JDOHelper.getPersistenceManagerFactory方法相同的類加載器。類加載器是org.datanucleus.api.jdo包使用的類加載器(請參見下面的示例)
  3. 您需要將datanucleus.plugin.pluginRegistryClassName屬性設置爲org.datanucleus.plugin.OSGiPluginRegistry
  4. 停止時/卸載你的包,你必須刷新javax.jdo包,以避免當重新創建持久性管理器工廠(關於這個問題的檢查this question

的樣本定製LocalPersistenceManagerFactoryBean錯誤:

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 { // on Java runtime 
      classLoader = this.getClass().getClassLoader(); 
     } 
     return classLoader; 
    } 

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

感謝。我會看看。 – binarek

+0

另請注意,所有數據包必須在啓動捆綁包時啓動。如果不這樣,則會在OSGIPluginRegistry中給出錯誤(NullPointerException)。 –

相關問題