Nablarchのドメインバリデーションを使用して入力値をチェックする

TISでは、豊富な基幹システム構築経験から得られたナレッジを集約したJavaアプリケーション開発/実行基盤として Nablrch を提供しています。 SpringからNablarchの機能を利用することで、Springに不足している機能を補うことができます。

この例では、Nablarchの機能である ドメインバリデーション を使用して、入力値をチェックする実装方法を説明します。

ドメインバリデーションを使用することで、Nablarchが提供するバリデーターの使用や、Beanにドメイン名を指定するだけでバリデーションを設定することができます。Beanごとにバリデーションのルールを定義する必要がないため、ルールの変更が容易になります。

サンプルコードの動作確認環境については、 動作確認環境と依存ライブラリについて を参照してください。

サンプル全体は nablarch-validation を参照してください。

Nablarchを使用するための準備

pom.xml

Nablarchのモジュールバージョンを管理するために、dependencyManagementにnablarch-bomを追加します。

  <dependency>
    <groupId>com.nablarch.profile</groupId>
    <artifactId>nablarch-bom</artifactId>
    <version>6</version>
    <type>pom</type>
    <scope>import</scope>
  </dependency>

ドメインバリデーションを使うため、依存ライブラリにnablarch-core-validation-eeとnablarch-main-default-configurationを追加します。

<!-- Nablarch:ドメインバリデーション -->
<dependency>
  <groupId>com.nablarch.framework</groupId>
  <artifactId>nablarch-core-validation-ee</artifactId>
</dependency>
<!-- Nablarch:文字種設定をNablarchデフォルト設定から読み込む -->
<dependency>
  <groupId>com.nablarch.configuration</groupId>
  <artifactId>nablarch-main-default-configuration</artifactId>
</dependency>

Tip

Nablarchでは独自のログ出力機能を提供していますが、別のログライブラリを使用するためのアダプタが提供されています。この例では、SLF4Jを使用するためのアダプタである nablarch-slf4j-adaptor を使用しています。 詳細は logアダプタ を参照してください。

バリデーションルールの設定

ドメイン毎のバリデーションルールを設定するためドメインBeanを作成し、有効化します。

DomainBean
/**
 * ドメインのバリデーションルール。
 */
public class DomainBean {

    /** ID **/
    @Digits(integer = 4, fraction = 0)
    public String id;

    /** 名前 **/
    @Length(max = 10)
    @SystemChar(charsetDef = "全角文字")
    public String name;

    /** 年齢 **/
    @NumberRange(min = 0, max = 100)
    public String age;

    /** 備考 **/
    @Length(max = 10)
    @SystemChar(charsetDef = "システム許容文字")
    public String note;
}

作成したドメインBeanをNablarchで使えるようにするため、 DomainManager の実装クラスを作成します。

ExampleDomainManager
/**
 * DomainManager実装クラス。
 */
public class ExampleDomainManager implements DomainManager<DomainBean> {

    @Override
    public Class<DomainBean> getDomainBean() {
        return DomainBean.class;
    }
}

ドメインバリデーションを動作させるための設定

Nablarchのドメインバリデーションは、NablarchのDIコンテナ機能を使用して動作するようになっています。Nablarchにはドメインバリデーションを動作させるための設定が組み込まれていますが、Springからそのまま使用することは出来ないため、Nablarchに組み込まれている設定と同等の設定をSpring側で行います。

Nablarchのドメインバリデーションを動作させるには、NablarchのDIコンテナであるシステムリポジトリを設定する必要があります。バリデーションルールの設定時に作成した DomainManager の実装クラスや、その他に必要なクラスを作成し、システムリポジトリに登録します。

ValidationConfiguration
    /**
     * ValidationSystemRepositoryLoaderを構築する。
     * 
     * @param localValidatorFactoryBean {@link Validator}実装クラスのインスタンス
     * @return 構築されたインスタンス
     */
    @Bean
    public ValidationSystemRepositoryLoader validationSystemRepositoryLoader(LocalValidatorFactoryBean localValidatorFactoryBean) {
        return new ValidationSystemRepositoryLoader(localValidatorFactoryBean);
    }
ValidationSystemRepositoryLoader
/**
 * バリデーション機能に必要なインスタンスを{@link SystemRepository}へ登録するクラス。
 */
public class ValidationSystemRepositoryLoader implements InitializingBean {

    /**
     * {@link Validator}実装クラスのインスタンス
     */
    private final LocalValidatorFactoryBean localValidatorFactoryBean;

    /**
     * コンストラクタ。
     *
     * @param localValidatorFactoryBean {@link Validator}実装クラスのインスタンス
     */
    public ValidationSystemRepositoryLoader(LocalValidatorFactoryBean localValidatorFactoryBean) {
        this.localValidatorFactoryBean = localValidatorFactoryBean;
    }

