JDBC OSGI 礼宾服务中的 Oracle

JDBC Oracle in OSGI concierge

我需要一些线索如何使用 ojdbc8(我试过 ojdbc6,ojdbc7 也从来没有用过)部署为 OSGi Bundle,我可以加载class 使用 Class.load(),但是当 运行:

时出现以下错误
java.net.MalformedURLException: unknown protocol: bundle
    at java.net.URL.<init>(URL.java:421)
    at java.net.URL.<init>(URL.java:310)
    at java.net.URL.<init>(URL.java:333)
    at org.eclipse.concierge.BundleImpl$Revision.createURL(BundleImpl.java:2460)
    at org.eclipse.concierge.BundleImpl$JarBundleRevision.findFile(BundleImpl.java:3633)
    at org.eclipse.concierge.BundleImpl$JarBundleRevision.lookupFile(BundleImpl.java:3587)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findOwnResources(BundleImpl.java:3220)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource1(BundleImpl.java:2747)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource0(BundleImpl.java:2685)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource(BundleImpl.java:2541)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.getResource(BundleImpl.java:2517)
    at java.lang.ClassLoader.getResourceAsStream(ClassLoader.java:1307)
    at java.lang.Class.getResourceAsStream(Class.java:2223)
    at oracle.jdbc.driver.SQLStateMapping.doGetMappings(SQLStateMapping.java:208)
    at oracle.jdbc.driver.SQLStateMapping.getMappings(SQLStateMapping.java:194)
    at oracle.jdbc.driver.DatabaseError.<clinit>(DatabaseError.java:1075)
    at oracle.jdbc.driver.OracleDiagnosabilityMBean.getDescription(OracleDiagnosabilityMBean.java:96)
    at javax.management.StandardMBean.getMBeanInfo(StandardMBean.java:456)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getNewMBeanClassName(DefaultMBeanServerInterceptor.java:333)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:319)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522)
    at oracle.jdbc.driver.OracleDriver.registerMBeans(OracleDriver.java:409)
    at oracle.jdbc.driver.OracleDriver.run(OracleDriver.java:241)
    at java.security.AccessController.doPrivileged(Native Method)
    at oracle.jdbc.driver.OracleDriver.<clinit>(OracleDriver.java:237)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at java.sql.DriverManager.isDriverAllowed(DriverManager.java:556)
    at java.sql.DriverManager.getConnection(DriverManager.java:661)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at nz.co.spark.cg.shared.sql.SQLUtils.getDBConnection(SQLUtils.java:19)
    at nz.co.spark.cg.shared.sql.SQLUtils.createLocalDB(SQLUtils.java:29)
    at nz.co.spark.cg.extractor.task.ChatExtractorJob.<init>(ChatExtractorJob.java:61)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at org.quartz.simpl.SimpleJobFactory.newJob(SimpleJobFactory.java:56)
    at org.quartz.simpl.PropertySettingJobFactory.newJob(PropertySettingJobFactory.java:69)
    at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
    at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375)
