从Spring-DM切换到Blueprint:无法加载JDBC驱动程序类' com.mysql.jdbc.Driver'

时间:2016-05-11 14:30:22

标签: java jdbc blueprint-osgi apache-servicemix spring-dm

我们有一个应用程序,并从Apache的Servicemix 4.5.3升级到Servicemix 6.1.0。我们还从Apache Commons dbcp升级到dbcp2和pool2。在升级之后我注意到的一件事是捆绑启动和关闭非常非常慢。所以我浏览了一下Google,发现Spring-DM是deprecated,将被Blueprint取代。因此,我将Spring-DM配置替换为所有捆绑包的Blueprint,现在它们在启动和关闭方面更快。

但是我在这次操作后看到了一些不同的行为。例如,我们制作了Camel Routebuilders,在configure()方法中,我们从数据库中获得了一些配置。在其他情况下,我们有一个带有setDataSource(..)方法的bean,我们通过blueprint将数据库连接注入到它中,并在将该连接存储在后台fielkd中后,我们调用DB进行一些额外的(缓存)初始化。

在这个领域,我们现在使用Blueprint获得异常,而我们从未使用过Spring-DM。找不到MySql Drive类。 setDataSource(..)方法获取代理类,而后备服务尚未初始化。对此代理类的调用会导致异常,并且bundle启动失败。如果你稍后手动重启捆绑,那么它工作正常;可能是因为依赖关系已经解决了。

好的,长篇介绍。这就是我们在代码中所做的。

在deploy文件夹中,我们有一个名为jndi.xml的文件,这是其内容的一部分:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
        >

    <cm:property-placeholder id="database.properties" persistent-id="our.database.connection.properties"/>


    <bean id="datasourceMain" class="org.apache.commons.dbcp2.managed.BasicManagedDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="${connection-string}"/>
        <property name="username" value="${connection-username}"/>
        <property name="password" value="${connection-password}"/>
        <property name="maxTotal" value="20"/>
        <property name="maxIdle" value="10"/>
        <property name="maxWaitMillis" value="5000"/>
        <property name="minEvictableIdleTimeMillis" value="2880000"/>
        <property name="testWhileIdle" value="true"/>
        <property name="validationQuery" value="select 1"/>
        <property name="transactionManager" ref="jtaTransactionManager"/>
    </bean>
    <service id="serviceMade" interface="javax.sql.DataSource" ref="datasourceOurApp">
        <service-properties>
            <entry key="osgi.jndi.service.name" value="MainDB"/>
        </service-properties>
    </service>

然后我们有一个maven编译的bundle,在OSGI-INF.blueprint文件夹(资源)中使用blueprint.xml初始化,使用这个片段:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
           http://camel.apache.org/schema/blueprint
           http://camel.apache.org/schema/blueprint/camel-blueprint-2.16.1.xsd
           ">
    <bean id="ourlogicBean" class="oprg.unimportant.SomeClass">
        <property name="dataSource" ref="dataSourceRef"/>
    </bean>
    <reference id="dataSourceRef" interface="javax.sql.DataSource" filter="(osgi.jndi.service.name=MainDB)"/>
</blueprint>

这是我们在ServiceMix日志文件中看到的例外:

2016-05-11 10:48:13,915 | ERROR | OURAPP/deploy | BlueprintContainerImpl           | 15 - org.apache.aries.blueprint.core - 1.4.4 | Unable to start blueprint container for bundle our-package/1.0.0
org.osgi.service.blueprint.container.ComponentDefinitionException: Error setting property: PropertyDescriptor <name: dataSource, getter: null, setter: [class oprg.unimportant.SomeClass.setDataSource(interface javax.sql.DataSource)]
        at org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:939)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:905)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:886)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:820)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:787)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:79)[15:org.apache.aries.blueprint.core:1.4.4]
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)[:1.7.0_79]
        at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:88)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:247)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:183)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl.java:682)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:377)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:269)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:294)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:263)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:253)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)[9:org.apache.aries.util:1.1.1]
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)[9:org.apache.aries.util:1.1.1]
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)[9:org.apache.aries.util:1.1.1]
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)[9:org.apache.aries.util:1.1.1]
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)[9:org.apache.aries.util:1.1.1]
        at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1103)[org.apache.felix.framework-4.2.1.jar:]
        at org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:695)[org.apache.felix.framework-4.2.1.jar:]
        at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:483)[org.apache.felix.framework-4.2.1.jar:]
        at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4403)[org.apache.felix.framework-4.2.1.jar:]
        at org.apache.felix.framework.Felix.startBundle(Felix.java:2092)[org.apache.felix.framework-4.2.1.jar:]
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)[org.apache.felix.framework-4.2.1.jar:]
        at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1245)[7:org.apache.felix.fileinstall:3.5.0]
        at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1217)[7:org.apache.felix.fileinstall:3.5.0]
        at org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:509)[7:org.apache.felix.fileinstall:3.5.0]
        at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:358)[7:org.apache.felix.fileinstall:3.5.0]
        at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:310)[7:org.apache.felix.fileinstall:3.5.0]
Caused by: oprg.unimportant.SystemException: Exception thrown in SomeClass.setDataSource
        at oprg.unimportant.SomeClass.setDataSource(SomeClass.java:52)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.7.0_79]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_79]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_79]
        at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_79]
        at org.apache.aries.blueprint.utils.ReflectionUtils$MethodPropertyDescriptor.internalSet(ReflectionUtils.java:630)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.utils.ReflectionUtils$PropertyDescriptor.set(ReflectionUtils.java:380)[15:org.apache.aries.blueprint.core:1.4.4]
        at org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:937)[15:org.apache.aries.blueprint.core:1.4.4]
        ... 31 more
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Cannot load JDBC driver class 'com.mysql.jdbc.Driver'
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80)
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:575)[244:org.apache.servicemix.bundles.spring-jdbc:3.2.14.RELEASE_1]
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:639)[244:org.apache.servicemix.bundles.spring-jdbc:3.2.14.RELEASE_1]
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:668)[244:org.apache.servicemix.bundles.spring-jdbc:3.2.14.RELEASE_1]
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:676)[244:org.apache.servicemix.bundles.spring-jdbc:3.2.14.RELEASE_1]
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:716)[244:org.apache.servicemix.bundles.spring-jdbc:3.2.14.RELEASE_1]
        at org.springframework.jdbc.core.JdbcTemplate.queryForList(JdbcTemplate.java:803)[244:org.apache.servicemix.bundles.spring-jdbc:3.2.14.RELEASE_1]
        at oprg.unimportant.SomeClass.setDataSource(SomeClass.java:165)
        ... 40 more
Caused by: java.sql.SQLException: Cannot load JDBC driver class 'com.mysql.jdbc.Driver'
        at org.apache.commons.dbcp2.BasicDataSource.createConnectionFactory(BasicDataSource.java:2138)
        at org.apache.commons.dbcp2.managed.BasicManagedDataSource.createConnectionFactory(BasicManagedDataSource.java:138)
        at org.apache.commons.dbcp2.BasicDataSource.createDataSource(BasicDataSource.java:2032)
        at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1533)
        at Proxyee603976_5a24_4518_bfe5_33f1be6168ad.getConnection(Unknown Source)
        at Proxy718290c5_58a3_421e_b083_26c576c0433e.getConnection(Unknown Source)
        at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)[244:org.apache.servicemix.bundles.spring-jdbc:3.2.14.RELEASE_1]
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)[244:org.apache.servicemix.bundles.spring-jdbc:3.2.14.RELEASE_1]
        ... 47 more
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)[:1.7.0_79]
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)[:1.7.0_79]
        at java.security.AccessController.doPrivileged(Native Method)[:1.7.0_79]
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)[:1.7.0_79]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)[:1.7.0_79]
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)[:1.7.0_79]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)[:1.7.0_79]
        at org.apache.commons.dbcp2.BasicDataSource.createConnectionFactory(BasicDataSource.java:2129)
        ... 54 more

我遇到了两个出现此问题的案例:

  1. 当SomeClass中的方法“setDataSource”进行调用时 数据库;
  2. 当SomeClass中的方法“setDataSource”时 在私有支持字段中注册数据源值,但SomeClass是一个(Camel) 从configure()方法访问RouteBuilder和DB;
  3. 我在上面的情况1中设置了一个断点,并且接收的值是非空的。此非空值可能是用于Reference Dynamismdamping process的代理类。

    看起来我们的bundle在线程A中运行,接收Jdbc驱动程序的代理,并调用数据库,而Jdbc初始化在线程B完成,而threab B尚未就绪,所以你在没有支持服务的情况下打电话。阻尼过程应该阻止对DB的捆绑调用,直到服务准备好,所以我可能在该区域做错了。

    上述问题发生在几个捆绑包中,并且在不同的系统上采取不同的行为。所以如果你认为你把它固定在一个,那么它会通过另一个再次出现。不幸的是,这一切都非常难以预测。

    我们已经尝试过:

    • 捆绑蓝图有一个&#34;&lt; reference&#34;到数据库连接,我使用了一个引用 - 听众 - 有时是工作,有时不工作;
    • 在&#34; import-packages&#34;中添加了一个依赖项。在pom.xml中,在pool2上,在maven-bundle-plugin部分下,巧合地发现了这一点,我已经看到了良好的结果,但它不能始终如一地工作;
    • 在可能的地方,使用lazy-inits,这可以100%工作但不能应用于Camel Routebuilder configure()方法(我不知道何时调用它);
    • 使用bundle优先级在启动过程的早期初始化jndi.xml。由于我们有自动安装,我甚至很早就安装了jndi.xml,之前在ServiceMix中安装了其他任何东西。有点帮助。

    我没试过的事情是:   - 将DB存储的配置移动到本地文件 - 此版本不可行,以备将来使用;   - 恢复到Spring-DM。比麻烦更慢。然而这对我来说也是实验性的,我已经看到它(慢)在我的机器上工作,也许它在其他机器上有同样的问题。此外,我在ServiceMix论坛上发布了这个问题(还没有得到答案),他们强烈地#39;建议不要恢复到Spring-DM

    我真的不明白为什么捆绑包不会等到JDBC驱动程序完全初始化。

0 个答案:

没有答案