1

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

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

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

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

在 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 编译的包,在 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) RouteBuilder 并且从 configure() 方法访问 DB 时;

我在上面的情况 1 中设置了一个断点,并且收到的值是非空的。这个非空值可能是用于参考动态的代理类,在阻尼过程中使用。

看起来是我们的包,它在线程 A 中运行,接收到 Jdbc 驱动程序的代理,并调用数据库,而 Jdbc 初始化在线程 B 中完成,而 threab B 尚未准备好,所以你'在没有支持服务的情况下调用某些东西。阻尼过程应该阻止对数据库的捆绑调用,直到服务准备好,所以我可能在那个区域做错了什么。

上面的问题发生在几个捆绑包中,并且在不同的系统上表现不同。因此,如果您认为已将其固定在一个中,那么它会通过另一个重新出现。不幸的是,这一切都非常不可预测。

我们已经尝试过的是:

  • 捆绑蓝图对数据库连接有一个“<reference”,我使用了一个引用侦听器——有时有效,有时无效;
  • 在 pom.xml 中的“import-packages”中添加了一个依赖项,在 pool2 的 maven-bundle-plugin 部分下,巧合地发现了这个,我已经看到了很好的结果,但它不能始终如一地工作;
  • 尽可能在任何地方使用惰性初始化,这 100% 有效,但不能应用于 Camel Routebuilder 的 configure() 方法(我不知道何时调用);
  • 在启动过程的早期使用捆绑优先级来初始化 jndi.xml。由于我们有自动安装,我什至很早就安装了 jndi.xml,并且在 ServiceMix 中的任何其他内容之前安装。有点帮助。

我没有尝试的事情是: - 将数据库存储的配置移动到本地文件 - 对于这个版本不可行,对于未来的一个选项;- 恢复为 Spring-DM。慢总比麻烦好。然而,这对我来说也是实验性的,我已经看到它(慢)在我的机器上工作,也许它在其他机器上也有同样的问题。我也在 ServiceMix 论坛上发布了这个问题(还没有得到答案),他们“强烈”建议不要恢复到 Spring-DM

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

4

0 回答 0