    @Override
    public void afterPropertiesSet() {
        SystemRepository.load(() -> Map.of(
                "domainManager", new ExampleDomainManager(),
                "validatorFactoryBuilder", new ValidatorFactoryBuilderImpl(localValidatorFactoryBean)));
    }
}
ValidatorFactoryBuilderImpl
/**
 * 特定の{@link Validator}実装クラスを返す{@link ValidatorFactoryBuilder}サブクラス。
 */
public class ValidatorFactoryBuilderImpl extends ValidatorFactoryBuilder implements ValidatorFactory {

    /**
     * {@link Validator}実装クラスのインスタンス
     */
    private final LocalValidatorFactoryBean localValidatorFactoryBean;

    /**
     * コンストラクタ。
     * 
     * @param localValidatorFactoryBean {@link Validator}実装クラスのインスタンス
     */
    public ValidatorFactoryBuilderImpl(LocalValidatorFactoryBean localValidatorFactoryBean) {
        this.localValidatorFactoryBean = localValidatorFactoryBean;
    }

    @Override
    protected ValidatorFactory build() {
        return this;
    }

    @Override
    public Validator getValidator() {
        return localValidatorFactoryBean;
    }

    @Override
    public void close() {
    }

    @Override
    public ValidatorContext usingContext() {
        // ドメインバリデーションで使用しない部分については UnsupportedOperationException を送出する実装にしておく
        throw new UnsupportedOperationException();
    }

    @Override
    public MessageInterpolator getMessageInterpolator() {
        throw new UnsupportedOperationException();
    }

    @Override
    public TraversableResolver getTraversableResolver() {
        throw new UnsupportedOperationException();
    }

    @Override
    public ConstraintValidatorFactory getConstraintValidatorFactory() {
        throw new UnsupportedOperationException();
    }

    @Override
    public ParameterNameProvider getParameterNameProvider() {
        throw new UnsupportedOperationException();
    }

    @Override
    public ClockProvider getClockProvider() {
        throw new UnsupportedOperationException();
    }

    @Override
    public <T> T unwrap(Class<T> type) {
        throw new UnsupportedOperationException();
    }
}

サンプルでは文字種バリデーションを使用しますが、Nablarchでは文字種定義をデフォルト設定として提供しています。ここではデフォルト設定を使用するため、対応するプロパティ値をバインドするためのBeanを定義します。

CharsetDefProperties
/**
 * Nablarchデフォルト設定に含まれる文字種の定義を読み込むためのProperties。
 */
public class CharsetDefProperties {

    /** 半角数字 */
    private CharsetDef numericCharset = new LiteralCharsetDef();

    /** 半角英小文字 */
    private CharsetDef lowerAlphabetCharset = new LiteralCharsetDef();

    /** 半角英大文字 */
    private CharsetDef upperAlphabetCharset = new LiteralCharsetDef();

    /** ASCII記号 */
    private CharsetDef asciiSymbolCharset = new LiteralCharsetDef();

    /** 全角スペース */
    private CharsetDef zenkakuSpaceCharset = new LiteralCharsetDef();

    /** 半角カナ */
    private CharsetDef hankakuKanaCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる全角英字 */
    private CharsetDef zenkakuAlphaCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる全角数字 */
    private CharsetDef zenkakuNumCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる全角ギリシャ文字 */
    private CharsetDef zenkakuGreekCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる全角ロシア文字 */
    private CharsetDef zenkakuRussianCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる全角ひらがな */
    private CharsetDef zenkakuHiraganaCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる全角カタカナ */
    private CharsetDef strictZenkakuKatakanaCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる全角記号 */
    private CharsetDef jisSymbolCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる全角罫線 */
    private CharsetDef zenkakuKeisenCharset = new LiteralCharsetDef();

    /** JIS第1水準に含まれる漢字 */
    private CharsetDef level1KanjiCharset = new LiteralCharsetDef();

    /** JIS第2水準漢字 */
    private CharsetDef level2KanjiCharset = new LiteralCharsetDef();

    /** NEC選定IBM拡張 */
    private CharsetDef necExtendedCharset = new LiteralCharsetDef();

    /** NEC特殊文字 */
    private CharsetDef necSymbolCharset = new LiteralCharsetDef();

    /** IBM拡張文字 */
    private CharsetDef ibmExtendedCharset = new LiteralCharsetDef();

