JDBC/OSGi 以及如何动态加载驱动程序而无需在捆绑包中显式声明依赖项?
这是一件大事。
我有一个结构良好但整体的代码库,它具有原始的模块化架构(所有模块都实现接口但共享相同的类路径)。当我在可能具有不同冲突版本的库的应用程序服务器上进行部署时,我意识到这种方法的愚蠢之处以及它所代表的问题。
我现在依赖大约 30 个罐子,并且正在将它们捆绑起来。现在我的一些模块很容易声明其版本依赖项,例如我的网络组件。它们静态引用 JRE 和其他 BNDded 库中的类,但我的 JDBC 相关组件通过 Class.forName(...) 实例化,并且可以使用任意数量的驱动程序之一。
我将按服务区域将所有内容分解为 OSGi 包。
- 我的核心类/接口。
- 报告相关组件。
- 数据库访问相关组件(通过 JDBC)。
- 等等......
我希望我的代码仍然能够在没有 OSGi 的情况下通过具有所有依赖项的单个 jar 文件使用,并且根本不需要 OSGi(通过 JARJAR),并且还可以通过 OSGi 元数据和粒度包进行模块化带有依赖信息。
如何配置我的捆绑包以及 我的代码,这样它就可以 动态利用任何驱动程序 类路径和/或 OSGi 内 容器环境 (Felix/Equinox/等)?
是否有一个运行时方法来检测我是否在跨容器(Felix/Equinox/等)兼容的 OSGi 容器中运行?
如果我在 OSGi 容器中,我是否需要使用不同的类加载机制?
我是否需要将 OSGi 类导入到我的项目中才能通过我的数据库模块加载捆绑时未知的 JDBC 驱动程序?
我还有第二种获取驱动程序的方法(通过 JNDI,这仅在应用服务器中运行时才真正适用),我是否需要更改 OSGi 感知应用服务器的 JNDI 访问代码?
This is a biggie.
I have a well-structured yet monolithic code base that has a primitive modular architecture (all modules implement interfaces yet share the same classpath). I realize the folly of this approach and the problems it represents when I go to deploy on application servers that may have different conflicting versions of my library.
I'm dependent on around 30 jars right now and am mid-way though bnding them up. Now some of my modules are easy to declare the versioned dependencies of, such as my networking components. They statically reference classes within the JRE and other BNDded libraries but my JDBC related components instantiate via Class.forName(...) and can use one of any number of drivers.
I am breaking everything up into OSGi bundles by service area.
- My core classes/interfaces.
- Reporting related components.
- Database access related components (via JDBC).
- etc....
I wish for my code to be able to still be used without OSGi via single jar file with all my dependencies and without OSGi at all (via JARJAR) and also to be modular via the OSGi meta-data and granular bundles with dependency information.
How do I configure my bundle and
my code so that it can
dynamically utilize any driver on the
classpath and/or within the OSGi
container environment
(Felix/Equinox/etc.)?Is there a run-time method to detect if I am running in an OSGi container that is compatible across containers (Felix/Equinox/etc.) ?
Do I need to use a different class loading mechanism if I am in a OSGi container?
Am I required to import OSGi classes into my project to be able to load an at-bundle-time-unknown JDBC driver via my database module?
I also have a second method of obtaining a driver (via JNDI, which is only really applicable when running in an app server), do I need to change my JNDI access code for OSGi-aware app servers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一个简单的示例片段:
只要确保如果将此代码放入包中,该包应该导入 org.osgi.framework (否则它将永远找不到该类)。
A simple example snippet:
Just make sure that you if you put this code in a bundle, the bundle should import org.osgi.framework (otherwise it will never find that class).
我在 Eclipse RCP 中为 OSGI 制作了一个 JDBC 驱动程序管理器,我将带您了解如何很好地使用 OSGI。首先,忘记 DynamicImport-Package,使用 OSGI 的唯一好方法是安装/启动/停止捆绑包并按照设计方式使用 OSGI 机制。
您拥有 JDBC 捆绑包,并创建另一个“驱动程序捆绑包”,其中包含 DriverClass 的初始化、连接逻辑并添加必要的公共库,例如 dbcp2 和 pool2。
将驱动程序包导出为 JAR/ZIP 并将其作为资源包含在您的 JDBC 包中。
让您的 JDBC 包将驱动程序包解压缩到其工作区域中。
以编程方式添加驱动程序 jar 并相应地修改驱动程序包的 MANIFEST.MF 文件。
以编程
从工作区以编程方式加载驱动程序包
以编程方式修改驱动程序列表时,根据需要使用bundle.start()、stop()、uninstall()。
I made a JDBC driver manager for OSGI in an Eclipse RCP and I will take you through how to play nice with OSGI. First, forget about DynamicImport-Package, the only good way to use OSGI is to install/start/stop bundles and use the OSGI mechanism the way it was designed.
You have your JDBC bundle, and create another "Driver bundle" which has the initialization of the DriverClass, the Connection logic and add the necessary commons libraries such as dbcp2 and pool2.
Export the Driver bundle as a JAR/ZIP and include it in your JDBC bundle as a resource.
Let your JDBC bundle unzip the Driver bundle in its work area.
Programmatically add driver jars and modify the Driver bundle's MANIFEST.MF file accordingly.
Load the Driver bundle programmatically from the work area
Use bundle.start(), stop(), uninstall() as necessary when programmatically modifying the list of drivers.
pax-jdbc 可用于通过声明方式委托数据源,这意味着您可以在 ConfigAdmin 服务中创建配置条目,并且可以通过 JNDI 访问数据源。 JDBC 驱动程序作为捆绑包进行部署。 (大多数都有 OSGi 版本)
例如:
配置条目 PID 是 org.ops4j.datasource-test
属性:
服务由给定的 dataSourceName 标识。因此,您可以使用 (&(objectClass=javax.sql.DataSource)(dataSourceName=test2)) 对其进行过滤。
您可以通过 JNDI 访问数据源:
The pax-jdbc can be used to delegate dataSources via declarative way, means you can create a config entry in ConfigAdmin service, and the dataSource can be accessed via JNDI. The JDBC driver is deployed as bundle. (most of them have OSGi version)
For example:
The config entry PID is org.ops4j.datasource-test
Properties:
The service is identified by the given dataSourceName. So you can filter for it with (&(objectClass=javax.sql.DataSource)(dataSourceName=test2)).
And you can access the datasource via JNDI: