2011年3月24日木曜日

Struts2 + Spring + Slim3

この内容は修正されました。
修正後はこちら

Struts2 + Spring + Slim3の連携に挑戦。

ソースの省略はしません。
今回と次回で、簡単なサンプルを動作させるまでの手順を載せます。

Slim3の新規プロジェクト作成
まず最初に、EclipseのSlim3プラグインを使用してSlim3の新規プロジェクトを作成します。
プロジェクト名とルートパッケージ
Project names3sample
Root Packagecom.brightgenerous.s3.sample.data
不要なファイルを削除しておきます。
削除するファイルとディレクトリ
/src/application_en.properties
/src/application_ja.properties
/war/css
/war/ktrwjr
/war/common.jsp
Jarファイル追加
以下のjarファイルを「war/WEB-INF/lib」に追加します。
追加するjarファイル
aopalliance-1.0
commons-beanutils-1.7.0
commons-digester-2.0
commons-fileupload-1.2.1
commons-io-1.3.2
commons-lang-2.3
commons-logging-1.0.4
commons-validator-1.3.1
freemarker-gae-pre3
javassist
ognl-3.0
spring-aop
spring-beans
spring-context
spring-core
spring-tx
spring-web
struts2-convention-plugin-2.2.1.1
struts2-core-2.2.1.1
struts2-spring-plugin-2.2.1.1
xwork-core-2.2.1.1
freemarker-gae-pre3は、gae用のfreemarkerです。
Springは2.5を使用します。
web.xml
「war/WEB-INF」に配置するweb.xmlファイルです。
  1. <!--xml version="1.0" encoding="utf-8"?-->  
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">  
  3.   
  4.  <context-param>  
  5.   <param-name>slim3.rootPackage</param-name>  
  6.   <param-value>com.brightgenerous.s3.sample.data</param-value>  
  7.  </context-param>  
  8.   
  9.  <context-param>  
  10.   <param-name>contextConfigLocation</param-name>  
  11.   <param-value>classpath:applicationContext*.xml</param-value>  
  12.  </context-param>  
  13.   
  14.  <filter>  
  15.   <filter-name>struts2</filter-name>  
  16.   <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>  
  17.   <init-param>  
  18.    <param-name>actionPackages</param-name>  
  19.    <param-value>com.brightgenerous.s3.sample.action</param-value>  
  20.   </init-param>  
  21.  </filter>  
  22.   
  23.  <filter-mapping>  
  24.   <filter-name>struts2</filter-name>  
  25.   <url-pattern>/*</url-pattern>  
  26.  </filter-mapping>  
  27.   
  28.  <listener>  
  29.   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  30.  </listener>  
  31.  <listener>  
  32.   <listener-class>com.brightgenerous.s3.sample.gae.GaeInitListener</listener-class>  
  33.  </listener>  
  34.   
  35. </web-app>  
Slim3の新規プロジェクトを作成して生成されるweb.xmlの内容のほとんどを消すことになります。
「com.brightgenerous.s3.sample.gae.GaeInitListener」は、独自に実装するクラスです。ソースは「実装するクラス」にて後述します。
applicationContext.xml
「classpath:applicationContext*.xml」(src直下)に配置します。
  1. <!--xml version="1.0" encoding="utf-8"?-->  
  2. <!--xml version="1.0" encoding="UTF-8" ?-->  
  3. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation="  
  4.    http://www.springframework.org/schema/beans  
  5.    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  6.    http://www.springframework.org/schema/context  
  7.    http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  8.   
  9.  <context:annotation-config></context:annotation-config>  
  10.   
  11.  <context:component-scan base-package="com.brightgenerous.s3.sample.action"></context:component-scan>  
  12.   
  13.  <bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor" class="com.brightgenerous.s3.sample.gae.GaeFixInternalPersistenceAnnotationProcessor">  
  14.  </bean>  
  15.   
  16.  <bean id="transactionManager" class="com.brightgenerous.s3.sample.gae.Slim3TransactionManager">  
  17.  </bean>  
  18.  <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">  
  19.   <property name="properties">  
  20.    <props>  
  21.     <prop key="regist*">PROPAGATION_REQUIRED</prop>  
  22.     <prop key="update*">PROPAGATION_REQUIRED</prop>  
  23.     <prop key="delete*">PROPAGATION_REQUIRED</prop>  
  24.     <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>  
  25.    </props>  
  26.   </property>  
  27.  </bean>  
  28.  <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">  
  29.   <property name="transactionManager" ref="transactionManager"></property>  
  30.   <property name="transactionAttributeSource" ref="transactionAttributeSource"></property>  
  31.  </bean>  
  32.  <bean id="beanNameAutoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
  33.   <property name="interceptorNames">  
  34.    <list>  
  35.     <value>transactionInterceptor</value>  
  36.    </list>  
  37.   </property>  
  38.   <property name="beanNames">  
  39.    <list>  
  40.     <value>*ServiceImpl</value>  
  41.    </list>  
  42.   </property>  
  43.  </bean>  
  44.   
  45. </beans>  
「transactionManager」のみ用意してやれば他はそのまま使えます。なかなかナイスな設計です。
「com.brightgenerous.s3.sample.gae.GaeFixInternalPersistenceAnnotationProcessor」、「com.brightgenerous.s3.sample.gae.Slim3TransactionManager」については、後述です。
実装するクラス
1.com.brightgenerous.s3.sample.gae.GaeInitListener
  1. package com.brightgenerous.s3.sample.gae;  
  2.   
  3. import javax.servlet.ServletContextEvent;  
  4. import javax.servlet.ServletContextListener;  
  5. import javax.servlet.http.HttpSessionAttributeListener;  
  6. import javax.servlet.http.HttpSessionBindingEvent;  
  7. import javax.servlet.http.HttpSessionEvent;  
  8. import javax.servlet.http.HttpSessionListener;  
  9.   
  10. import ognl.OgnlRuntime;  
  11.   
  12. public class GaeInitListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {  
  13.   
  14.  @Override  
  15.  public void contextInitialized(ServletContextEvent sce) {  
  16.   OgnlRuntime.setSecurityManager(null);  
  17.  }  
  18.   
  19.  @Override  
  20.  public void contextDestroyed(ServletContextEvent arg0) {  
  21.  }  
  22.   
  23.  @Override  
  24.  public void sessionCreated(HttpSessionEvent arg0) {  
  25.  }  
  26.   
  27.  @Override  
  28.  public void sessionDestroyed(HttpSessionEvent arg0) {  
  29.  }  
  30.   
  31.  @Override  
  32.  public void attributeAdded(HttpSessionBindingEvent arg0) {  
  33.  }  
  34.   
  35.  @Override  
  36.  public void attributeRemoved(HttpSessionBindingEvent arg0) {  
  37.  }  
  38.   
  39.  @Override  
  40.  public void attributeReplaced(HttpSessionBindingEvent arg0) {  
  41.  }  
  42. }  
OGNLのセキュリティマネージャがなんとかかんとか...理由については、詳しく調べていません。
2.com.brightgenerous.s3.sample.gae.GaeFixInternalPersistenceAnnotationProcessor
  1. package com.brightgenerous.s3.sample.gae;  
  2.   
  3. public class GaeFixInternalPersistenceAnnotationProcessor {  
  4.   
  5.  public GaeFixInternalPersistenceAnnotationProcessor() {  
  6.  }  
  7. }  
「java.lang.NoClassDefFoundError」を回避することだけが目的です。
3.com.brightgenerous.s3.sample.gae.Slim3TransactionManager
  1. package com.brightgenerous.s3.sample.gae;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. import org.slim3.datastore.Datastore;  
  6. import org.springframework.transaction.TransactionDefinition;  
  7. import org.springframework.transaction.TransactionException;  
  8. import org.springframework.transaction.support.AbstractPlatformTransactionManager;  
  9. import org.springframework.transaction.support.DefaultTransactionStatus;  
  10.   
  11. import com.google.appengine.api.datastore.Transaction;  
  12.   
  13. public class Slim3TransactionManager extends AbstractPlatformTransactionManager {  
  14.   
  15.  private static final long serialVersionUID = 3423679590583692519L;  
  16.   
  17.  @Override  
  18.  protected void doBegin(Object x_arg0, TransactionDefinition x_arg1) throws TransactionException {  
  19.   TransactionObject transactionObject = (TransactionObject) x_arg0;  
  20.   transactionObject.p_transaction = Datastore.beginTransaction();  
  21.  }  
  22.   
  23.  @Override  
  24.  protected void doCommit(DefaultTransactionStatus x_arg0) throws TransactionException {  
  25.   TransactionObject transactionObject = (TransactionObject) x_arg0.getTransaction();  
  26.   transactionObject.p_transaction.commit();  
  27.  }  
  28.   
  29.  @Override  
  30.  protected Object doGetTransaction() throws TransactionException {  
  31.   return new TransactionObject();  
  32.  }  
  33.   
  34.  @Override  
  35.  protected void doRollback(DefaultTransactionStatus x_arg0) throws TransactionException {  
  36.   TransactionObject transactionObject = (TransactionObject) x_arg0.getTransaction();  
  37.   transactionObject.p_transaction.rollback();  
  38.  }  
  39.   
  40.  private class TransactionObject implements Serializable {  
  41.   
  42.   private static final long serialVersionUID = -8353097480608667182L;  
  43.   
  44.   Transaction p_transaction;  
  45.  }  
  46. }  
「org.springframework.jdbc.datasource.DataSourceTransactionManager」の実装を参考にして、Slim3用に簡単に対応させています。
このクラスのみ自作です。間違い等あれば指摘していただけるとありがたいです。

以上でStruts2 + Spring + Slim3の設定は完了です。
次回は、このフレームワークを使用して簡単なサンプルを書いてみます。

0 件のコメント:

コメントを投稿