アプリケーションがあり、Apache の Servicemix 4.5.3 から Servicemix 6.1.0 にアップグレードしました。また、Apache Commons dbcp から dbcp2 および pool2 にアップグレードしました。このアップグレード後に気づいたことの 1 つは、バンドルの起動とシャットダウンが非常に遅いことでした。それで、Google で調べてみると、Spring-DM は非推奨であり、Blueprint に置き換えられることがわかりました。そのため、すべてのバンドルで Spring-DM 構成を Blueprint に置き換えたところ、起動とシャットダウンがはるかに高速になりました。
ただし、この操作の後、いくつかの異なる動作が見られます。たとえば、Camel Routebuilders を作成し、configure() メソッドで、データベースからいくつかの構成を取得します。他のケースでは、setDataSource(..) メソッドを持つ Bean があり、ブループリントを介してそれにデータベース接続を注入し、その接続をバッキング フィールドに格納した後、追加の (キャッシュされた) 初期化のために DB を呼び出します。 .
この領域では、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>
次に、OSGI-INF.blueprint フォルダー (リソース) に blueprint.xml の初期化を含む、maven でコンパイルされたバンドルがあり、次のフラグメントがあります。
<?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
この問題が発生する 2 つのケースを確認しました。
- SomeClass のメソッド「setDataSource」がデータベースを呼び出すとき。
- SomeClass のメソッド「setDataSource」がデータソース値をプライベート バッキング フィールドに登録するだけで、SomeClass が (Camel) RouteBuilder であり、DB が configure() メソッドからアクセスされる場合。
上記のケース 1 でブレークポイントを設定しましたが、受け取った値は null ではありません。この null 以外の値はおそらく、ダンピング プロセスで使用されるリファレンス ダイナミズムに使用されるプロキシ クラスです。
スレッド A で実行されているバンドルは、Jdbc ドライバーへのプロキシを受け取り、データベースへの呼び出しを行いますが、Jdbc の初期化はスレッド B で行われ、スレッド B はまだ準備ができていません。バッキング サービスなしで何かを呼び出しています。ダンピング プロセスは、サービスの準備が整うまで、DB へのバンドル呼び出しをブロックする必要があるため、おそらくその領域で何か間違ったことをしているのでしょう。
上記の問題は複数のバンドルで発生し、システムによって動作が異なります。したがって、1 つを修正したと思われる場合は、別のものを介して再び表示されます。残念ながら、それはすべて非常に予測不可能です。
すでに試したことは次のとおりです。
- バンドルの設計図には、DB 接続への「<参照」があり、参照リスナーを使用しました。動作する場合と動作しない場合があります。
- プール 2 の maven-bundle-plugin セクションの下にある pom.xml の「import-packages」に依存関係を追加し、偶然これを見つけました。
- 可能な限りどこでも、lazy-inits を使用しました。これは 100% 機能しますが、Camel Routebuilder の configure() メソッドには適用できません (これがいつ呼び出されるかはわかりません)。
- バンドルの優先度を使用して、起動プロセスの早い段階で jndi.xml を初期化しました。インストールが自動化されているため、jndi.xml を非常に早い段階で、ServiceMix の他の何よりも先にインストールします。少しは役に立ちます。
私が試していないことは次のとおりです。-DBに保存された構成をローカルファイルに移動します-このリリースでは実行できませんが、将来のオプションです。- Spring-DM に戻します。面倒というより遅いほうがいい。ただし、これは私にとって実験的なものでもあります。私のマシンで(遅い)動作しているのを見てきました。他のマシンでも同じ問題が発生している可能性があります。また、この問題をServiceMixフォーラムに投稿しました(まだ回答が得られていません)が、Spring-DMに戻らないように「強く」アドバイスしています
JDBC ドライバーが完全に初期化されるまでバンドルが待機しない理由がよくわかりません。