本文へ移動
Wagby11
マニュアルのグループを選ぶ

WAGBY11 MANUAL / 27

標準チェックで表せない検証を追加する

AppSchemaにカスタム検証のruleを宣言し、次の指示でSPIを使うJava実装をAIへ依頼する流れを説明します。

最終更新日:

カスタマイズの小目次へ

1. このページで伝える機能

標準の必須・長さ・範囲・正規表現・項目間比較で表せない入力チェックを、Javaのカスタム検証で追加できます。関連するDBデータや利用者の情報を踏まえて、登録・更新を止めたり、警告を返したりする場合に使います。

AIへの依頼は、まずAppSchemaへ検証の仕様とrulesを定義し、次にそのルールに対応するJava実装を作る、という2段階で進めます。利用者がJava構文を覚えることは前提にしません。

2. Wagby11で実現できること

2.1 標準チェックとカスタム検証を使い分ける

単一項目の必須、文字数、数値範囲、正規表現、同じモデル内の単純な項目間比較には、まず標準の入力チェックを使います。標準機能で表せるものを、すべてJavaで書き直す必要はありません。

保存する時点の関連データや、ログオン利用者を使った業務判断など、標準の宣言で表せない部分をカスタム検証にします。AppSchemaには、実行する操作、ルールID、エラーか警告か、関連付ける項目、メッセージコードを定義します。Java実装が違反を返したとき、その内容を利用者へ伝えます。

2.2 SPIは処理を追加するための決められた接続口

SPI(Service Provider Interface)は、Wagbyが用意する拡張用のインターフェースです。「どの処理の段階で呼び出すか」「どの情報を渡すか」「何を返すか」が決まっています。AIは実現したい処理に合うSPIを選び、その約束に従ったJavaクラスを作ります。

追加する処理の主目的主なSPI
値の計算・導出CalculationCustomizer
保存前の業務検証BusinessValidationCustomizer
保存前後の処理・別モデルの更新LifecycleRuleHandler
利用者ごとの認可・行の範囲AuthorizationCustomizer
画面を開いたときの初期化FormInitializationCustomizer
検索条件への条件追加SearchSpecificationCustomizer

rulesは任意の処理を実行するプログラムではありません。処理内容を文章で宣言しても、利用できるSPIの役割・呼出しタイミング・引数・トランザクションの範囲に収まる実装が必要です。画面操作、外部連携、保存後の処理などを、すべてカスタム検証へ詰め込むことはしません。要件がSPIに合わなければ、別の拡張方法や設計をAIと検討します。

2.3 取引停止中の顧客への受注を止める

説明例として、受注モデルOrderが顧客モデルCustomerを参照し、顧客に取引停止フラグtradingSuspendedがある構成を考えます。受注の登録・更新時に顧客の現在の停止状態をDBから確認し、停止中なら保存を拒否します。更新時は顧客を選び直していなくても確認する、という仕様です。

決める内容この例の仕様
検証する操作受注の登録と更新
参照する情報受注が参照する顧客の取引停止フラグ
停止する条件フラグがtrueの顧客を指定している
重大度エラー。保存は続行しない
エラーを関連付ける項目受注の顧客項目customerId
表示する文面「取引停止中の顧客は指定できません。」

未入力や存在しない顧客の扱いは、既存の必須・参照チェックと合わせて設計します。実際の依頼では、現在のモデル名・項目名・型を確認し、この例の名前をそのまま既存定義へ当てはめないようにします。

2.4 ルール定義とJava実装を2回に分けて依頼する

  1. 1回目は仕様をAppSchemaへ定義します。受注モデルのentity.validation.constraintsと、同じモデルモジュールのrulesを作ります。ルールIDと検証ID、実行操作、メッセージ等を確認します。この段階ではJava実装はまだ作りません。
  2. 2回目はそのルールのJava実装を依頼します。AIが最新の定義から必要なコードを生成し、生成Entity・Repository・Rule Catalogを確認したうえで、SPIに対応するJavaクラスを作ります。実装本体は再生成で上書きされないrestapi/src/main/customize/javaへ置きます。

AppSchemaから生成されるのは、モデルやルールの対応情報などです。独自の検証ロジックは、AIがruleを読んで作成するJavaカスタマイズです。1回目の定義だけでは、要求したチェックが動く状態にはなりません。2回目の実装後にテストして、利用できる状態にします。

2.5 定義と実装の対応を確認する