    // (アクセサの記載は省略します)
ValidationConfiguration
    /**
     * CharsetDefPropertiesを構築する。
     * 
     * @return 構築されたインスタンス
     */
    @Bean
    @ConfigurationProperties("nablarch")
    public CharsetDefProperties charsetDefProperties() {
        return new CharsetDefProperties();
    }

文字種バリデーションを動作させるため、プロパティ値をバインドしたBeanを使用して必要な設定を行い、Nablarchのシステムリポジトリに登録します。

ValidationConfiguration
    /**
     * CharsetDefSystemRepositoryLoaderを構築する。
     *
     * @param properties CharsetDefProperties
     * @return 構築されたインスタンス
     */
    @Bean
    public CharsetDefSystemRepositoryLoader charsetDefSystemRepositoryLoader(CharsetDefProperties properties) {
        return new CharsetDefSystemRepositoryLoader(properties);
    }
CharsetDefSystemRepositoryLoader
/**
 * 文字種バリデーション機能に必要なインスタンスを{@link SystemRepository}へ登録するクラス。
 */
public class CharsetDefSystemRepositoryLoader implements InitializingBean {

    /**
     * Nablarchデフォルト設定に含まれる文字種の定義を読み込むためのProperties
     */
    private final CharsetDefProperties properties;

    /**
     * コンストラクタ。
     * 
     * @param properties Nablarchデフォルト設定に含まれる文字種の定義を読み込むためのProperties
     */
    public CharsetDefSystemRepositoryLoader(CharsetDefProperties properties) {
        this.properties = properties;
    }

    @Override
    public void afterPropertiesSet() {
        // 半角スペース
        RangedCharsetDef halfWidthSpace = new RangedCharsetDef();
        halfWidthSpace.setStartCodePoint("U+0020");
        halfWidthSpace.setEndCodePoint("U+0020");

        // 半角英数字
        CompositeCharsetDef alphabetsAndNumbers = new CompositeCharsetDef();
        alphabetsAndNumbers.setCharsetDefList(List.of(
                properties.getNumericCharset(),
                properties.getLowerAlphabetCharset(),
                properties.getUpperAlphabetCharset()));

        // ASCII文字
        CompositeCharsetDef asciiCharset = new CompositeCharsetDef();
        asciiCharset.setCharsetDefList(List.of(
                alphabetsAndNumbers,
                properties.getAsciiSymbolCharset()));

        // 全角文字
        CompositeCharsetDef zenkakuCharset = new CompositeCharsetDef();
        zenkakuCharset.setCharsetDefList(List.of(
                properties.getZenkakuHiraganaCharset(),
                properties.getStrictZenkakuKatakanaCharset(),
                properties.getZenkakuAlphaCharset(),
                properties.getZenkakuNumCharset(),
                properties.getZenkakuGreekCharset(),
                properties.getZenkakuRussianCharset(),
                properties.getJisSymbolCharset(),
                properties.getZenkakuKeisenCharset(),
                properties.getLevel1KanjiCharset(),
                properties.getLevel2KanjiCharset(),
                properties.getZenkakuSpaceCharset()));

        // システム許容文字
        CompositeCharsetDef systemAllowedCharset = new CompositeCharsetDef();
        systemAllowedCharset.setCharsetDefList(List.of(
                asciiCharset,
                zenkakuCharset,
                properties.getHankakuKanaCharset(),
                halfWidthSpace));

        SystemRepository.load(() -> Map.of(
                "半角数字", properties.getNumericCharset(),
                "半角英数", alphabetsAndNumbers,
                "ASCII文字", asciiCharset,
                "全角文字", zenkakuCharset,
                "システム許容文字", systemAllowedCharset));
    }
}

ドメインバリデーションの使用例

Nablarchが提供するバリデーターでは、メッセージを定義するためプロパティ名がデフォルトで設定されているため、使用するバリデーターに合わせてメッセージを定義します。

バリデータで使用するプロパティ名は、Nablarchのデフォルト設定として定義されています。Nablarchのデフォルト設定の詳細については デフォルト設定一覧 を参照してください。

型変換エラー時に表示するメッセージの設定については、 入力値の型変換エラー時に入力画面に適切なメッセージを表示する を参照してください。

message.properties
nablarch.core.validation.ee.Required.message=入力してください。
nablarch.core.validation.ee.Digits.integer.message=数値を入力してください。
nablarch.core.validation.ee.NumberRange.min.max.message={min}以上{max}以下の数値を入力してください。
nablarch.core.validation.ee.Length.max.message={max}以下の文字数で入力してください。
nablarch.core.validation.ee.SystemChar.message=入力できない文字が含まれています。

typeMismatch.java.lang.Integer=数値を入力してください。

Controllerで受け取るBeanのプロパティに対して、 @Domain アノテーションで対応するドメイン名を指定します。Springでバリデーションが実行される際、ドメインBeanに設定したバリデーションルールに従ってバリデーションが実行されます。

ValidationForm
public class ValidationForm {

    @Required
    @Domain("id")
    private Integer id;

    @Required
    @Domain("name")
    private String name;

    @Required
    @Domain("age")
    private Integer age;

    @Domain("note")
    private String note;

    // (アクセサの記載は省略します)