JDBC / OSGi以及如何动态加载驱动程序而不明确说明bundle中的依赖项?

时间:2010-04-25 08:06:21

标签: java jdbc osgi modularity

这是一个很大的问题。

我有一个结构良好但单片的代码库,它具有原始的模块化架构(所有模块实现接口但共享相同的类路径)。我意识到这种方法的愚蠢以及当我在可能具有不同冲突版本的库的应用程序服务器上进行部署时它所代表的问题。

我现在依赖于大约30个罐子而且在中途将它们收起来。现在,我的一些模块很容易声明版本化的依赖关系,例如我的网络组件。它们静态引用JRE和其他BNDded库中的类,但我的JDBC相关组件通过Class.forName(...)实例化,并且可以使用任意数量的驱动程序之一。

我正在通过服务区将所有内容分解为OSGi包。

  • 我的核心课程/接口。
  • 报告相关组件。
  • 数据库访问相关组件(通过JDBC)。
  • 等...

我希望我的代码能够在没有OSGi的情况下通过单个jar文件使用我的所有依赖项并且根本没有OSGi(通过JARJAR),也可以通过OSGi元数据和具有依赖性的粒度包进行模块化信息。

  • 如何配置我的捆绑包和 我的代码,所以它可以 动态利用上的任何驱动程序 classpath和/或在OSGi中 集装箱环境 (菲利克斯/春分/等)?

  • 是否有运行时方法来检测我是否在跨容器兼容的OSGi容器中运行(Felix / Equinox / etc。)?

  • 如果我在OSGi容器中,是否需要使用不同的类加载机制?

  • 我是否需要将OSGi类导入到我的项目中,以便能够通过我的数据库模块加载at-bundle-time-unknown JDBC驱动程序?

  • 我还有第二种获取驱动程序的方法(通过JNDI,只在app服务器上运行时才真正适用),我是否需要更改支持OSGi的应用服务器的JNDI访问代码?< / p>

3 个答案:

答案 0 :(得分:7)

  • 在OSGi环境中使用任何驱动程序都需要使用DynamicImport-Package:*语句,以便在使用Class.forName(..)加载驱动程序时,bundle可以解析这些包。
  • 可能最简单的方法是尝试访问org.osgi.framework包中的类。这些至少应该始终在OSGi环境中(参见下面的代码片段)。有更复杂的机制,所以如果你需要更先进的东西,请告诉我。另外,请看一下OSGi R4.2核心规范,第3.8.9节,其中显示了查找类的Bundle和BundleContext的一些方法,因此间接有助于确定您是否在框架中。
  • 这取决于你在做什么,这里没有通用的“是”或“否”答案。 OSGi使用类加载器,并且这种方式对于标准Java应用程序来说不是“典型”,但是根据您正在做的事情,您可能不会注意到。
  • 没有
  • 看看最近发布的OSGi企业规范。他们在OSGi中有一章关于JNDI集成,它可能允许你(很大程度上)不修改你的代码。

一个简单的示例摘录:

 public static boolean inOSGi() {
  try {
   Class.forName("org.osgi.framework.FrameworkUtil");
   return true;
  }
  catch (ClassNotFoundException e) {
   return false;
  }
 }

如果你把这个代码放在一个包中,请确保你输入org.osgi.framework(否则它永远不会找到那个类)。

答案 1 :(得分:0)

我在Eclipse RCP中为OSGI创建了一个JDBC驱动程序管理器,我将带您了解如何使用OSGI。首先,忘记DynamicImport-Package,使用OSGI的唯一好方法是安装/启动/停止捆绑包并按照设计的方式使用OSGI机制。

  1. 你有你的JDBC包,并创建另一个&#34;驱动程序包&#34;它具有DriverClass的初始化,连接逻辑并添加必要的公共库,如dbcp2和pool2。

  2. 将驱动程序包导出为JAR / ZIP并将其作为资源包含在JDBC包中。

  3. 让您的JDBC包在其工作区中解压缩Driver包。

    String workdir= Platform.getStateLocation(jdbc_bundle).toPortableString();
    
  4. 以编程方式添加驱动程序jar并相应地修改Driver bundle的MANIFEST.MF文件。

  5. 以编程方式从工作区

    加载驱动程序包
    getBundleContext().installBundle("file:/"+workdir);
    
  6. 在以编程方式修改驱动程序列表时,根据需要使用bundle.start(),stop(),uninstall()。

答案 2 :(得分:0)

pax-jdbc可用于通过声明方式委托dataSource,这意味着您可以在ConfigAdmin服务中创建配置条目,并且可以通过JNDI访问dataSource。 JDBC驱动程序部署为bundle。 (大多数都有OSGi版本)

例如:

配置条目PID是org.ops4j.datasource-test

属性:

osgi.jdbc.driver.name=H2
databaseName=test
user=sa
password=
dataSourceName=testds-h2

服务由给定的dataSourceName标识。所以你可以用(&amp;(objectClass = javax.sql.DataSource)(dataSourceName = test2))过滤它。

您可以通过JNDI访问数据源:

osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=test2)