S2Struts1.2.0-EA4での新規Validationの追加

ここで書くべきことじゃないけど、ないよりかあったほうが良いと思ったので。



S2Struts1.2.0-EA4ではアノテーションを利用してValidationを設定できます。
新規のValidationを追加するにはアノテーションを作成する等の作業を行う必要があります。
Maxbytelength、MinbytelengthアノテーションS2Struts独自のValidationですので、新規Validation作成の参考になります。


S2StrutsExample1.2.0-EA4に2つの入力内容が同じか検証するValidationを追加する作業を通して、新規Validationの追加方法を説明します。
Struts Validator Guide(http://struts.apache.org/userGuide/dev_validator.html)に、Strutsでの新規Validationを追加する方法が記述されています。こちらも参考にしてください。


Struts(commons validator)での作業

Struts(commons validator)としての新規Validationを追加するには、

  • 検証用クラスの作成
  • validator-rules.xmlへ設定情報の追加

を行います。


2つの入力内容が同じか検証するクラスは以下のようになります。

package org.seasar.struts.examples.validator;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.validator.Field;
import org.apache.commons.validator.GenericValidator;
import org.apache.commons.validator.Validator;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.util.ValidatorUtils;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.validator.Resources;

public class FieldChecks {

    public static boolean validateTwoFields(Object bean,
            ValidatorAction validatorAction, Field field,
            ActionMessages errors, Validator validator,
            HttpServletRequest request) {

        String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        String sProperty2 = field.getVarValue("secondProperty");
        String value2 = ValidatorUtils.getValueAsString(bean, sProperty2);

        if (!GenericValidator.isBlankOrNull(value)) {
            try {
                if (!value.equals(value2)) {
                    errors.add(field.getKey(), Resources.getActionMessage(
                            validator, request, validatorAction, field));

                    return false;
                }
            } catch (Exception e) {
                errors.add(field.getKey(), Resources.getActionMessage(
                        validator, request, validatorAction, field));
                return false;
            }
        }

        return true;
    }
}

次に上記のクラスをvalidator-rules.xmlに追加します。
validatorタグのname属性(validator name)に指定する内容は、アノテーション名と関連があります。
S2Strutsでは以下の規則によりアノテーション名を変換しvalidator nameと一致するか判断して特定しています。

例えば、Hogeアノテーションの場合のvalidator nameは"hoge"となり、FooTypeアノテーションの場合のvalidator nameは"foo"となります。


今回はアノテーション名をTwoFieldsとするためnameは"twoFields"とします。
validator-rules.xml

      <validator name="twoFields"
            classname="org.seasar.struts.examples.validator.FieldChecks"
               method="validateTwoFields"
         methodParams="java.lang.Object,
                       org.apache.commons.validator.ValidatorAction,
                       org.apache.commons.validator.Field,
                       org.apache.struts.action.ActionMessages,
                       org.apache.commons.validator.Validator,
                       javax.servlet.http.HttpServletRequest"
              depends=""
                  msg="errors.twoFields"/>

msg属性に"errors.twoFields"と指定したので、このメッセージKeyをapplication.propertiesに追加します。

errors.twoFields={0} has to have the same value as the confirm field.

ここまでがStrutsでの新規Validation追加作業です。


S2Strutsでの作業

S2Strutsに新規Validationを追加する場合は、

を行う必要があります。

Valiadtionのアノテーションにはメタアノテーションとしてorg.seasar.struts.validator.annotation.ValidatorTargetを指定します。
TwoFieldsアノテーションは以下のようになります。

package org.seasar.struts.examples.validator.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.seasar.struts.validator.annotation.ValidatorTarget;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ValidatorTarget
public @interface TwoFields {

    String secondProperty();

}

次に上記アノテーションを登録するためのConfigRegisterとしてTwoFieldsConfigRegisterImplを作成します。
TwoFieldsConfigRegisterImplは、org.seasar.struts.validator.config.ConfigRegisterを実装します。
registメソッドの引数はfieldとparameterです。
parameterは、アノテーションで定義したメソッド名をkey、メソッドの戻り値をvalueとしたMapです。

package org.seasar.struts.examples.validator.config;

import java.util.Map;

import org.apache.commons.validator.Field;
import org.apache.commons.validator.Var;
import org.seasar.struts.validator.config.ConfigRegister;

public class TwoFieldsConfigRegisterImpl implements ConfigRegister {

    public void regist(Field field, Map parameter) {
        String secondProperty = (String) parameter.get("secondProperty");

        Var var = new Var();
        var.setName("secondProperty");
        var.setValue(secondProperty);
        field.addVar(var);
    }

}

ConfigRegisterはコンポーネントとして登録する必要があります。
登録するときのコンポーネント名は、validator nameのときと同様のアノテーション名変換を行い"ConfigRegister"を付け加えた名前となります。
例えば、Hogeアノテーションの場合は"hogeConfigRegister"となり、FooTypeアノテーションの場合は"fooConfigRegister"となります。


今回はコンポーネントとして登録するために新規でallvalidator.dionを作成します。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
	"http://www.seasar.org/dtd/components21.dtd">
<components>
	<component name="twoFieldsConfigRegister" class="org.seasar.struts.examples.validator.config.TwoFieldsConfigRegisterImpl"/>
</components>

そしてapp.diconにincludeを追加して、allvalidator.dionを読み込むようにします。

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

これで新規Validation追加作業は終了です。

動作確認

今回作成したTwoFieldsアノテーションを試すには、

  • Actionの作成
  • Form(Dto)の作成
  • JSPの作成

を行う必要があります。


まずActionの作成ですが、今回はPOJOのActionで無設定機能をフルに使います。
Actionのインターフェースと実装は以下のようになります。

package org.seasar.struts.examples.validator;

public interface TwoFieldsAction {
    
    String execute();

}
package org.seasar.struts.examples.validator;

public class TwoFieldsActionImpl implements TwoFieldsAction {

    public String execute() {
        return "success";
    }

}

無設定機能をフルに利用するので、StrutsActionアノテーション、StrutsActionForwardアノテーションは不要です。
Actionの処理は"success"を返すだけですがTwoFieldsアノテーションの動作確認には十分です。


Actionはコンポーネントとして登録する必要があります。
S2.3の自動登録機能を利用すれば毎回diconファイルを作る必要はなくなるのですが、S2StrutsExampleがまだ対応していないので、個別に登録することにします。。。
新規に作成したtwoFields.diconは以下のようになります。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
	"http://www.seasar.org/dtd/components21.dtd">
<components>
	<component class="org.seasar.struts.examples.validator.TwoFieldsActionImpl" />
</components>

そしてapp.diconにincludeを追加して、twoFields.diconを読み込むようにします。

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


次はForm(Dto)を作成します。

package org.seasar.struts.examples.validator;

import java.io.Serializable;

import org.seasar.struts.examples.validator.annotation.TwoFields;
import org.seasar.struts.validator.annotation.Args;
import org.seasar.struts.validator.annotation.Required;

public class TwoFieldsDto implements Serializable {

    private String field = "";

    private String confirmField = "";

    public String getField() {
        return field;
    }

    @Required
    @TwoFields(secondProperty="confirmField")
    @Args(keys = "Field", resource = false)
    public void setField(String field) {
        this.field = field;
    }

    public String getConfirmField() {
        return confirmField;
    }

    @Required
    public void setConfirmField(String confirmField) {
        this.confirmField = confirmField;
    }

}

Form(Dto)も無設定機能をフルに利用しますので、StrutsActionFormアノテーションは不要ですが、Validation関連のアノテーションを指定するのを忘れないようにしましょう。


最後にJSPを作成します。
TwoFieldsActionに自動的にforward設定されるようにするため、JSP名はtwoFields.jspとしてpagesディレクトリに作成します。

<%@ page contentType="text/html;charset=Windows-31j" language="java" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<%@ taglib uri="http://www.seasar.org/tags-s2struts" prefix="s2struts" %>

<tiles:insert page="/pages/layout/layout.jsp">
    <tiles:put name="layoutTitle" type="string">
        Two Fields Check
    </tiles:put>

    <tiles:put name="body" type="string">

        <html:errors />

        <html:form action="/twoFields" method="POST">
        <s2struts:page/>

        <table>
            <tr>
                <td>field</td>
                <td><html:text property="field" styleClass="text" errorStyleClass="text-error"/></td>
            </tr>
            <tr>
                <td>confirm field</td>
                <td><html:text property="confirmField" styleClass="text" errorStyleClass="text-error"/></td>
            </tr>
        </table>

        <html:submit/>
        </html:form>

    </tiles:put>
</tiles:insert>

ここでのポイントはs2struts:pageタグを利用しているところです。
これにより、TwoFieldsActionでinputを指定していなくても検証エラーのときにこのJSPを再表示します。


これで動作確認する準備ができました。
Tomcatを起動して、
http://localhost:8080/s2struts-example/pages/twoFields.jsp
にアクセスし、動作を確認してください。


新規のValidationを追加する作業はちょっと大変ですが、一度追加すれば簡単にForm(Dto)で使えるようになると思います。