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 javax.transaction.Status;
019:
020: import org.apache.openejb.ApplicationException;
021: import org.apache.openejb.SystemException;
022:
023: /**
024: * 17.6.2.2 Required
025: *
026: * The Container must invoke an enterprise Bean method whose transaction
027: * attribute is set to Required with a valid transaction context.
028: *
029: * If a client invokes the enterprise Bean's method while the client is
030: * associated with a transaction context, the container invokes the enterprise
031: * Bean's method in the client's transaction context.
032: *
033: * If the client invokes the enterprise Bean's method while the client is not
034: * associated with a transaction context, the container automatically starts a
035: * new transaction before delegating a method call to the enterprise Bean
036: * business method. The Container automatically enlists all the resource
037: * managers accessed by the business method with the transaction. If the
038: * business method invokes other enterprise beans, the Container passes the
039: * transaction context with the invocation. The Container attempts to commit
040: * the transaction when the business method has completed. The container
041: * performs the commit protocol before the method result is sent to the client.
042: *
043: */
044: public class TxRequired extends TransactionPolicy {
045:
046: public TxRequired(TransactionContainer container) {
047: super (Type.Required, container);
048: }
049:
050: public void beforeInvoke(Object instance, TransactionContext context)
051: throws SystemException, ApplicationException {
052:
053: try {
054:
055: context.clientTx = context.getTransactionManager()
056: .getTransaction();
057:
058: if (context.clientTx == null) {
059: beginTransaction(context);
060: }
061:
062: context.currentTx = context.getTransactionManager()
063: .getTransaction();
064:
065: } catch (javax.transaction.SystemException se) {
066: logger.error("Exception during getTransaction()", se);
067: throw new SystemException(se);
068: }
069: }
070:
071: public void afterInvoke(Object instance, TransactionContext context)
072: throws ApplicationException, SystemException {
073:
074: try {
075: if (context.clientTx != null)
076: return;
077:
078: if (context.currentTx.getStatus() == Status.STATUS_ACTIVE) {
079: commitTransaction(context, context.currentTx);
080: } else {
081: rollbackTransaction(context, context.currentTx);
082: }
083:
084: } catch (javax.transaction.SystemException se) {
085: logger.debug("Exception during getTransaction()", se);
086: throw new SystemException(se);
087: }
088: }
089:
090: public void handleApplicationException(Throwable appException,
091: boolean rollback, TransactionContext context)
092: throws ApplicationException, SystemException {
093: if (rollback && context.currentTx != null)
094: markTxRollbackOnly(context.currentTx);
095:
096: throw new ApplicationException(appException);
097: }
098:
099: public void handleSystemException(Throwable sysException,
100: Object instance, TransactionContext context)
101: throws ApplicationException, SystemException {
102:
103: /* [1] Log the system exception or error **********/
104: logSystemException(sysException, context);
105:
106: boolean runningInContainerTransaction = (!context.currentTx
107: .equals(context.clientTx));
108: if (runningInContainerTransaction) {
109: /* [2] Mark the transaction for rollback. afterInvoke() will roll it back */
110: markTxRollbackOnly(context.currentTx);
111:
112: /* [3] Discard instance. **************************/
113: discardBeanInstance(instance, context.callContext);
114:
115: /* [4] Throw RemoteException to client ************/
116: throwExceptionToServer(sysException);
117: } else {
118: /* [2] Mark the transaction for rollback. *********/
119: markTxRollbackOnly(context.clientTx);
120:
121: /* [3] Discard instance. **************************/
122: discardBeanInstance(instance, context.callContext);
123:
124: /* [4] Throw TransactionRolledbackException to client ************/
125: throwTxExceptionToServer(sysException);
126: }
127: }
128: }
|