You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RCP集成BIRT 4.13:Rhino脚本如何加载其他OSGi Bundle类?

问题描述

在基于Java 17的2023-09版本RCP应用中集成4.13版本BIRT报表引擎,需求是Bundle B向包含报表引擎的Bundle R提交rptdesign文件。Bundle B的报表脚本中使用了该Bundle内的myapp.mech.model.Dao类,且该类所在包已由Bundle B导出。

当前在Bundle R中设置类加载器的代码如下:

Bundle bundle = org.eclipse.core.runtime.Platform.getBundle(getBundleIdFromUrl(reportDesign));
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
config.getAppContext().put(EngineConstants.APPCONTEXT_CLASSLOADER_KEY, bundleWiring.getClassLoader());
config.getAppContext().put(EngineConstants.APPCONTEXT_DATASET_CACHE_OPTION, Boolean.FALSE.toString());
config.getAppContext().put(EngineConstants.REFRESH_DATA, Boolean.TRUE.toString());

IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
engine = factory.createReportEngine(config);

执行报表脚本时出现类未找到错误:

A BIRT exception occurred. See next exception for more information.
TypeError: [JavaPackage myapp.mech.model.Dao] is not a function, it is object. (/report/data-sets/script-data-set[@id="411"]/method[@name="open"]#1)
org.eclipse.birt.data.engine.core.DataException: Fail to execute script in function __bm_OPEN(). Source:
------
" + model = new Packages.myapp.mech.model.Dao();

注:Bundle R内的报表可正常运行

解决方案

针对该类加载问题,可从以下方向调整:

1. 调整类加载器设置时机

当前在创建引擎时设置类加载器,可尝试在加载报表设计文件后,为ReportDesignHandle单独设置类加载器:

// 获取reportDesignHandle后添加
reportDesignHandle.getModuleHandle().setClassLoader(bundleWiring.getClassLoader());

2. 使用复合类加载器

OSGi环境下单独用Bundle B的类加载器可能无法访问BIRT引擎自身类,需构建包含Bundle B和Bundle R类加载器的复合加载器:

ClassLoader bundleBClassLoader = bundleWiring.getClassLoader();
ClassLoader bundleRClassLoader = getClass().getClassLoader();
ClassLoader compositeClassLoader = new ClassLoader(bundleRClassLoader) {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            return bundleBClassLoader.loadClass(name);
        } catch (ClassNotFoundException e) {
            return super.findClass(name);
        }
    }
};
config.getAppContext().put(EngineConstants.APPCONTEXT_CLASSLOADER_KEY, compositeClassLoader);

3. 检查OSGi包配置

  • 确认Bundle B的MANIFEST.MF正确导出目标包,且范围覆盖Bundle R:
    Export-Package: myapp.mech.model;version="1.0.0"
    
  • 确认Bundle R的MANIFEST.MF已导入该包:
    Import-Package: myapp.mech.model;version="[1.0.0,2.0.0)"
    

4. 调整脚本类引用方式

尝试去掉Packages前缀直接引用类:

model = new myapp.mech.model.Dao();

5. 验证类加载器有效性

设置类加载器前先验证能否加载目标类,排除类路径问题:

try {
    Class<?> daoClass = bundleBClassLoader.loadClass("myapp.mech.model.Dao");
    System.out.println("成功加载类:" + daoClass.getName());
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

内容的提问来源于stack exchange,提问作者paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:42:55