WebアプリケーションでSpring Integrationを使用する場合のスレッド
今回のブログは、Spring Framework Advent Calendar 2012の20日目の記事として投稿します。
前回のブログで、WebアプリケーションでSpring Integrationを使用すると、Spring Integrationが生成するスレッドをAPサーバが管理できないので危険だというお話をしました。
この件について、SpringSource CommunityのForumに、「Spring IntegrationをWebアプリケーションで使用するのは、スレッドの観点から安全なのか?」質問したところ、APサーバが管理するスレッドをSpring Integrationが使用する方法を紹介してもらいました。
今回のブログでは、APサーバが管理するスレッドをSpring Integrationが利用する方法を紹介します。
Spring Integrationには、CommonJと呼ばれるAPIを介して並列処理を実施する仕組みが提供されています。CommonJは、「JSR 237: Work Manager for Application Servers」と「JSR 236: Concurrency Utilities for JavaTM EE」を合わせた呼び名で、EJBやServletがコンテナ内で並列処理をするためのAPIです。ちなみにWebLogicやWebSphereは対応しているようですが、Tomcatは対応していません。
CommonJでは、非同期処理用のcommonj.work.WorkManagerインタフェースと、スケジューリング用のcommonj.timers.TimerManagerインタフェースが提供されています。Spring Integrationはそれぞれに対応したorg.springframework.scheduling.commonj.WorkManagerTaskExecutorクラスとorg.springframework.jms.listener.DefaultMessageListenerContainerクラスが提供されており、Bean定義ファイルでBeanを定義して利用します。
TimerManagerTaskSchedulerのBean定義は以下になります。
<bean id="taskScheduler" class="org.springframework.scheduling.commonj.TimerManagerTaskScheduler"> <property name="timerManagerName" value="java:comp/env/tm/MyTimerManager" /> </bean>
propertyで指定しているのは、APサーバが提供しているTimerManagerのJNDI名です。この設定により、ポーリングするようなEndpointでは、このBeanが使われるようです(動作確認は、
WorkManagerTaskExecutorのBean定義は以下になります。
<bean id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor"> <property name="workManagerName" value="java:comp/env/wm/MyWorkManager" /> </bean>
動作確認のため、
<bean id="sampleQueueListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="taskExecutor" ref="taskExecutor"/> <property name="connectionFactory" ref="connectionFactory"/> <property name="destinationName" value="sampleQueue"/> </bean> <jms:message-driven-channel-adapter id="inboundAdapter" channel="channel2" container="sampleQueueListenerContainer"/>
DefaultMessageListenerContainerのpropertyでtaskExecutorを指定し、