kuniku’s diary

はてなダイアリーから移行(旧 d.hatena.ne.jp/kuniku/)、表示がおかしな箇所はコメントをお願いします。記載されている内容は日付およびバージョンに注意してください。直近1年以上前は古い情報の可能性が高くなります。

s2strutsの移行 1.2から1.3へ

Seasar2のバージョンアップをやってみる

Seasar2の2.3+s2struts1.2+s2Daoで作成していて動作までしていたものを
hotdeploy対応してみたく、Seasar2の2.4+s2struts1.3に変更している
のだけれどもなかなか動作してくれない。
まだまだ悪戦苦闘中><。

S2Struts1.3.xへの移行移行ガイドを参考にしながらコンテナを起動するところまではできたが、
その後が「catalog s2struts がありません」となり、Action系がさっぱり動作しなかった。
次に示していくことを試したら動いた。
けど今度は別のところエラー(ActionでもらうDTOがインジェクションできない)だとさ。
まだまだ奮闘せにゃあかんね。

書き忘れてたので追記
2008/04/07に s2struts1.2から1.3への移行ガイドは修正されています。

FormのDTOがセットできないエラー

org.seasar.framework.beans.IllegalPropertyRuntimeException: 
[ESSR0059]クラス(xxxxxxActionImpl$$EnhancedByS2AOP$$c12978)の
プロパティ(xxxxxxDto)の設定に失敗しました。
理由はjava.lang.IllegalArgumentException: argument type mismatch

・・・・・
なお、適当に改行やxxxでクラス名を変更しています。

最初に移行として行った作業

  • 開発途中のEclipse3.4M4とWTPwtp-S-3.0M4-20080105091323)にて動的Webプロジェクトの作成

  (tomcat Pluginは普段使っていないのでWTPで試した)

  • Seasar2のDIコンテナとして必要なファイルを配置

http://s2container.seasar.org/2.4/ja/setup.html#notdolteng
にならい、Seasar2の2.4に必要なファイルをダウンロードし
WEB-INF/libに配置

  • DIコンテナを使用するようにアプリケーションの設定

http://s2container.seasar.org/2.4/ja/DIContainer.html#CreateFileにならいapp.diconを配置
S2ContainerServletを使うためには、web.xmlに設定情報を記述するとのことで
http://s2container.seasar.org/2.4/ja/DIContainer.html#S2ContainerServletにならい
web.xmlを修正

  • S2Struts1.3.xへの移行移行ガイドの修正を適用

これらの変更だけでは無理っす(当然か・・・)。


次の作業(まずはsampleを移行してみる)

ってことで、そもそもs2struts1.2のsampleを1.3に移行してみれば
不足していること、違いが明確になるのではないか思い。ちょっと路線を変更(周り道だけどさ)。

ということで1.2系のsampleを1.3系に移行した作業でコンパイルエラーやeclipseがエラーと表示
している箇所を地道に修正し、修正した箇所を、移行したいWebAppに適用していく。

修正箇所いろいろ

Dtoとして定義していたクラス(strutsでいうところのActionFormに相当)の
import文、アノテーションなどを変更(移行ガイドの通り)

移行ガイドの
import文をorg.seasar.struts.MessageManagerからorg.seasar.struts.pojo.MessageManagerへ
import文をorg.seasar.struts.validator.config.ConfigRegisterからorg.seasar.struts.lessconfig.validator.config.ConfigRegisterへ
 
とあるので、それに伴い
@Args(keys="message.xxxx.xxxxx", resource=true)

@Args(keys="message.xxxx.xxxxx", resource = BoolType.TRUE)
同様にresource = BoolType.FALSE などの修正も。

diconファイルの変数を変更
2.3系のときに、
servletContext.getRealPath("/")
と記述していたので、それを
暗黙的なコンポーネントを見て
ServletContext application とのことで、

servletContext.getRealPath("/")

application.getRealPath("/")へ


{WebApp}/WEB−INF/struts-config.xmlの変更
struts-configは移行ガイドだけでは不足しているので注意

