RCP应用程序

时间:2018-04-19 20:59:13

标签: java osgi eclipse-rcp

要点: 我在OSGi包中看到OSGi环境中运行时可用的类。

上下文 我的RCP应用程序将对象存储到磁盘,其中涉及存储每个对象的类名。想法是在加载时,将使用写入磁盘的类名重新实例化对象。主AppBundle执行存储操作。存储的对象中包括由其他包提供的类型的对象,例如Bundle1Bundle2

问题: 当我尝试基于存储的名称读取类信息时,尽管OSGi运行时中包含相同的bundle及其提供的类,但是我的AppBundle中看不到类信息。我已经包含了处理存储和读取的代码示意图。

public class Storage{
    transient Object[] objs = new Object[3];

    {
        // Something link the following happens dynamically during the application
        objs[0] = new AppBundleClass();
        objs[1] = new Bundle1Class();
        objs[2] = new Bundle2Class();
    }

    // Persisted to disk
    private String[] objTypes;

    public void saveToDisk(){
        objTypes = new String[objs.length];
        for (int i = 0; i < objTypes.length; i++)
            objTypes[i] = objs[i].getClass().getCanonicalName();
    }

    public void afterLoadingFromDisk(){
        objs = new Object[objTypes.length];
        for (int i = 0; i < objs.length; i++){
            Class<?> klass = Class.forName(objTypes[i]);
            // **** Throws error above ****

            objs = loadByClass(klass);      
            // Custom method that works for classes withing the app.
        }
    }
}

AppBundleBundle1Bundle2没有构建依赖关系。这个想法是应用程序的用户可以在运行时根据需要激活不同的包。

尝试解决方案: 我怀疑问题与OSGi为每个包使用不同的类加载器以及AppBundle的类加载器无法解析Bundle1Class有关,因为它不是通过指定的编译时依赖性bundle-dependencies或包导入。所以,我尝试了以下内容。

Bundle1/MANIFEST.MF
   DynamicImport-Package: *
   (to allow packages from this bundle to be dynamically visible)

AppBundle/MANIFEST.MF
    Eclipse-BuddyPolicy: global
    (to allow this bundle to be able to resolve any class available in the OSGi runtime)

预期行为 Bundle1Bundle2中的类现在应该对AppBundle可见。

实际行为 奇怪的是,时不时(相当随机),这是有效的。但是,大多数时候,我遇到了关于没有找到的课程的错误。

2 个答案:

答案 0 :(得分:2)

您不需要BuddyPolicy。只需确保Bundle1和Bundle2导出包,AppBundle具有DynamicImport-Package: *

请记住,这种方法只有在每个此类软件包仅由一个软件包导出时才有效。一般来说,通过类名识别一个类是OSGi中一个有缺陷的方法。

更好的方法是让每个bundle处理它知道的类并自己进行序列化。这也可以更好地匹配模块边界。

答案 1 :(得分:1)

我同意基督徒的观点,认为纯粹通过名字来确定一个课程是问题的根源,但会提供不同的解决方案。

在任何模块化环境中,类名称不足以标识类,因为多个包可以知道相同的名称。您的应用程序当前正在保存仅附加了类名的数据,因此只需更改此选项即可保存包标识由Bundle-SymbolicNameBundle-Version组成的类名和包ID。

加载时,使用Bundle-SymbolicNameBundle-Version查找匹配的Bundle对象,然后调用Bundle.loadClass(..)按名称加载类。

您不需要导出包含持久化类的包,也不需要将此包导入持久性框架包。