PGBox
P
G
Box

カスタムタグの作成【動的なタグの検証とスクリプト変数の定義】

JSPのメニューへ戻る



使用した環境
JDK 6 Update 11
Tomcat 6.0.18

TagExtraInfo(tei-class)を作成する事により、タグのtldだけでは検証しきれない相関的な属性値の検証や、動的にスクリプト変数を定義する事が可能です。



属性値の検証

例えば、カスタムタグに「属性A」「属性B」があり、そのどちらか一方のみが必須である場合
tldの<tag><attribute><required>だけではチェックしきれません。

この場合、TagExtraInfoを継承したクラスを作成する事により厳密にチェックを行う事が可能となります。


例えば、以下のようなカスタムタグがあり
package sample;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * サンプルのタグクラス
 */
public class SampleTag extends TagSupport {
    
    private String attrA;
    
    private String attrB;
    
    @Override
    public int doStartTag() throws JspException {
        
        // ** タグの処理 **
        
        return SKIP_BODY;
    }

    public void setAttrA(String attrA) {
        this.attrA = attrA;
    }
    public void setAttrB(String attrB) {
        this.attrB = attrB;
    }
}

attrAとattrBどちらか一方のみを必須にしたい場合、
以下のようなTagExtraInfoを継承したteiクラスを作成します。

package sample;

import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.ValidationMessage;

/**
 * SampleTagの属性値に対するチェックを行う
 */
public class SampleTei extends TagExtraInfo {

    // タグ属性値の検証を行う
    @Override
    public ValidationMessage[] validate(TagData data) {
        
        // タグ属性値に対してチェックを行う
        if (!isValid(data)) {
            
            // 検証エラーの場合はエラーメッセージを返す
            ValidationMessage message =
                new ValidationMessage(data.getId(), "attrAとattrBのどちらかは必須です。");
            
            return new ValidationMessage[] { message };
            
        }
        
        // エラーがない場合はnullを返す
        return null;
    }

    // タグ属性値の値が正常な場合にtrueを返す
    @Override
    public boolean isValid(TagData data) {
        
        // 属性の値を取得
        String attrA = (String) data.getAttribute("attrA");
        String attrB = (String) data.getAttribute("attrB");
        
        // paramAとparamBの両方がnullの場合は検証エラー
        if (attrA == null && attrB == null) {
            return false;
        }
        
        return true;
    }
}


validateメソッドをオーバーライドする事で、独自のエラーメッセージを記述する事が可能となります。
また、isValidメソッドでは実際に検証を行い、結果をbooleanで返します。


tldファイルでは、以下のように<tei-class>の記述を追加します。
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xml="http://www.w3.org/XML/1998/namespace"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
          version="2.1">
      
      <tag>
        <name>sample</name>
        <tag-class>sample.SampleTag</tag-class>
        <tei-class>sample.SampleTei</tei-class>
        
        <body-content>empty</body-content>
        <attribute>
            <name>attrA</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>attrB</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        
    </tag>

</taglib>
tldファイルの詳細な情報についてはtldファイルを参照してください。


以上で独自のチェック処理が行われるようになります。


JSPで以下の記述はエラーとはなりませんが
<xxx:sample attrA="aaa" />
<xxx:sample attrB="bbb" />
<xxx:sample attrA="aaa" attrB="bbb" />

以下のような記述を行うと、JSPコンパイルエラーが発生するようになります。
<xxx:sample />

ちなみに、このサンプルを作成しているtomcatのバージョンでは以下のようなエラーメッセージが表示されます。
※ 改行は見やすいように調整してあります。
org.apache.jasper.JasperException: /sample.jsp(4,0) 
    <h3>sample:sample に対するTagExtraInfoからの検証エラーメッセージです</h3>
    <p>attrAとattrBのどちらかは必須です。</p>



動的にスクリプト変数を定義する

スクリプト変数の概要についてはカスタムタグの作成【スクリプト変数】を参照してください。

tldファイルでスクリプト変数の使用を定義した場合、スクリプト変数の名前や型はあらかじめ決めておく必要があります。
TagExtraInfoを継承したteiクラスを作成する事により、これらの要素を動的に決定する事が可能となります。


まず、TagExtraInfoを継承したクラスを作成します。
package sample;

import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.VariableInfo;

/**
 * 動的にスクリプト変数を定義する
 */
public class SampleVarialbleTei extends TagExtraInfo {

    // スクリプト変数の情報を返す
    @Override
    public VariableInfo[] getVariableInfo(TagData data) {
        
        // Integer型のスクリプト変数「sampleVar」の情報    
        VariableInfo variableInfo =
            new VariableInfo("sampleVar", "java.lang.Integer", true, VariableInfo.AT_BEGIN);

        // 配列で返す
        return new VariableInfo[] { variableInfo };
    }
    
}
getVariableInfoメソッドをオーバーライドする事により、スクリプト変数の情報を独自に作成して返す事が可能となります。

VariableInfoのコンストラクタ引数には、それぞれ以下の情報を指定します。
new VariableInfo(変数の名前, 変数の型, 新しい変数として定義する場合にtrue, スクリプト変数のスコープ);


対となるタグクラスでは、以下のようにしてスクリプト変数の値をセットします。
package sample;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

public class SampleVariableTag extends TagSupport {
    
    @Override
    public int doStartTag() throws JspException {
        
        // スクリプト変数をセットする
        pageContext.setAttribute("sampleVar", 123);
        
        return SKIP_BODY;
    }
    
}


tldファイルでは、以下のように<tei-class>の記述を追加します。
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xml="http://www.w3.org/XML/1998/namespace"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
          version="2.1">
      
      <tag>
        <name>sampleVariable</name>
        <tag-class>sample.SampleVariableTag</tag-class>
        <tei-class>sample.SampleVarialbleTei</tei-class>
        <body-content>empty</body-content>
    </tag>

</taglib>
tldファイルの詳細な情報についてはtldファイルを参照してください。


JSPでは、以下のようにして動的に定義したスクリプト変数を使用する事が可能です。
<%@ page contentType="text/html; charset=Windows-31J" pageEncoding="Windows-31J" %>
<%@ taglib uri="/sample" prefix="sample" %>

<sample:sampleVariable />
<%= sampleVar %>





JSPのメニューへ戻る