1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.openejb.core.transaction;
18
19 import javax.transaction.Status;
20
21 import org.apache.openejb.ApplicationException;
22 import org.apache.openejb.SystemException;
23
24 /**
25 * 17.6.2.2 Required
26 *
27 * The Container must invoke an enterprise Bean method whose transaction
28 * attribute is set to Required with a valid transaction context.
29 *
30 * If a client invokes the enterprise Bean's method while the client is
31 * associated with a transaction context, the container invokes the enterprise
32 * Bean's method in the client's transaction context.
33 *
34 * If the client invokes the enterprise Bean's method while the client is not
35 * associated with a transaction context, the container automatically starts a
36 * new transaction before delegating a method call to the enterprise Bean
37 * business method. The Container automatically enlists all the resource
38 * managers accessed by the business method with the transaction. If the
39 * business method invokes other enterprise beans, the Container passes the
40 * transaction context with the invocation. The Container attempts to commit
41 * the transaction when the business method has completed. The container
42 * performs the commit protocol before the method result is sent to the client.
43 *
44 */
45 public class TxRequired extends TransactionPolicy {
46
47 public TxRequired(TransactionContainer container) {
48 super(Type.Required, container);
49 }
50
51 public void beforeInvoke(Object instance, TransactionContext context) throws SystemException, ApplicationException {
52 context.callContext.set(Type.class, getPolicyType());
53
54 try {
55
56 context.clientTx = context.getTransactionManager().getTransaction();
57
58 if (context.clientTx == null) {
59 beginTransaction(context);
60 }
61
62 context.currentTx = context.getTransactionManager().getTransaction();
63
64 } catch (javax.transaction.SystemException se) {
65 logger.error("Exception during getTransaction()", se);
66 throw new SystemException(se);
67 }
68 }
69
70 public void afterInvoke(Object instance, TransactionContext context) throws ApplicationException, SystemException {
71
72 try {
73 if (context.clientTx != null) return;
74
75 if (context.currentTx.getStatus() == Status.STATUS_ACTIVE) {
76 commitTransaction(context, context.currentTx);
77 } else {
78 rollbackTransaction(context, context.currentTx);
79 }
80
81 } catch (javax.transaction.SystemException se) {
82 logger.debug("Exception during getTransaction()", se);
83 throw new SystemException(se);
84 }
85 }
86
87 public void handleApplicationException(Throwable appException, boolean rollback, TransactionContext context) throws ApplicationException, SystemException {
88 if (rollback && context.currentTx != null) markTxRollbackOnly(context.currentTx);
89
90 throw new ApplicationException(appException);
91 }
92
93 public void handleSystemException(Throwable sysException, Object instance, TransactionContext context) throws ApplicationException, SystemException {
94
95 /* [1] Log the system exception or error **********/
96 logSystemException(sysException, context);
97
98 boolean runningInContainerTransaction = (!context.currentTx.equals(context.clientTx));
99 if (runningInContainerTransaction) {
100 /* [2] Mark the transaction for rollback. afterInvoke() will roll it back */
101 markTxRollbackOnly(context.currentTx);
102
103 /* [3] Discard instance. **************************/
104 discardBeanInstance(instance, context.callContext);
105
106 /* [4] Throw RemoteException to client ************/
107 throwExceptionToServer(sysException);
108 } else {
109 /* [2] Mark the transaction for rollback. *********/
110 markTxRollbackOnly(context.clientTx);
111
112 /* [3] Discard instance. **************************/
113 discardBeanInstance(instance, context.callContext);
114
115 /* [4] Throw TransactionRolledbackException to client ************/
116 throwTxExceptionToServer(sysException);
117 }
118 }
119 }