XMLDTDを変更する

 struts-config_1_2.dtd →struts-config_1_3.dtd

struts controllerのprocessorClass、RequestProcessorを変更する
 具体的には、
 controllerは、hotdeployを利用するためs2container2.4側にまかせるため

 <controller catalog="s2struts"/>

 を定義し、
s2struts1.2で使用していた従来のcontrollerはコメント

 <!--
  <controller processorClass="org.seasar.struts.processor.S2RequestProcessor" />
 -->

 
strutsのPluguinでseasarと結びつける自動設定処理のクラスを修正(移行ガイド通り)
従来のはコメントとし

  <!-- <plug-in className="org.seasar.struts.plugin.AutoStrutsConfigRegisterPlugIn"> -->
    <plug-in className="org.seasar.struts.lessconfig.plugin.AutoStrutsConfigRegisterPlugIn">
	<set-property property="enableJar" value="false" />
	<set-property property="docRoot" value="/pages"/>
  </plug-in>

・hotdeployを利用するpluginを追加する

 <plug-in className="org.seasar.struts.hotdeploy.plugin.HotdeployPlugIn"/>

{WebApp}/WEB−INF/web.xmlの変更


・Filterの追加
  hotdeploy用のfilterを追加

 <filter>
    <filter-name>hotdeployfilter</filter-name>
    <filter-class>org.seasar.framework.container.hotdeploy.HotdeployFilter</filter-class>
  </filter>

  <filter>
    <filter-name>s2strutshotdeployfilter</filter-name>
    <filter-class>org.seasar.struts.hotdeploy.filter.S2StrutsHotdeployFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>hotdeployfilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
  </filter-mapping>

servletの追加(変更):移行ガイドだけでは不足しているので注意
actionとして処理するクラスをorg.seasar.struts.servlet.S2ActionServletから
org.apache.struts.action.ActionServletに戻す

そのactionのinit処理でchainConfigパラメータを追加し、そのパラメータに対する値として
s2struts-chain-config.xml, org/apache/struts/chain/chain-config.xmlを設定
設定(変更)した内容は以下の

<web-appp>
    ・・・
  <servlet>
   <servlet-name>action</servlet-name>
	<!-- s2,ver2.4,およびs2struts1.3対応 -->
	<!-- S2ActionServletをActionServletに戻す
	<servlet-class>org.seasar.struts.servlet.S2ActionServlet</servlet-class>
	-->
	<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
	 <init-param>
	 <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
      </init-param>

    <init-param>
      <param-name>chainConfig</param-name>
      <param-value>s2struts-chain-config.xml, org/apache/struts/chain/chain-config.xml</param-value>
      <!--
      <param-value>s2struts-chain-config.xml, org/apache/struts/tiles/chain-config.xml</param-value>
      -->
    </init-param>
  <init-param>
   <param-name>debug</param-name>
   <param-value>2</param-value>
  </init-param>
  <init-param>
   <param-name>detail</param-name>
   <param-value>2</param-value>
  </init-param>
  <load-on-startup>2</load-on-startup>
  </servlet>

    ・・・
    ・・・
</web-appp>

FormDTOがセットできないエラー

このエラーは、どうやらs2struts1.2では発生しないのだけども、
s2struts1.3では そのままでは動作しないのでなんとか直したいがよくわからない。

検証したのは、s2struts1.2のsampelに対して検証してみた。

やりたいことは、1つのActionが受けて、そのActionがパラメータの値に応じて
別のActionにForwardするということです。

s2struts1.2では、リクエストパラメータとしてstruts-configのform-beanで
定義するDtoをActionの実装クラスのインスタンスにセットしてくれるが
1.3だと

org.seasar.framework.beans.IllegalPropertyRuntimeException: 
[ESSR0059]クラス(xxxxxxActionImpl$$EnhancedByS2AOP$$c12978)の
プロパティ(xxxxxxDto)の設定に失敗しました。
理由はjava.lang.IllegalArgumentException: argument type mismatch

となり、Dtoに設定されない。(1.2で作成していたwebappの場合でのエラー内容)

