Webアプリケーションが行う処理の整理

ひとまずUIはおいといて、ボタンクリック等のイベント発生から、次の画面表示(またはWebAPIのリクエストからレスポンスまで)に行われる処理の一覧を書き出してみる。

(8/18 例外処理、その他の追記)

  • 前処理
    • 個別ロジックの選択
    • セッションデータの取得
    • アクセス権限チェック
    • 入力パラメータのパース
    • 入力パラメータ整合性チェック
      • 文字数
      • 数値桁数(整数部、小数部)
      • 日付書式
      • 文字種
      • メールアドレス
      • 特殊形式(Regex)
  • 本処理
    • 入力データ、セッションデータの論理チェック(必須、値域等)
    • DBアクセス
      • 参照データ取得
      • データ保存
    • データ加工
    • 外部データ入出力
      • ファイルI/F(リモートメッセージ)
      • RPC(WebService etc)
      • メール送出
      • 非同期帳票出力
    • 表示用データの作成
    • 保存するセッションデータの作成
    • 遷移先画面の選択
  • 後処理
    • セッションデータの保存
    • 画面の生成
    • データ送出(XML,JSON etc...)
  • 例外処理、その他
    • エラーコード、メッセージのハンドリング
    • トランザクション管理
    • エラーのプレゼンテーション
      • メッセージ表示
      • エラー項目の強調表示、ヘルプ表示
    • ロギング

Oracle JDBCドライババージョンによる日付型の扱いの違い

元記事最終更新:2010/08/26

概要

Oracle10gになってJDBCドライバの仕様が変わり、OracleのDATE型に対応するJava型が、java.sql.Timestampからjava.sql.Dateへ変更となった。また、Oracle側にTIMESTAMP型が追加となった(従来のDATE型は秒までの精度だが、TIMESTAMPはミリ秒精度)。

このこと自体は、SQLの標準に照らすと妥当な変更であるが、旧来の慣習によってDB設計を行った場合、問題となる場合があるため、備忘録として記述する。

変更内容

JDBCドライバの変更

OracleのDATE型が、java.sql.Date型にマッピングされた(従来はjava.sql.Timestamp)。これにより、OracleのDATE型に格納された時刻部分の情報が、Javaに持ってきたときに削除されることになる。(java.sql.Dateは時刻情報が入らない)

Oracle型「TIMESTAMP」の追加

日付・時刻(ミリ秒精度)を格納できるTIMESTAMP型が追加された。これは、JDBCドライバによってjava.sql.Timestamp型にマップされる。

想定される悪影響

時刻情報の欠落

日付・時刻の情報を格納する前提でDATE型のカラムを用意したにもかかわらず、Javaで時刻情報が取得・更新できない。

回避策

時刻情報を含む項目はTIMESTAMP型で定義する。

この対応が本道。

JDBCをバージョン8互換モードにする

10g以降のJDBCドライバには、バージョン8互換モードが存在する。このモードにおいては、日付型の扱いはOracle8と同様になるため、上記の問題を回避できる。

バージョン8互換モードで動作させるには、Java起動時に、システムプロパティoracle.jdbc.V8Compatibilityに対してtrueを設定する。

java -Doracle.jdbc.V8Compatibility="true" MyApp

バージョン11gでの変更について

(2010/08/26追記)

JDBCドライバ バージョン11gでは、OracleのDATE型もjava.Date.Timestamp型にマッピングされるように変更となった模様。

例外のスタックトレースが途切れる

元記事最終更新:2007/04/19

概要

Sun Java VMに含まれる、HotSpot Servet VMでアプリケーションを実行する際、たまに例外のスタックトレースが省略されてしまう件に関して記述。

現象

Sun Java SE 1.4.1_08 のHostSpot Server VMで確認。
同じ箇所繰り返しNullPointerExceptionを発生するコードがあった際、何度目かの例外発生後、NullPointerExcetpionインスタンススタックトレースが含まれなくなった。

このため、例外発生時の原因特定が困難となってしまった。

原因

HotSpotVMは、実行時最適化の一環として、繰り返し出力される一部の組み込み例外については、都度例外インスタンスを生成せず、同じインスタンスを使い回すことによってインスタンス生成コストを抑えるという処理を行っている。

この使いまわされる例外インスタンスは、他所でthrowされた例外の情報が混入しないよう、スタックトレースそのものを省略する。

このため、例外発生箇所がHotSpotVMによって最適化されると、以降発生する例外にはスタックトレースが含まれないように見えてしまう。

対応

JavaVM起動時、以下のオプションを付加することにより、上記の例外に対する最適化処理を無効とすることができる。

 -XX:-OmitStackTraceInFastThrow

この設定によるリスクとしては、NullPointerExceptionの生成コストが若干大きくなることが挙げられる。が、NullPointerExceptionの生成コストが全体のパフォーマンスに影響を与えるような状況は、つまりNullPointerExceptionが大量発生しているということであり、そもそもアプリケーションの設計自体を見直さなければならない状況であるので、あまり気にする必要はないんじゃないかと。

crontabで月末日を指定

元記事最終更新:2009/05/08

crontabで、月末日にスケジューリングしたいときの記載例

50 23 28-31 * * /usr/bin/test $( date -d '+1 day' +%d ) -eq 1 && /hoge/job

Solaris(非gnu tool)だと date -d が使えないんだけど……

環境変数TZでごまかすとか。

/usr/bin/test TZ=JST+33; $(date +%d) -eq 1 && /hoge/job

TZのオフセット値に0〜24以外の値を設定した際の動作は、保証外であることに注意。

RFC1123形式での時刻出力をJavaで実装する

元記事最終更新:2007/04/19

HTTPヘッダ等に時刻情報を付加する場合、通常、RFC1123形式でフォーマッティングする必要がある。
以下は、現在時刻をRFC1123形式の文字列で取得するJavaコード例。

/**
 * RFC1123形式で現在時刻を取得する
 * @return 現在時刻をRFC1123、GMTタイムゾーンで返す
 */
public String getRFC1123CurrentTime() {
    SimpleDateFormat rfc1123DateFormat = 
            new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss zzz", java.util.Locale.US);
    rfc1123DateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

    Date current = Calendar.getInstance().getTime();
    return rfc1123DateFormat.format(current);
}

出力例

 Fri, 09 Jun 2006 11:02:56 GMT