java.net.MalformedURLException: unknown protocol: bundle
    at java.net.URL.<init>(URL.java:421)
    at java.net.URL.<init>(URL.java:310)
    at java.net.URL.<init>(URL.java:333)
    at org.eclipse.concierge.BundleImpl$Revision.createURL(BundleImpl.java:2460)
    at org.eclipse.concierge.BundleImpl$JarBundleRevision.findFile(BundleImpl.java:3633)
    at org.eclipse.concierge.BundleImpl$JarBundleRevision.lookupFile(BundleImpl.java:3587)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findOwnResources(BundleImpl.java:3220)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource1(BundleImpl.java:2747)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource0(BundleImpl.java:2685)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource(BundleImpl.java:2541)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.getResource(BundleImpl.java:2517)
    at java.lang.ClassLoader.getResourceAsStream(ClassLoader.java:1307)
    at java.util.ResourceBundle$Control.run(ResourceBundle.java:2686)
    at java.util.ResourceBundle$Control.run(ResourceBundle.java:2671)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.util.ResourceBundle$Control.newBundle(ResourceBundle.java:2670)
    at java.util.ResourceBundle.loadBundle(ResourceBundle.java:1510)
    at java.util.ResourceBundle.findBundle(ResourceBundle.java:1474)
    at java.util.ResourceBundle.findBundle(ResourceBundle.java:1428)
    at java.util.ResourceBundle.findBundle(ResourceBundle.java:1428)
    at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1370)
    at java.util.ResourceBundle.getBundle(ResourceBundle.java:782)
    at oracle.jdbc.driver.Message11.msg(Message11.java:36)
    at oracle.jdbc.driver.DatabaseError.findMessage(DatabaseError.java:939)
    at oracle.jdbc.driver.OracleDiagnosabilityMBean.getDescription(OracleDiagnosabilityMBean.java:96)
    at javax.management.StandardMBean.getMBeanInfo(StandardMBean.java:456)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getNewMBeanClassName(DefaultMBeanServerInterceptor.java:333)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:319)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522)
    at oracle.jdbc.driver.OracleDriver.registerMBeans(OracleDriver.java:409)
    at oracle.jdbc.driver.OracleDriver.run(OracleDriver.java:241)
    at java.security.AccessController.doPrivileged(Native Method)
    at oracle.jdbc.driver.OracleDriver.<clinit>(OracleDriver.java:237)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at java.sql.DriverManager.isDriverAllowed(DriverManager.java:556)
    at java.sql.DriverManager.getConnection(DriverManager.java:661)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at nz.co.spark.cg.shared.sql.SQLUtils.getDBConnection(SQLUtils.java:19)
    at nz.co.spark.cg.shared.sql.SQLUtils.createLocalDB(SQLUtils.java:29)
    at nz.co.spark.cg.extractor.task.ChatExtractorJob.<init>(ChatExtractorJob.java:61)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at org.quartz.simpl.SimpleJobFactory.newJob(SimpleJobFactory.java:56)
    at org.quartz.simpl.PropertySettingJobFactory.newJob(PropertySettingJobFactory.java:69)
    at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
    at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375)
java.net.MalformedURLException: unknown protocol: bundle
    at java.net.URL.<init>(URL.java:421)
    at java.net.URL.<init>(URL.java:310)
    at java.net.URL.<init>(URL.java:333)
    at org.eclipse.concierge.BundleImpl$Revision.createURL(BundleImpl.java:2460)
    at org.eclipse.concierge.BundleImpl$JarBundleRevision.findFile(BundleImpl.java:3633)
    at org.eclipse.concierge.BundleImpl$JarBundleRevision.lookupFile(BundleImpl.java:3587)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findOwnResources(BundleImpl.java:3220)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource1(BundleImpl.java:2747)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource0(BundleImpl.java:2685)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.findResource(BundleImpl.java:2541)
    at org.eclipse.concierge.BundleImpl$Revision$BundleClassLoader.getResource(BundleImpl.java:2517)
    at java.lang.ClassLoader.getResourceAsStream(ClassLoader.java:1307)
    at java.lang.Class.getResourceAsStream(Class.java:2223)
    at oracle.jdbc.driver.OracleDriver.<clinit>(OracleDriver.java:323)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at java.sql.DriverManager.isDriverAllowed(DriverManager.java:556)
    at java.sql.DriverManager.getConnection(DriverManager.java:661)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at nz.co.spark.cg.shared.sql.SQLUtils.getDBConnection(SQLUtils.java:19)
    at nz.co.spark.cg.shared.sql.SQLUtils.createLocalDB(SQLUtils.java:29)
    at nz.co.spark.cg.extractor.task.ChatExtractorJob.<init>(ChatExtractorJob.java:61)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at org.quartz.simpl.SimpleJobFactory.newJob(SimpleJobFactory.java:56)
    at org.quartz.simpl.PropertySettingJobFactory.newJob(PropertySettingJobFactory.java:69)
    at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
    at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375)

这发生在 oracle jdbc 驱动程序内部,在 class SQLStateMapping 中,classr 正在尝试获取资源文件,使用 SQLStateMapping.class.getResourceAsStream("error..xml");

发生这种情况是因为在 OSGi 包内它更改了 URL 插入 "bundle" 词,并且资源从未 returns 正确地抛出 java.net.MalformedURLException。有谁知道如何解决这个问题?

如果您想在 OSGi 中使用 JDBC,我建议您使用 (PAX-JDBC). It makes all required glue which will register DataSourceFactory from JDBC drivers, and if you are using ConfigAdmin service you can register DataSource-s too. When I use a library which able to handle JDBC connection or DataSource I get the instance from OSGi services and using that. The benefits of it you can use connection poolers too, PAX-JDBC supports it out of box. If the documentation not clear I can extend this answer with some example, but for start there is a good tutorial。它基于 karaf,但它可以适应任何标准 OSGi 实现。