思いつく違いとしてはs2struts1.2で、
processorClass="org.seasar.struts.processor.S2RequestProcessor"
を使用しているけど

s2struts1.3ではそれをコメントにし、

 

としていることは違う。
struts1.2から1.3ではRequestProcessorが変更されたとか、どこかで
見かけてので、その辺りの影響なのかな。(不明)

あとは、web.xml(下記参照)でS2ActionServletをコメントにしてstruts側でデフォルトで
もつActionServletを使用するようにしている影響なのかな。(不明)

strutsについて未熟な者で、Seasarも未熟で 正直ようわからん。

今回の現象が再現するファイルを以下の通り、sampleファイルを作成していく。


2008.04.04 10:50追記
IllegalArgumentException: argument type mismatch ではなくなった。なんか動いてる。
下記のdiconの設定dev.diconで設定が足りてなかった。
けど、以前のs2struts1.2で動作していたものが1.3で動作しないのは、もっと調べる必要がありそうだ。

2008.04.04 17:30追記
なんとか動きはじめた。
ActionFormとして取得するDtoをdiconに定義するとダメみたいだ。

struts-config.xmlのform-beanで記述しているDtoをdev.diconで記述していたが
それをコメントにした。具体的には下記検証したdev.diconの

<!--
<component name="layerDto" class="org.seasar.struts.examples.dev.dto.LayerDto" instance="request"/>
-->

の通りコメントにする。
そうするとAction側に用意したDtoにインジェクションしてもらえる。


検証を行ったsampleファイル

**struts-config.xmlを以下のように追加

 <form-bean name="layerDto" type="org.seasar.struts.examples.dev.dto.LayerDto" />
 </form-beans>

  <action-mappings>
     <!-- 受ける基となるAction -->
   <action scope="request" path="/layer"
      type="org.seasar.struts.examples.dev.LayerForwardAction">
   
      <!-- commerce -->
      <forward name="commerce" path="/layer/commerce.do" />
      
      <!-- ads -->
      <forward name="ads" path="/layer/ads.do" />
   </action>
         
   <!-- ForwardされてくるAction -->
   <action path="/layer/commerce"
    scope="request" name="layerDto" 
    type="org.seasar.struts.examples.dev.CommerceLayerAction">
    <forward name="success" path="/pages/devtestresult.html" />
    <forward name="failed" path="/" />
 </action>
        
        
  <!-- ForwardされてくるAction -->
   <action path="/layer/ads"
     scope="request" name="layerDto" 
     type="org.seasar.struts.examples.dev.AdsLayerAction">
    <forward name="success" path="/pages/devtestresult.html" />
    <forward name="failed" path="/" />
   </action>
        
 </action-mappings>

strutsのActionServletとして受けるためのActionを作成

POJOにするために、まずはインターフェイスを作成。

ForwardするためのAction(LayerForwardAction.java)とForwardされた後のAction(AdsLayerAction.java、CommerceLayerAction.java)を作成

package org.seasar.struts.examples.dev;

public interface LayerForwardAction {
  public String execute();
}
package org.seasar.struts.examples.dev;

public interface CommerceLayerAction {

  public static final String SUCCESS = "success";
  
    public String execute();
}
package org.seasar.struts.examples.dev;

public interface AdsLayerAction {
	
  public static final String SUCCESS = "success";
  
  public String execute();
	
}


上記のAction3つの実装クラスを作成

package org.seasar.struts.examples.dev.impl;

import org.seasar.struts.examples.dev.LayerForwardAction;

public class LayerForwardActionImpl implements LayerForwardAction {

  private String layername;
	
    public void setLayername(String layername) {
      this.layername = layername;
    }
    
    public String execute() {
      return layername;
    }
}
package org.seasar.struts.examples.dev.impl;

import org.seasar.struts.examples.dev.CommerceLayerAction;
import org.seasar.struts.examples.dev.dto.LayerDto;

public class CommerceLayerActionImpl implements CommerceLayerAction {
	
   private LayerDto layerDto;
	
   private String result;
	
