001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.core.transaction;
017:
018: import org.apache.openejb.ApplicationException;
019: import org.apache.openejb.InvalidateReferenceException;
020: import org.apache.openejb.SystemException;
021: import org.apache.openejb.core.ThreadContext;
022: import org.apache.openejb.core.Operation;
023: import org.apache.openejb.util.LogCategory;
024: import org.apache.openejb.util.Logger;
025:
026: import javax.transaction.Transaction;
027: import javax.transaction.TransactionManager;
028: import javax.transaction.InvalidTransactionException;
029: import javax.transaction.HeuristicMixedException;
030: import javax.transaction.HeuristicRollbackException;
031: import javax.transaction.RollbackException;
032: import javax.transaction.NotSupportedException;
033: import javax.ejb.EJBException;
034:
035: import java.rmi.RemoteException;
036:
037: public abstract class TransactionPolicy {
038: public Type getPolicyType() {
039: return policyType;
040: }
041:
042: public static enum Type {
043: Mandatory, Never, NotSupported, Required, RequiresNew, Supports, BeanManaged;
044: }
045:
046: private final Type policyType;
047: protected final TransactionContainer container;
048: private TransactionManager manager;
049:
050: protected final static Logger logger = Logger.getInstance(
051: LogCategory.OPENEJB, "org.apache.openejb.util.resources");
052: protected final static Logger txLogger = Logger.getInstance(
053: LogCategory.TRANSACTION,
054: "org.apache.openejb.util.resources");
055:
056: public TransactionPolicy(Type policyType,
057: TransactionContainer container) {
058: this .policyType = policyType;
059: this .container = container;
060: }
061:
062: public TransactionContainer getContainer() {
063: return container;
064: }
065:
066: public String policyToString() {
067: return policyType.toString();
068: }
069:
070: public abstract void handleApplicationException(
071: Throwable appException, boolean rollback,
072: TransactionContext context) throws ApplicationException,
073: SystemException;
074:
075: public abstract void handleSystemException(Throwable sysException,
076: Object instance, TransactionContext context)
077: throws ApplicationException, SystemException;
078:
079: public abstract void beforeInvoke(Object bean,
080: TransactionContext context) throws SystemException,
081: ApplicationException;
082:
083: public abstract void afterInvoke(Object bean,
084: TransactionContext context) throws ApplicationException,
085: SystemException;
086:
087: protected void markTxRollbackOnly(Transaction tx)
088: throws SystemException {
089: try {
090: if (tx != null) {
091: tx.setRollbackOnly();
092: if (txLogger.isInfoEnabled()) {
093: txLogger.info("TX " + policyToString()
094: + ": setRollbackOnly() on transaction "
095: + tx);
096: }
097: }
098: } catch (javax.transaction.SystemException se) {
099: logger.error("Exception during setRollbackOnly()", se);
100: throw new SystemException(se);
101: }
102: }
103:
104: protected Transaction suspendTransaction(TransactionContext context)
105: throws SystemException {
106: try {
107: Transaction tx = context.getTransactionManager().suspend();
108: if (txLogger.isInfoEnabled()) {
109: txLogger.info("TX " + policyToString()
110: + ": Suspended transaction " + tx);
111: }
112: return tx;
113: } catch (javax.transaction.SystemException se) {
114: logger.error("Exception during suspend()", se);
115: throw new SystemException(se);
116: }
117: }
118:
119: protected void resumeTransaction(TransactionContext context,
120: Transaction tx) throws SystemException {
121: try {
122: if (tx == null) {
123: if (txLogger.isInfoEnabled()) {
124: txLogger.info("TX " + policyToString()
125: + ": No transaction to resume");
126: }
127: } else {
128: if (txLogger.isInfoEnabled()) {
129: txLogger.info("TX " + policyToString()
130: + ": Resuming transaction " + tx);
131: }
132: context.getTransactionManager().resume(tx);
133: }
134: } catch (InvalidTransactionException ite) {
135:
136: txLogger
137: .error("Could not resume the client's transaction, the transaction is no longer valid: "
138: + ite.getMessage());
139: throw new SystemException(ite);
140: } catch (IllegalStateException e) {
141:
142: txLogger
143: .error("Could not resume the client's transaction: "
144: + e.getMessage());
145: throw new SystemException(e);
146: } catch (javax.transaction.SystemException e) {
147:
148: txLogger
149: .error("Could not resume the client's transaction: The transaction reported a system exception: "
150: + e.getMessage());
151: throw new SystemException(e);
152: }
153: }
154:
155: protected void commitTransaction(TransactionContext context,
156: Transaction tx) throws SystemException {
157: try {
158: if (txLogger.isInfoEnabled()) {
159: txLogger.info("TX " + policyToString()
160: + ": Committing transaction " + tx);
161: }
162: if (tx.equals(context.getTransactionManager()
163: .getTransaction())) {
164:
165: context.getTransactionManager().commit();
166: } else {
167: tx.commit();
168: }
169: } catch (RollbackException e) {
170:
171: txLogger
172: .info("The transaction has been rolled back rather than commited: "
173: + e.getMessage());
174: throw new EJBException(e);
175:
176: } catch (HeuristicMixedException e) {
177:
178: txLogger
179: .info("A heuristic decision was made, some relevant updates have been committed while others have been rolled back: "
180: + e.getMessage());
181: throw new EJBException(e);
182:
183: } catch (HeuristicRollbackException e) {
184:
185: txLogger
186: .info("A heuristic decision was made while commiting the transaction, some relevant updates have been rolled back: "
187: + e.getMessage());
188: throw new EJBException(e);
189:
190: } catch (SecurityException e) {
191:
192: txLogger
193: .error("The current thread is not allowed to commit the transaction: "
194: + e.getMessage());
195: throw new SystemException(e);
196:
197: } catch (IllegalStateException e) {
198:
199: txLogger
200: .error("The current thread is not associated with a transaction: "
201: + e.getMessage());
202: throw new SystemException(e);
203:
204: } catch (javax.transaction.SystemException e) {
205: txLogger
206: .error("The Transaction Manager has encountered an unexpected error condition while attempting to commit the transaction: "
207: + e.getMessage());
208:
209: throw new SystemException(e);
210: }
211: }
212:
213: protected void rollbackTransaction(TransactionContext context,
214: Transaction tx) throws SystemException {
215: try {
216: if (txLogger.isInfoEnabled()) {
217: txLogger.info("TX " + policyToString()
218: + ": Rolling back transaction " + tx);
219: }
220: if (tx.equals(context.getTransactionManager()
221: .getTransaction())) {
222:
223: context.getTransactionManager().rollback();
224: } else {
225: tx.rollback();
226: }
227: } catch (IllegalStateException e) {
228:
229: logger
230: .error("The TransactionManager reported an exception while attempting to rollback the transaction: "
231: + e.getMessage());
232: throw new SystemException(e);
233:
234: } catch (javax.transaction.SystemException e) {
235:
236: logger
237: .error("The TransactionManager reported an exception while attempting to rollback the transaction: "
238: + e.getMessage());
239: throw new SystemException(e);
240: }
241: }
242:
243: protected void throwAppExceptionToServer(Throwable appException)
244: throws ApplicationException {
245: throw new ApplicationException(appException);
246: }
247:
248: protected void throwTxExceptionToServer(Throwable sysException)
249: throws ApplicationException {
250: /* Throw javax.transaction.TransactionRolledbackException to remote client */
251:
252: String message = "The transaction has been marked rollback only because the bean encountered a non-application exception :"
253: + sysException.getClass().getName()
254: + " : "
255: + sysException.getMessage();
256: TransactionRolledbackException txException = new TransactionRolledbackException(
257: message, sysException);
258:
259: throw new InvalidateReferenceException(txException);
260:
261: }
262:
263: protected void throwExceptionToServer(Throwable sysException)
264: throws ApplicationException {
265:
266: RemoteException re = new RemoteException(
267: "The bean encountered a non-application exception.",
268: sysException);
269:
270: throw new InvalidateReferenceException(re);
271:
272: }
273:
274: protected void logSystemException(Throwable sysException,
275: TransactionContext context) {
276: Operation operation = context.callContext.getCurrentOperation();
277: if (operation != null && operation.isCallback()) {
278: logger.error("startup.beanInstanceSystemExceptionThrown",
279: sysException, sysException.getMessage());
280: } else {
281: logger.debug("startup.beanInstanceSystemExceptionThrown",
282: sysException, sysException.getMessage());
283: }
284: }
285:
286: protected void discardBeanInstance(Object instance,
287: ThreadContext callContext) {
288: container.discardInstance(instance, callContext);
289: }
290:
291: protected void beginTransaction(TransactionContext context)
292: throws javax.transaction.SystemException {
293: try {
294: context.getTransactionManager().begin();
295: if (txLogger.isInfoEnabled()) {
296: txLogger.info("TX "
297: + policyToString()
298: + ": Started transaction "
299: + context.getTransactionManager()
300: .getTransaction());
301: }
302: } catch (NotSupportedException nse) {
303: logger.error("", nse);
304: }
305: }
306:
307: protected void handleCallbackException() {
308: }
309: }
|