kuniku’s diary

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

s2struts1.2のsubmitタグの動作でのforwardがうまくいかない

S2 framework-2.3.23
S2struts-1.2.12

を使用することになったので、いろいろと検証しているのだけれども、ちょっと上手くいっていない。

(スーツな人たちが、このフレームワークのバージョンを指定してきた、個人的にはhotdeploy可能なs2struts1.3またはSAStrutsがよいのだけれども、使ったことがないから、このバージョンになったとか聞いた。)

S2Strutsタグライブラリを使用して、

以下のようなサブミット時に実行するコンポーネントとメソッドを指定する事が可能とのことで

Actionクラスが異なっても、メソッドが実行できると思って、楽に使えるのではないか?と思いためしてみた。1つの画面に進んで来る場合と戻ってくる場合を1つのAtionで別々のメソッドで実行できばいいかなと考えた。戻り先を動的に変更したいと思ってね。

<html:form action="/hoge1">
  <s2struts:submit action="#{hoge1Action.execute}"><bean:message key="toNext"/></s2struts:submit>
  <s2struts:submit action="#{hoge2Action.execute}"><bean:message key="toBack"/></s2struts:submit>
</html:form>

として、submitで、それぞれのActionは実行される(デバッグにて確認済)。 hoge1Action.executeは問題なく動作できる。しかし、hoge2Actionにおいてforwardがうまくいかない。うまくいかないっていうのは、ログでは以下のように出力される。

WARN org.apache.struts.action.ActionMapping - Unable to find 'success2' forward.

struts-config.xmlでは、以下のようになっていて、リクエスト処理自体はデバッグにて確認済みの hoge2Action.executeが実行され、hoge2Action.executeでは、return "success2"を戻しているのだけれども、最終的なforward時にaction=/hoge1 というリクエストに基づいて /hoge1 での forward先にsuccess2が存在していなくて、forwardがうまくいっていない。

<action path="/hoge1"
 type="jp.co.samples.web.action.hoge1Action"
 name="hogeForm"
 scope="request"
 validate="false">
 <forward name="success" path="/jsp/hoge1.jsp" />
</action>
<action path="/hoge2"
 type="jp.co.samples.web.action.hoge2Actionn"
 name="bForm"
 scope="request"
 validate="false">
 <forward name="success2" path="/jsp/hoge2.jsp" />
</action>

なんとか、できないものなのかな〜。もしかしてS2Strutsタグライブラリでは、

S2Struts1.3.0-RC3以降では、指定したコンポーネントに対応するActionMappingが使用されます。

とあるけど、調べてないから何とも言えないけどs2struts1.3では、そのあたりが改良されていたりするのかな。

javaScript側で、hoge2のsubmit時にaction先を変更しないと無理なのか。

もしくは、共通用のActionを用意して、そのAction内で、それぞれのhoge1.doやhoge2.doにforwardさせるしかないのかな

例えば、jsp側でsubmitボタンのproperty="hoge1"をセットしておけばHttpServletRequestの getParameterMap()内にkeyとして、そのhoge1が存在するから、そのpropertyに対応するMapを用意しておき、そのMap 内からhoge1の遷移先のforwardを取り出すといった方法かな〜。でも、これだと設定が2箇所に分かれてしまう(forwardを管理するMap とstruts-config.xmlの両方に意識して設定しなきゃならん)。

例えばのsample

<form action="/hoge" name="baseForm">
  <html:submit property="hoge1" value="戻る"/>
  <html:submit property="hoge2" value="次へ"/>
</form>
<action path="/hoge"
    type="jp.co.samples.web.action.CommonAction"
    name="BaseForm"
    scope="request"
    validate="false">
      
    <forward name="hoge1" path="/hoge1.do" />
    <forward name="hoge2" path="/hoge2.do" />
    <forward name="hoge3" path="/hoge3.do" />
</action>

java系のsampleソース

public class CommonActionImpl implements CommonAction {

  private HttpServletRequest request;

  private CommonActionSortService commonActionSortService;

  public void setCommonActionSortService(CommonActionSortService commonActionSortService) {
    this.commonActionSortService = commonActionSortService;
  }

  public void setRequest(HttpServletRequest request) {
    this.request = request;
  }

  public String excute() {

    Map<String, String[]> requestParameterMap = request.getParameterMap();

	for (Map.Entry<String, String[]> entry : requestParameterMap.entrySet()) {

	  String forward = cmaCommonActionSortService.sort(entry.getKey());
	   // log.debug("key=" + entry.getKey() + " value=" + entry.getValue());

	   if (forward != null) {
	     return forward;
	   }
	}
	System.err.println("ERROR no-action-foward FORWARD先がありません。");
	return "index";
  }
}
public class CommonActionSortServiceImpl implements CommonActionSortService {

  private HashMap<String, String> forwardMap = new HashMap<String, String>();

  public String sort(String param) {
    
    if (forwardMap.containsKey(param)) {
	  return param;
    } else {
      return null;
    }

  }

  public void setForwardMap(HashMap<String, String> forwardMap) {
    this.forwardMap = forwardMap;
  }
}

2008-06-17追記
id:taedium さんの http://d.hatena.ne.jp/taedium/20080616/p1 
にてs2strutsを使用した場合の推奨パターンが記載されています。ポイントは、

基本的にjspとActionFormとActionとInitActionは1対1対1対1で作成

Forwardされた先のjspでは s2struts:init タグにより画面表示に必要な情報を取得するInitActionを呼び出します。

なのかな。ものすごーく参考になります。自分のやり方は、突貫工事のようでよろしくないですね。
こうゆう設計方針が、未熟者にとっては、リファレンスなどに記載してあると良いように思う。