カスタム検証はBusinessValidationCustomizerの登録用・更新用メソッドへ実装します。一つのルールIDを複数のクラスやSPIへ重複して登録しません。生成コードを直接書き換えず、ルールIDと実装の対応を検査します。

Rule Catalogは、定義に対して実装が不足していないか、重複していないか、変更後の定義に実装が対応しているかを確認するための情報です。定義や依存モデルを変更したら、Java実装とテストも確認します。

実装にはruleIds()とimplementationFingerprints()を宣言します。fingerprintはルールと依存モデルの契約を要約した値で、Java本文のハッシュではありません。生成値は実装内容を確認してリテラルで記録し、現在値を動的に読む方法や値だけの更新で確認を省略しません。進捗の記録をrules[].noteへ追記するとfingerprintも変わるため、進捗は別の管理文書へ残します。

3. AIへの指示例

同じ会話で、1回目の成果を確認してから2回目を送ります。以下に、短い指示の組と、仕様を詳しく指定する組を示します。

最小限の指示例

1回目:AppSchemaのruleを用意する

取引停止中の顧客への受注は、登録・更新できないようにしたいです。まず既存のモデルと標準チェックを確認し、カスタム検証に必要なAppSchemaのruleと検証定義だけを作ってください。Java実装はまだ作らず、判定条件とエラー表示の仕様を説明してください。

AIは対象モデル、停止を示す項目、ルールID、実行操作、エラー付与先などを既存の定義から類推します。取引停止中の既存受注を更新できるか、どの項目にどう表示するかなど、業務に影響する未確定事項を確認します。

2回目:ruleからJava実装を用意する

先ほど確認したAppSchemaのruleに対応するJavaカスタム検証を作ってください。Javaカスタマイズガイドに従い、適切なSPIを使って実装してください。生成コードは直接変更せず、登録・更新の正常ケースと拒否ケースのテスト、ルールと実装の対応検査も用意してください。

2回目は、1回目に決めた定義を実装の基準にします。AIは生成コードと既存カスタマイズを確認して型や実装方法を決めます。この短い指示だけで、次の詳細例と同じモデル構成・ルールID・メッセージになるとは限りません。

より詳細な指示例

1回目:カスタム検証の設計を定義する

Wagby11のカスタム検証guide、validationとrulesのreferenceを確認してください。
受注OrderのcustomerIdが顧客Customerを参照し、CustomerのtradingSuspendedが取引停止を示すtrue/false項目である例です。実際の既存モデル・型・同等の項目を確認し、異なる場合は対応を整理してください。
保存時点で参照先顧客の取引停止フラグがtrueなら、受注の登録・更新をエラーにしてください。更新では顧客を変更していなくても判定します。未入力や存在しない顧客は既存の必須・参照検証と整合させてください。
Orderのentity.validation.constraintsに次の2件を定義してください。
・ORDER_CUSTOMER_ACTIVE_CREATE:type custom、rule_id RULE_ORDER_CUSTOMER_ACTIVE_CREATE、operations [CREATE]。
・ORDER_CUSTOMER_ACTIVE_UPDATE:type custom、rule_id RULE_ORDER_CUSTOMER_ACTIVE_UPDATE、operations [UPDATE]。
両方ともseverity error、attach_to customerId、message_code error.order.customer.suspendedとします。
同じモデルモジュールのrulesに対応する2件を定義し、trigger.operationは登録側INSERT・更新側UPDATE、timingはBEFORE_SAVEとしてください。
BusinessValidationCustomizerで顧客の現在の停止状態を検証する方針とし、contract.entitiesにCustomerを指定してください。判定条件と拒否時の動作はactionsへ具体的に記述し、任意コードやスクリプトは埋め込まないでください。
既存の主キー・固定ID・項目・権限・データを保持してください。今回はAppSchemaの定義とその検証までとし、Java実装・アプリのビルドは行わないでください。変更した定義と、次に実装すべき内容を説明してください。

2回目:SPIを使うJavaコードを作る

