S2StrutsをJSP1.2環境(Tomcat4.1)で使う -その6-

 最新のtrunkにあったs2-struts-1.2.1-SNAPSHOT.jarを利用してInitializeタグでFormをsessionに格納するパターンが問題ないことを確認しました。s2struts.diconが変更されているのに気づかずに試していて、POSTすると真っ白な画面でActionが実行されないで、ちょっとはまりました。s2struts.diconも差し替えればOKでした。
 id:kanag さんご対応頂きありがとうございました。

S2Daoを使っていて思ったこと

 S2Daoを使っていて、検索中心のDao(集計結果など)だとメソッド毎にBEANアノテーションが指定できたら良いのになぁと思いました。

public static final Class メソッド名_BEAN = JavaBeans名.class;

と定義したら、そのメソッドの戻り値は指定したJavaBeansまたは、そのListになるようなイメージです。
 Daoを分けるか、JavaBeansにプロパティを追加すれば良いのですが、同一テーブルへの処理はできれば同一のDaoに入れられた方が良いのではと思ったのと、更新対象ではない項目を更新処理を行うDaoのJavaBeansには何となく追加したくないという思いからです。
 この辺は皆さんはどう使われているのでしょうか?

【追記】
 ARGSアノテーションに引数名を記述する時に、その引数がJavaBeansのプロパティに存在しないとエラーになるのも気になりました。IN句を使いたかったので、エンティティに存在しない引数を指定してあれっとなりました。

DozerをDxoに適用する

 Java BeanマッピングライブラリであるDozerをS2StrutsアプリのDxoに適用してみました。Commons BeanUtilsと比べて何が優れているかまだ良くわかりませんが、とりあえず実験です。XMLの定義により細かなマッピング制御ができるようです。

事前準備

 http://sourceforge.net/project/showfiles.php?group_id=133517 からDozerをダウンロードします。distフォルダにdozer-2.0.1.jarがあるので、プロジェクトのクラスパスに追加します。
 また、下記のライブラリを利用しているので必要に応じて、クラスパスに追加します。

  • commons-beanutils.jar 1.7
  • commons-collections.jar 3.1
  • commons-lang.jar 2.1
  • commons-logging.jar 1.03
  • log4j.jar 1.2.8

dxo.diconファイルの作成

 dxo.diconを作成して、Dozerをコンポーネントとして登録します。


  
    {"dozerBeanMapping.xml"}
  


alldxo.diconファイルの作成

 プロジェクトで利用するdxoコンポーネントとして登録します。


  
  

  
    aop.traceInterceptor
  

@org.seasar.framework.container.deployer.InstanceDefFactory@SINGLETON "sample.dxo.impl" ".*DxoImpl" dxoInterceptorChain "sample.dxo.impl" ".*DxoImpl"


dozerBeanMapping.xmlファイルの作成

 マッピング情報を定義するdozerBeanMapping.xmlファイルを作成します。とりあえず、マッピングエラーを無視する設定にしています。


  
    false
  


Dxoインタフェースの作成

 Dtoの変換を行うDxoインタフェースを作成します。

public interface DataDxo {
    public void copyDtoToEntity(EntryDto entryDto, DataEntity dataEntity);
}


Dxoクラスの作成

 Dtoの変換を行うDxoクラスを作成します。

public class DataDxoImpl implements DataDxo {
    private MapperIF mapper;
    public void setMapper(MapperIF mapper) {
        this.mapper = mapper;
    }
    public void copyDtoToEntity(EntryDto entryDto, DataEntity dataEntity){
        mapper.map(entryDto, dataEntity);
    }
}

S2StrutsをJSP1.2環境(Tomcat4.1)で使う -その5-

 subversion上のtrunkにコミットされたソースをビルドして、ELInitializeTagクラスを元に戻しまして試しましたが同じ現象がおきています。ソースを見たところ、InitializeTagクラスに同じ記述を加えて頂いているようです。
 コメントには、Tomcat4.1の場合だとJSPServletでHttpServletRequestが異なるので再設定するとなっていますが、Tomcat4.1以外の方に影響はないのでしょうか。

 現象をもう少し詳しく書くと下記のようになります。

 1.入力画面呼び出し(entry.jsp)
 2.InitializeタグでEntryInitActionの呼び出し
  ・セッションに値がない場合は、フォームの初期値を設定
 3.入力画面の表示
  ※2で設定した値が表示されない
 4.データを入力しPOST
 5.EntryActionの呼び出し
  ・セッションに格納されたEntryDtoにデータが格納される
 6.確認画面の表示(confirm.jsp)
 7.確認画面から入力画面に戻る
 8.入力画面の再呼び出し
 9.InitializeタグでEntryInitActionの呼び出し