   public LayerDto getLayerDto() {
     return layerDto;
   }

   public void setLayerDto(LayerDto layerDto) {
     this.layerDto = layerDto;
   }


   public String getResult() {
     return result;
   }

   public String execute() {
		
     this.result = layerDto.getX() + "と" + layerDto.getY();
     return "success";
   }

}
package org.seasar.struts.examples.dev.impl;

import org.seasar.struts.examples.dev.AdsLayerAction;
import org.seasar.struts.examples.dev.dto.LayerDto;

public class AdsLayerActionImpl implements AdsLayerAction {
	
  private LayerDto layerDto;
	
  private String result;
	
  public LayerDto getLayerDto() {
    return layerDto;
  }

  public void setLayerDto(LayerDto layerDto) {
    this.layerDto = layerDto;
  }

  public String getResult() {
    return result;
  }

  public String execute() {
		
    this.result = layerDto.getX() + "と" + layerDto.getY();
    return "success";
  }

}

ActionFormとしてhtmlの画面から取得するリクエストパラメータの値を
格納するクラス(ここでは、LayerDto.javaとする)を作成

package org.seasar.struts.examples.dev.dto;

public class LayerDto {
 
 private String x;
 
 private String y;

 public String getX() {
  return x;
 }

 public void setX(String x) {
  this.x = x;
 }

 public String getY() {
  return y;
 }

 public void setY(String y) {
  this.y = y;
 }
 
}

diconファイルを作成
org/seasar/struts/examples/dicon/dev.diconとします。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
	"http://www.seasar.org/dtd/components23.dtd">
<components>
	
	<component name="layerDto" class="org.seasar.struts.examples.dev.dto.LayerDto" instance="request"/>
	
	<component class="org.seasar.struts.examples.dev.impl.LayerForwardActionImpl" instance="request" >
     <!-- 2008.04.04 10:40 追記 -->
          <property name="layername">request.getParameter("layername")</property>

	</component>
	
	<component class="org.seasar.struts.examples.dev.impl.AdsLayerActionImpl" instance="request" >
	</component>

	<component class="org.seasar.struts.examples.dev.impl.CommerceLayerActionImpl" instance="request" >
	</component>
	
</components>

app.diconに上記のdiconを追加

<include path="org/seasar/struts/examples/dicon/dev.dicon"/>

入力・結果画面のhtmlとmayaaファイルを作成

入力画面として
/pages/devtest.html

<html>
<body>

	<h2><a name ="commerce">テスト1</a></h2>
	<div>
		<span id="subtitle">▽広告1</span>
		<form action="./../layer.do" method="post">
			<input type="text" name="layername" value="commerce" />
			x:<input type="text" size="10" name="x" value="100" />
			y:<input type="text" size="10" name="y" value="50" />
			
			<input type="submit" value="実行" />
		</form>
	</div>
	<h2><a name ="ads">テスト2</a></h2>
	<div>
		<span id="subtitle">▽広告2</span>
		<form action="./../layer.do" method="post">
			<input type="text" name="layername" value="ads" />
			x:<input type="text" size="10" name="x" value="1" />
			y:<input type="text" size="10" name="y" value="5" />
			<input type="submit" value="実行" />
		</form>
	</div>
	

</body>
</html>


結果画面のhtmlを作成

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=Windows-31j">
  <link href="../../css/global.css" rel="stylesheet" type="text/css"></link>
  <script type="text/javascript" src="../../js/execute.js"></script>
</head>
<body>


<div id="devResultbody">

	結果=<span id="resultValue"></span>

</div>

</body>
</html>


結果画面のmayaaを作成

<?xml version="1.0" encoding="Shift_JIS"?>
<m:mayaa xmlns:m="http://mayaa.seasar.org"
        xmlns:html="http://struts.apache.org/tags-html"
        xmlns:bean="http://struts.apache.org/tags-bean"
        m:noCache="true">

	<m:doRender m:id="devResultbody" name="devResultbody" replace="true" />
    <m:write m:id="resultValue" value="${ result }" />
    
</m:mayaa>