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

1.3.12. 非推奨(Deprecated)APIについて

Nablarchでは以下に該当するAPIは @Deprecated アノテーションを付与し非推奨とする。

  • 他パッケージに移動したクラス

    Nablarchチームの都合でクラスを他パッケージに移動した際には、移動前クラスを非推奨とする。 Javadocには、移動先のクラスを使用するように記載を行っている。

    なお、移動前のクラスは移動後のクラスに全ての処理を委譲しているため、移動前のクラスを利用している場合でも動作は保証される。 ただし、メソッド追加などは行われないため、移動先クラスを使用することが好ましい。

  • 不具合やセキュリティ面で問題のあるクラスやメソッド

    不具合やセキュリティ面での問題があるクラスは非推奨とする。 Javadocには、理由及び代わりに使用すべきAPIや実装方法の記載を行っている。

    Javadocを参照し不具合やセキュリティ面での問題を解消したAPIを使用するよう対応が必要となる。

    重要

    不具合や脆弱性については基本的に問題を解消するよう修正を行う。 しかし、クラス構造的な制約や後方互換の維持を目的として問題のあるAPIを非推奨として残す場合がある。 非推奨APIとして残した場合は、新たな不具合などが見つかっても対応は行わない。 このため、問題が解消された新しいAPIを使用するようアプリケーション側は必ず対応を行う必要がある。

補足

本ドキュメントで代替機能の使用を推奨しているものについては、非推奨API( @Deprecated の付与)とはしていない。 なぜなら、これらのAPI(機能)は、使用すること自体は問題なく、不具合などがあった場合もバージョンアップ時に対応を行うためである。