    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.taglib;
    017
    018import org.opengion.fukurou.db.Transaction;
    019import org.opengion.fukurou.db.TransactionImpl;
    020
    021import java.io.ObjectOutputStream;
    022import java.io.ObjectInputStream;
    023import java.io.IOException;
    024
    025/**
    026 * コネクションを共有して、トランザクションを実現します。
    027 *
    028 * 通常のタグでは、コネクションプールより、その時々のコネクションを取り出して利用するため、
    029 * タグごとに異なるコネクションで処理されます。
    030 * また、commit や rollback などもそれぞれのタグで行われるため、連続処理時にエラーが
    031 * 発生しても、中途半端な状態になります。
    032 * ここでは、各 DBID 単位にコネクションを共有し、このタグの間は、同じオブジェクトを
    033 * commit や、rollback せずに使いまわすようにします。
    034 * これにより、複数タグ間のトランザクションや、異なる DBID 間のトランザクションを
    035 * 実現します。
    036 *
    037 * このタグは、doEndTag() メソッドが正常に呼び出されることで、トランザクションが成立します。
    038 * つまり、途中で、JSP出力が、SKIP_PAGE された場合は、commit もされません。
    039 * これは、データベースエラー以外のエラーでも、トランザクション処理されることを意味します。
    040 *
    041 * @og.formSample
    042 * ●形式：&lt;og:transaction &gt; ... &lt;/og:transaction &gt;
    043 * ●body：あり(EVAL_BODY_INCLUDE:BODYをインクルードし、{&#064;XXXX} は解析しません)
    044 *
    045 * ●Tag定義：
    046 *   &lt;og:transaction
    047 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    048 *   &gt;   ... Body ...
    049 *   &lt;/og:transaction&gt;
    050 *
    051 * ●使用例
    052 *     &lt;og:transaction &gt;
    053 *         &lt;og:query command="NEW" dbid="SERVER1" &gt;
    054 *             insert into XX01 (aa,bb,cc) values ('AA','BB','CC') /&gt;
    055 *         &lt;/og:query &gt;
    056 *         &lt;og:query command="NEW" dbid="SERVER2" &gt;
    057 *             update YY02 set aa='AA',bb='BB',cc='CC' where uniq='00001' /&gt;
    058 *         &lt;/og:query &gt;
    059 *     &lt;/og:transaction &gt;
    060 *
    061 * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    062 * @og.group ＤＢ登録
    063 *
    064 * @version  5.0
    065 * @author       Kazuhiko Hasegawa
    066 * @since    JDK6.0,
    067 */
    068public class TransactionTag extends CommonTagSupport {
    069        //* このプログラムのVERSION文字列を設定します。   {@value} */
    070        private static final String VERSION = "5.1.9.0 (2010/08/01)" ;
    071        private static final long serialVersionUID = 519020100801L ;
    072
    073        // TransactionTag では、Transaction インターフェースではなく、実装クラスで管理します。
    074        private TransactionImpl tran = null;
    075
    076        /**
    077         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    078         *
    079         * @return      後続処理の指示( EVAL_BODY_INCLUDE )
    080         */
    081        @Override
    082        public int doStartTag() {
    083                tran = new TransactionImpl( getApplicationInfo() );
    084
    085                return EVAL_BODY_INCLUDE ;      // Body インクルード( extends TagSupport 時)
    086        }
    087
    088        /**
    089         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
    090         *
    091         * @return      後続処理の指示
    092         */
    093        @Override
    094        public int doEndTag() {
    095                debugPrint();           // 4.0.0 (2005/02/28)
    096
    097                // finish() は、TransactionImpl のメソッドです。
    098                if( tran != null ) { tran.finish(); }
    099
    100                return EVAL_PAGE ;              // ページの残りを評価する。
    101        }
    102
    103        /**
    104         * タグリブオブジェクトをリリースします。
    105         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
    106         *
    107         */
    108        @Override
    109        protected void release2() {
    110                super.release2();
    111
    112                // realClose() は、TransactionImpl のメソッドです。
    113                if( tran != null ) { tran.realClose(); }
    114                tran = null;
    115        }
    116
    117        /**
    118         * Transactionオブジェクトを返します。
    119         *
    120         * @return      Transactionオブジェクト
    121         */
    122        protected Transaction getTransaction() {
    123                return tran ;
    124        }
    125
    126        /**
    127         * シリアライズ用のカスタムシリアライズ書き込みメソッド
    128         *
    129         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
    130         * @serialData 一部のオブジェクトは、シリアライズされません。
    131         *
    132         * @param       strm    ObjectOutputStreamオブジェクト
    133         * @throws IOException  入出力エラーが発生した場合
    134         */
    135        private void writeObject( final ObjectOutputStream strm ) throws IOException {
    136                strm.defaultWriteObject();
    137        }
    138
    139        /**
    140         * シリアライズ用のカスタムシリアライズ読み込みメソッド
    141         *
    142         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
    143         *
    144         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
    145         * @serialData 一部のオブジェクトは、シリアライズされません。
    146         *
    147         * @param       strm    ObjectInputStreamオブジェクト
    148         * @see #release2()
    149         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
    150         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
    151         */
    152        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
    153                strm.defaultReadObject();
    154        }
    155
    156        /**
    157         * このオブジェクトの文字列表現を返します。
    158         * 基本的にデバッグ目的に使用します。
    159         *
    160         * @return このクラスの文字列表現
    161         */
    162        @Override
    163        public String toString() {
    164                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
    165                                .println( "VERSION"             ,VERSION        )
    166                                .println( "Other..."    ,getAttributes().getAttribute() )
    167                                .fixForm().toString() ;
    168        }
    169}