1.3. 基本方針

Nablarchアプリケーションフレームワークの基本方針について解説する。

1.3.1. 外部から受け付ける未入力値の扱い

アプリケーションは外部から未入力値も含めた様々なデータを受け付ける。 未入力値は一般的に null と空文字列の2つの表現方法がある。 アプリケーション開発者が2つの表現方法を意識する必要があると実装ミスが起きやすく、思わぬ不具合を生み出す可能性がある。 その問題を回避するためには未入力値の扱いを統一しなければならない。

未入力値の表現方法を統一するために、Nablarchでは未入力値を null に変換する。 例えば、HTTPリクエストのパラメータやXMLなどの外部から受け付けたデータの未入力値は null に変換する。 また、カスタムタグやフォーマットして出力するなどの外部へ null を出力するときは、出力するデータ形式に応じて未入力を意味する値に変換する。 変換はNablarchのハンドラ・ライブラリが行うため、アプリケーションで未入力値を変換する必要はない。 ただし、未入力値を null に変換するには ノーマライズハンドラ をハンドラキューに追加する必要がある。

この方針に従い、アプリケーションでは未入力値を null として開発すること。

1.3.2. コレクションや配列を返すAPIは原則nullを戻さない

Nablarchが提供するコレクションや配列を返すAPIは、対象データが存在しない場合には基本的に null ではなく空のコレクションや配列を返す。 これにより、呼び出し元での null 参照による不具合を防止できたり、分岐が減ることによる可読性の向上が期待できる。

例えば、データベースの検索結果をビュー(JSP)で一覧形式で表示する場合、 null 判定を行わずにループをすればよくコードの可読性が向上する。 もし、 null を考慮する必要がある場合、JSPで分岐を書いたり、サーバサイドで null のコレクションをリクエストスコープに詰めるなど無駄なコードが多くなる。またこれにより実装ミスが起こりやすくなる。

なお、HTTPのリクエストパラメータのように識別子を指定して取得するようなAPIの場合には、空の配列ではなく null を返す。

1.3.3. Nablarchは検査例外を送出しない

Nablarch内の全てのAPIは、非検査例外のみを送出する。またNablarchで定義している例外クラスも全て非検査例外としている。 全て非検査例外とすることで、アプリケーションで例外を意識する必要がなく、ハンドラで共通的な例外処理を行うことが出来る。

なお、検査例外には以下のデメリットがある。

  • 例外を捕捉するか throws に列挙しないとコンパイルエラーとなる。 例外を捕捉した場合、同じような例外処理を至る所に実装しなくてはならない。
  • 送出される例外が増えるたびにアプリケーション側のコードに影響が出る。 また、例外を捕捉するメソッドまで全てのメソッドで throws を追加するなど影響が広範囲に及ぶ。

1.3.4. ログや例外のメッセージは英語で統一する

Nablarchは、日本以外での利用も想定しているため、ログや例外のメッセージは全て英語としている。 なお、Nablarch内で出力しているログや例外のメッセージを英語以外に変更する機能は提供していない。

1.3.5. コンポーネントを差し替えることでNablarchが発行するSQLを変更できる

Nablarchでは、データベースにアクセスするコンポーネントには必ずインタフェースが定義されており、実装の差し替えが可能となっている。 なぜなら、プロジェクト側で実装クラスを作成し設定ファイルからコンポーネントを差し替えることで、発行するSQLを変更できるようにするためである。

これにより、例えばNablarchが使用するテーブルのカラムを追加や削除する場合に、コンポーネントを差し替えることで対応することができる。

なお、テーブル名やカラム名をデフォルトから変更したい場合であれば、新しくクラスを作成する必要はなく、設定ファイルの修正のみでよい。

1.3.6. OSSは利用しない

Nablarchのプロダクションコードは、致命的な不具合や脆弱性が見つかった際に、迅速に対応かつリリースを行うことを目的としてOSSを利用していない。

なお、OSSを利用することでメリットがあるものは、 アダプタ としてOSSを利用できるコンポーネントを提供しているため、プロジェクト要件などに応じて採用すると良い。

1.3.7. 複数の例外が発生した場合は起因例外をスローする

処理中に例外が発生し、その後の処理中に別の例外が発生すると複数の例外が発生することになる。 その場合、問題を解決するために重要になるのは起因例外であるため、Nablarchは起因例外をスローする。 また、他の例外の情報も問題の調査に利用できるように、起因例外以外の情報はWARNINGログに出力する。

1.3.8. スレッドセーフである

Nablarchが提供する機能は、基本的にスレッドセーフである。 なぜなら、Nablarchはハンドラキュー上のハンドラを各スレッドで実行し要求を処理するアーキテクチャを採用しているためである。アーキテクチャの詳細は、 アーキテクチャの章 を参照。 これにより、ウェブアプリケーションのように各スレッドがクライアントからの要求を処理するような基盤でも、安全に要求を処理し結果をクライアントに返すことが出来る。

なお、 システムリポジトリ 上のオブジェクトはシングルトンとなるため、スレッドセーフとする必要がある。

ちなみに

スレッドアンセーフな機能(例えばデータベース接続等)は、Javadoc上にスレッドアンセーフであることを明記している。

1.3.9. Java6に準拠している

NablarchのプロダクションコードはJava6に準拠しており、Java7以降で提供されているAPIは使用していない。

なぜなら、Nablarchの開発時点での最新バージョンがJava6だったため、 既存のNablarch導入プロジェクトに対する後方互換を維持するためにJava6準拠のままとしている。

なお、Nablarchを使用したアプリケーションを開発する際はJava6以降のバージョンであればよく、 Java7以降で提供されているAPIも問題なく使用できる。

1.3.10. アプリケーションで使用してもよいAPIについて

Nablarchでは、アプリケーション開発で必要になると想定したAPIを公開APIとして定義している。 公開APIには Published というアノテーションが付与され、どのクラスやメソッドが公開APIであるかがわかるようになっている。

公開APIは、アプリケーションで使用されるAPIであるため、バージョンアップ時に後方互換を維持し、アプリケーションに修正が発生しないようにしている。 ただし、致命的な不具合と脆弱性の対応時には後方互換を維持できない場合もある。

1.3.11. 文字列からBigDecimal変換時に発生する可能性のあるヒープ不足について

文字列からBigDecimalに変換する際に指数表現(例えば、 9e100000 のような値)を指定した場合に、以下の問題が発生する場合がある。

  • BigDecimal#toPlainString() の呼び出しで、非常に大きい文字列が生成されヒープが圧迫される
  • DecimalFormat を使用してフォーマットする際に非常に大きい文字列が生成されヒープが圧迫される

このため、Nablarchでは文字列からBigDecimalに変換する際に、 BigDecimal#scale を使用して桁数チェックを行い、ヒープを圧迫するような大きな値を取り込むことを防止している。 この機能では、許容するscaleの範囲を -9999 から 9999 の範囲とし、この範囲を超える指数表現の値を変換しようとした場合、例外を送出しヒープが圧迫されないようにしている。

なお、許容するscaleの範囲は設定で変更可能となっている。 設定はシステムリポジトリ機能の環境設定ファイルに指定する。 設定方法は、 環境依存値を設定する を参照。

例えば、許容する範囲を -10 から 10 としたい場合には、下のように設定を追加する。

nablarch.max_scale=10