1回目に定義した2件のruleを実装してください。製品同梱のJavaカスタマイズコード作成ガイドと、業務ルールのカスタマイズの説明を確認してください。
最新のAppSchemaから必要なコードを生成し、Order・Customerの生成Entity、Repository、OrderのRule Catalog、既存カスタマイズを読んでください。生成に失敗した状態でJava型やメソッドを推測しないでください。
BusinessValidationCustomizerのvalidateForCreateとvalidateForUpdateで、参照先Customerの現在の取引停止フラグをDBから確認してください。停止中は保存を止めるERRORをcustomerIdへ返してください。未入力や顧客なしは、1回目に確認した既存の検証方針に従ってください。
実装先はrestapi/src/main/customize/javaとし、生成コードのrestapi/src/main/javaは直接変更しないでください。
違反のIDはrule_idではなく、CREATE側はORDER_CUSTOMER_ACTIVE_CREATE、UPDATE側はORDER_CUSTOMER_ACTIVE_UPDATEを使ってください。メッセージコードはerror.order.customer.suspendedとし、「取引停止中の顧客は指定できません。」を再生成されないメッセージ定義へ追加してください。
ruleIdsには生成Rule Catalogの定数を使い、同じルールIDをほかのクラス・SPIへ重複登録しないでください。implementationFingerprintsには実装時点の生成値を確認してリテラルで記録してください。
登録・更新それぞれで、停止していない顧客は受理、停止中の顧客は拒否されるテストを用意してください。更新時は顧客IDを変えていないケースも確認してください。Rule Catalogによる未実装・重複・fingerprintの対応検査も用意してください。
テストと必要なビルドを実施し、変更したファイル、ruleごとの実装先、確認結果を説明してください。

2回目の指示例には、実装を利用可能にするためのテスト・ビルドまで含めています。1回目で仕様を確認し、実装を依頼する段階へ進むときに使います。

4. 編集されるAppSchemaの例

以下は1回目の指示で用意する定義の例です。Orderのモデルモジュールへ記述します。受注と顧客の項目・型・参照・権限等は別途定義されている前提で、省略しています。

entity:
  name: 受注
  name_en: Order
  validation:
    constraints:
      - id: ORDER_CUSTOMER_ACTIVE_CREATE
        type: custom
        rule_id: RULE_ORDER_CUSTOMER_ACTIVE_CREATE
        severity: error
        operations: [CREATE]
        attach_to: customerId
        message_code: error.order.customer.suspended
      - id: ORDER_CUSTOMER_ACTIVE_UPDATE
        type: custom
        rule_id: RULE_ORDER_CUSTOMER_ACTIVE_UPDATE
        severity: error
        operations: [UPDATE]
        attach_to: customerId
        message_code: error.order.customer.suspended
rules:
  - id: RULE_ORDER_CUSTOMER_ACTIVE_CREATE
    name: 受注登録時の取引停止チェック
    trigger:
      operation: INSERT
      timing: BEFORE_SAVE
    actions: >-
      BusinessValidationCustomizerで、受注が参照するCustomerの現在の
      tradingSuspendedをDBから確認する。trueならORDER_CUSTOMER_ACTIVE_CREATEの
      エラーをcustomerIdへ返し、登録を拒否する。
    contract:
      entities: [Customer]
  - id: RULE_ORDER_CUSTOMER_ACTIVE_UPDATE
    name: 受注更新時の取引停止チェック
    trigger:
      operation: UPDATE
      timing: BEFORE_SAVE
    actions: >-
      BusinessValidationCustomizerで、顧客IDの変更有無によらずCustomerの現在の
      tradingSuspendedをDBから確認する。trueならORDER_CUSTOMER_ACTIVE_UPDATEの
      エラーをcustomerIdへ返し、更新を拒否する。
    contract:
      entities: [Customer]

検証定義のrule_idは同じモジュールのrules[].idを参照します。attach_toは違反を関連付ける項目です。Javaから違反を返す際は、検証ID・重大度・項目・メッセージコードを定義に合わせます。

operations: [CREATE]は入力チェック側の登録操作、trigger.operation: INSERTはrule側の登録契機です。表記を混同しないようにします。contract.entitiesには実装が参照する追加モデルを列挙します。発火元のOrderは自動で対象になるため、ここへ重ねて書きません。

2回目には、この定義と生成コードをもとに、Javaクラス、再生成されないメッセージ定義、テストが用意されます。ruleの文章だけでJavaの検証処理が自動実装されるわけではありません。

5. 参考資料

guide:カスタム検証
designer/docs/appschema/html/guide/04-validation/11-custom-validation.html
reference:validation
designer/docs/appschema/html/reference/11-validation.html
reference:rules
designer/docs/appschema/html/reference/08-rules.html
Javaカスタマイズコード作成ガイド
designer/docs/java/html/java-customization/index.html
業務ルールのカスタマイズ
designer/docs/java/html/11_business_rule_customization.html