前回に引き続き、Validator。今回は、自前のカスタムValidatorを作るときどうするかっていう、備忘録です。

もし、あるDBの項目で重複を許したくない場合(ユニークチェックですね)を例として取り上げます。

環境はTeeda + DBFluteを想定し、EMPテーブルのidという項目の重複がある場合にエラーとなる場合です。

まずは、javax.faces.validator.Validatorインターフェースを継承したMyEmpDuplicateValidatorクラスを作成します。場所はDoltengであらかじめ作成されているvalidatorというディレクトリに置きました。

MyEmpDuplicateValidator.java

JAVA:
  1. package examples.teeda.validator;
  2.  
  3. import javax.faces.FacesException;
  4. import javax.faces.application.FacesMessage;
  5. import javax.faces.component.EditableValueHolder;
  6. import javax.faces.component.UIComponent;
  7. import javax.faces.context.FacesContext;
  8. import javax.faces.internal.FacesMessageUtil;
  9. import javax.faces.internal.UIComponentUtil;
  10. import javax.faces.internal.UIInputUtil;
  11. import javax.faces.validator.Validator;
  12. import javax.faces.validator.ValidatorException;
  13.  
  14. import org.seasar.framework.container.annotation.tiger.Binding;
  15. import org.seasar.framework.container.annotation.tiger.BindingType;
  16. import org.seasar.framework.util.AssertionUtil;
  17.  
  18. import examples.teeda.dbflute.cbean.EmpCB;
  19. import examples.teeda.dbflute.exbhv.EmpBhv;
  20.  
  21. public class MyEmpDuplicateValidator implements Validator {
  22.     private static final String MESSAGE_ID = "examples.teeda.validator.EmpDuplicateValidator.INVALID";
  23.     @Binding(bindingType = BindingType.MUST)
  24.     public EmpBhv empBhv;
  25.    
  26.     public void validate(FacesContext context, UIComponent component,
  27.             Object value) throws FacesException {
  28.         // nullな場合無視します。
  29.         AssertionUtil.assertNotNull("context", context);
  30.         AssertionUtil.assertNotNull("component", component);
  31.         if (UIInputUtil.isEmpty(value)){
  32.             return;
  33.         }
  34.         final String s = value.toString();
  35.  
  36.         // EMPテーブルのid項目に対して件数を取得しています。
  37.         FeedCB cb = new FeedCB();
  38.         cb.query().setId_Equal(s);
  39.         int count = empBhv.selectCount(cb);
  40.         if (count> 0){
  41.             final Object submittedValue = EditableValueHolder.class.cast(component).getSubmittedValue();
  42.             final Object[] args = { UIComponentUtil.getLabel(component),submittedValue};
  43.             final FacesMessage message = FacesMessageUtil.getMessage(context, MESSAGE_ID, args);
  44.             throw new ValidatorException(message, MESSAGE_ID, args);
  45.         }
  46.     }
  47. }

validateメソッドを実装します。その中で、DBにアクセスする必要があるので、DBFluteのBehaviorをInjectさせて、件数を取得し、件数がある場合に、JSFの作法にのっとり、ValidatorExceptionをthrowしてます。

また、MESSAGE_IDで指定した、文言がエラーとして出力されるので、resourcesのpropertyファイルに追記しておきます。

appMessages_ja.properties

CODE:
  1. examples.teeda.validator.EmpDuplicateValidator.INVALID = IDが重複しています。

そして、アノテーションを使えるようにするためにインターフェースを作成します。場所は上記と同じ場所に配置しました。

EmpDuplicateValidator.java

JAVA:
  1. package examples.teeda.validator;
  2.  
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7.  
  8. import org.seasar.teeda.extension.annotation.validator.Validator;
  9.  
  10. @Retention(RetentionPolicy.RUNTIME)
  11. @Target({ ElementType.FIELD, ElementType.METHOD})
  12. @Validator("myEmpDuplicateValidator")
  13. public @interface EmpDuplicateValidator {
  14. }

これで、Pageクラスなどで

JAVA:
  1. @EmpDuplicateValidator
  2. public String id;

と書くだけで、重複チェックが行われるわけです。

少しややこしいように見えますが、一度やってしまうと簡単にカスタムValidatorが作れます。便利ですね。

blogranking←ぽちっとな