10.入力画面の表示
  ※5で設定した値が表示される

 10の時も表示されなければ前述の箇所が原因かもしれませんが、表示されてしまうのでやっぱり使い方が悪いのでしょうか。

【追記】
 EntryDtoがセッションに存在する場合は表示され、セッションにない場合は表示されないだけみたいです。InitActionにEntryDtoのgetterを作成してExportToSessionアノテーションをつけると表示されるようになりましたが、4でエラーになります。
 SingletonS2ContainerFactory.getContainer().setRequestをつけてもはずしても現象に関係ないようなので、原因としては違うようです。使い方が間違っているのかな・・・。

java.lang.ClassCastException
at org.seasar.struts.interceptors.ProcessPojoFormInterceptor.lookupPojoForm(ProcessPojoFormInterceptor.java:136)
at org.seasar.struts.interceptors.ProcessPojoFormInterceptor.createPojoForm(ProcessPojoFormInterceptor.java:115)
at org.seasar.struts.interceptors.ProcessPojoFormInterceptor.processPojoForm(ProcessPojoFormInterceptor.java:85)
at org.seasar.struts.interceptors.ProcessPojoFormInterceptor.invoke(ProcessPojoFormInterceptor.java:60)
at org.seasar.struts.processor.S2RequestProcessor$$EnhancedByS2AOP$$1d121c7$$MethodInvocation$$processActionForm0.proceed(MethodInvocationClassGenerator.java)
at org.seasar.struts.processor.S2RequestProcessor$$EnhancedByS2AOP$$1d121c7.processActionForm(S2RequestProcessor$$EnhancedByS2AOP$$1d121c7.java)
at org.seasar.struts.processor.AcceptorImpl.process(AcceptorImpl.java:87)
at org.seasar.struts.processor.S2RequestProcessor.process(S2RequestProcessor.java:59)

S2StrutsをJSP1.2環境(Tomcat4.1)で使う -その4-

 セッションスコープにあるPOJO FormにInitActionで値を入れても初期化されてしまう現象がおきています。(POJO Formのscopeをrequestにすると問題ない。)
 id:n-ichimura:20060124で、ELInitializeTagクラスのdoStartTagメソッドの最初に下記を追加したのが原因だと思うのですがあっているでしょうか。

SingletonS2ContainerFactory.getContainer().setRequest( (HttpServletRequest) this.pageContext.getRequest() );

 理由は、pageContext.getRequestの戻り値はServletRequestで、セッション情報が含まれていないので、S2Containerのセッションが消えてしまうのだろうと考えました。
 this.pageContext.getSession()の内容をsetRequestに含められれば良いのだと思いますが、うまくいきませんでした。

backport175にはまる

 なぜか特定のクラスだけbackport175アノテーションがうまく認識されない現象に悩まされました。何度もクリーンビルドなどしたのですが復旧できず。インタフェース名を変更後元の名前に戻したら、何故かeclipseのエディタ上は、アノテーションとして認識したものの、実際に実行しても無効のままでした。
 あきらめて帰宅し、家のPCで今再ビルドしたら、何の問題もなくアノテーションとして認識されているみたいです。何が違うのかわかりません。これで今日の何時間を無駄にしたのだろう・・・。

S2StrutsをJSP1.2環境(Tomcat4.1)で使う -その3-

 id:kanag さんのアドバイスのおかげで、今まで理解できない動きをしていた原因がわかってきました。ありがとうございました。
 Struts-elでは、bean:writeタグを提供しておらず、c:outを使いましょうとなっていたので利用していたのですが、全てのタグにdynaBean.instanceをつけないといけないとなると抵抗があります。

 対応策としては、下記でしょうか。
1.beanタグとbean-elタグを併用し、bean:writeタグを利用する。
2.bean:writeのel対応タグを作成し、それを利用する。
3.c:outでdynaBean.instanceを記述する。

 どれにしても、開発者が混乱しそうだし、なんか今ひとつしっくりこない感じ。そうはいっても、早く方針出さないと進まないので案1かな。

 もう既に、JSP1.2環境を利用されている方があまりいないのか情報が少ないですね。Oracle Application Serverを利用しているのですが、まだJ2EE 1.3対応でJSP1.2環境というのがネックです。はやくJ2EE1.4対応版出てくれないかな?

【追記】
 結局struts-elのソースにel対応したbean:writeタグを追加して対応しました。こうしておけば、JSP2.0環境への移行時にJSPの中身をいじらなくても良いのと、開発者もタグを使い分けなくても良いのでわかりやすいというのが理由です。