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 * ●形式:<og:transaction > ... </og:transaction >
043 * ●body:あり(EVAL_BODY_INCLUDE:BODYをインクルードし、{@XXXX} は解析しません)
044 *
045 * ●Tag定義:
046 *   <og:transaction
047 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
048 *   >   ... Body ...
049 *   </og:transaction>
050 *
051 * ●使用例
052 *     <og:transaction >
053 *         <og:query command="NEW" dbid="SERVER1" >
054 *             insert into XX01 (aa,bb,cc) values ('AA','BB','CC') />
055 *         </og:query >
056 *         <og:query command="NEW" dbid="SERVER2" >
057 *             update YY02 set aa='AA',bb='BB',cc='CC' where uniq='00001' />
058 *         </og:query >
059 *     </og:transaction >
060 *
061 * @og.rev 5.1.9.0 (2010/08/01) 新規作成
062 * @og.group DB登録
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}