GAE/JにDWR2+Springframework2.5 DIを乗せてみた
DI(Dependency Injection)が注目されたのが、いつ頃だったか忘れてしまったが、廃刊になってしまった「Javapress」でSeaser2とSpringframework(以下、Spring)のサンプル付きの記事を読んだとき、「これはすごい!!」と思った。場所まで覚えている。渋谷の旧東邦生命ビルの喫茶店だった。
その後、Rod Johson氏の書籍(よくあれだけ分厚い本が書けると感心してしまった)を読んだり、米国に行った際に「in Actionシリーズ(邦訳は少ないが、有名なプロダクトについては必ず出版されている)」を買ってきたりした。
Springは、自分が知った当時から「大きな」プロジェクトで、「いったい、どれくらいのコミッターがいるのだろう」と思うくらい、プロダクトが次から次へと増えていった。今はSpringSourceという会社ができて、そのサイトからコミュニティー版がダウンロードできる(こちら)。
気が付くとバージョンは2.5。3.0が出そうな勢い。進化のスピードが速すぎて「フォローするのがキツいプロダクト」ではあるが、今でも利用させてもらうことが多い。
今回のログでは、以前に作った簡単なDWR2のサンプルを改造して、DWR2とSpringframework(V2.5.6)のDIを連携させてGoogle Apps Engine/Java(GAE/J)に乗せてみた。
Springのダウンロード
上のダウンロードセンターからspring-framework-2.5.6.SEC01-with-dependencies.zipをダウンロードすると、依存性のあるサードパーティーのプロダクトと一緒に、たくさんのプロダクトが入っているのが分かる。DIだけを利用する限り、spring.jarだけがあればよい。
プロジェクトの作成
GAEプラグインがインストールされたEclipseで、Wep Applicationプロジェクトを新規に作成する(プロジェクト名:GaeSpringframeworkTest)。今回もGWTは使わないので、チェックを外してプロジェクトを作成する。パッケージ名はtestとした。
jarの配置とその他のリソースの作成
DWR2からSpring DIを使うサンプルを作るので、dwr.jarとcommons-logging.jar、log4j.jar、spring.jarをwar/WEB-INF/lib下にコピーする。
また、以下の物も前回のサンプルからコピーする。
web.xmlの変更
コピーしてきたweb.xmlにはDWR2を利用するための定義がしてある(はず)。
サンプルでは、手っ取り早くSpringのコンテナをListnerを使ってロードするようにした。bean定義ファイル(beans.xml)は、war/WEB-INF下におくように定義した。
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"> <context-param> <description> Specify the beans.xml location. When you specify more than one, be separated by a camma. </description> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/beans.xml </param-value> </context-param> <listener> <description> Spring Bootstrap. </description> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dwr-invoker</servlet-name> <display-name>DWR Servlet</display-name> <description>Direct Web Remoter Servlet</description> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>activeReverseAjaxEnabled</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>initApplicationScopeCreatorsAtStartup</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>maxWaitAfterWrite</param-name> <param-value>-1</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>demo.html</welcome-file> </welcome-file-list> </web-app>
beans.xmlの作成
bean定義ファイルを作成する(war/WEB-INF/beans.xml)。
GAEでSpringコンテナが起動することと、DIが正常に行われることのサンプリングなので、以下のように簡単なものとした(参考:@IT「Springは「2.0」でどんだけ便利になったの?」)。
<?xml version="1.0" encoding="utf-8"?> <beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"> <bean id="demoBean" class="test.Demo"> <property name="helloMessages"> <ref bean="messages"/> </property> </bean> <util:map id="messages" map-class="java.util.HashMap"> <entry key="msg1" value="こんにちは! " /> <entry key="msg2" value="こんばんわ! " /> </util:map> </beans>
先日のログで作ったDemo.javaを少しだけ改造し、Map型のコレクションをインジェクションしてみる。
Demo.javaの改造
test.Demo.javaを以下のように改造した。
package test; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * DWR+Spring DIのデモ * */ public class Demo { private static final Log log = LogFactory.getLog(Demo.class); private Map<String,String> helloMessages; /** * Setter * @param helloMessages */ public void setHelloMessages(Map<String,String> helloMessages) { this.helloMessages = helloMessages; } public String sayHello(String name) { log.debug("say hello called. "+name); return this.helloMessages.get("msg1") + name + " さん"; } }
dwr.xmlの改造
DWR2からspringで定義されたbeanを呼び出すように変更する(DWRのマニュアルはこちら。「DWR 1.x - dwr.xml - The Spring creator」のセクションの方法をとる)。
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://directwebremoting.org/schema/dwr20.dtd"> <dwr> <allow> <create creator="spring" javascript="Demo"> <param name="beanName" value="demoBean" /> </create> </allow> </dwr>