我们有一个应用程序,并从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中设置了一个断点,并且接收的值是非空的。此非空值可能是用于Reference Dynamism的damping process的代理类。
看起来我们的bundle在线程A中运行,接收Jdbc驱动程序的代理,并调用数据库,而Jdbc初始化在线程B完成,而threab B尚未就绪,所以你在没有支持服务的情况下打电话。阻尼过程应该阻止对DB的捆绑调用,直到服务准备好,所以我可能在该区域做错了。
上述问题发生在几个捆绑包中,并且在不同的系统上采取不同的行为。所以如果你认为你把它固定在一个,那么它会通过另一个再次出现。不幸的是,这一切都非常难以预测。
我们已经尝试过:
我没试过的事情是: - 将DB存储的配置移动到本地文件 - 此版本不可行,以备将来使用; - 恢复到Spring-DM。比麻烦更慢。然而这对我来说也是实验性的,我已经看到它(慢)在我的机器上工作,也许它在其他机器上有同样的问题。此外,我在ServiceMix论坛上发布了这个问题(还没有得到答案),他们强烈地#39;建议不要恢复到Spring-DM
我真的不明白为什么捆绑包不会等到JDBC驱动程序完全初始化。