View Javadoc

1   /*
2    * $Id: TransactionTemplate.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transaction;
12  
13  import org.mule.config.i18n.CoreMessages;
14  import org.mule.umo.UMOTransaction;
15  import org.mule.umo.UMOTransactionConfig;
16  
17  import java.beans.ExceptionListener;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  
22  public class TransactionTemplate
23  {
24      private static final Log logger = LogFactory.getLog(TransactionTemplate.class);
25  
26      private final UMOTransactionConfig config;
27      private final ExceptionListener exceptionListener;
28  
29      public TransactionTemplate(UMOTransactionConfig config, ExceptionListener listener)
30      {
31          this.config = config;
32          exceptionListener = listener;
33      }
34  
35      public Object execute(TransactionCallback callback) throws Exception
36      {
37          if (config == null)
38          {
39              return callback.doInTransaction();
40          }
41          else
42          {
43              byte action = config.getAction();
44              UMOTransaction tx = TransactionCoordination.getInstance().getTransaction();
45  
46              if (action == UMOTransactionConfig.ACTION_NONE && tx != null)
47              {
48                  //TODO RM*: I'm not sure there is any value in throwing an exection here, since
49                  //there may be a transaction in progress but has nothing to to with this invocation
50                  //so maybe we just process outside the tx. Not sure yet
51                  //return callback.doInTransaction();
52  
53                  /*
54                      Reply from AP: There is value at the moment, at least in having fewer surprises
55                      with a more explicit config. Current behavior is that of 'Never' TX attribute
56                      in Java EE parlance.
57  
58                      What you refer to, however, is the 'Not Supported' TX behavior. A SUSPEND is performed
59                      in this case with (optional) RESUME later.
60  
61                      Revamping/enhancing the TX attributes in Mule is coming next on my action list for
62                      transactions in Mule after bringing Atomikos & ArjunaTS on-board and ditching a broken JOTM.
63                   */
64  
65                  throw new IllegalTransactionStateException(
66                      CoreMessages.transactionAvailableButActionIs("None"));
67              }
68              else if (action == UMOTransactionConfig.ACTION_ALWAYS_BEGIN && tx != null)
69              {
70                  throw new IllegalTransactionStateException(
71                      CoreMessages.transactionAvailableButActionIs("Always Begin"));
72              }
73              else if (action == UMOTransactionConfig.ACTION_ALWAYS_JOIN && tx == null)
74              {
75                  throw new IllegalTransactionStateException(
76                      CoreMessages.transactionNotAvailableButActionIs("Always Join"));
77              }
78  
79              if (action == UMOTransactionConfig.ACTION_ALWAYS_BEGIN
80                              || (action == UMOTransactionConfig.ACTION_BEGIN_OR_JOIN && tx == null))
81              {
82                  logger.debug("Beginning transaction");
83                  tx = config.getFactory().beginTransaction();
84                  logger.debug("Transaction successfully started");
85              }
86              else
87              {
88                  tx = null;
89              }
90              try
91              {
92                  Object result = callback.doInTransaction();
93                  if (tx != null)
94                  {
95                      if (tx.isRollbackOnly())
96                      {
97                          logger.debug("Transaction is marked for rollback");
98                          tx.rollback();
99                      }
100                     else
101                     {
102                         logger.debug("Committing transaction");
103                         tx.commit();
104                     }
105                 }
106                 return result;
107             }
108             catch (Exception e)
109             {
110                 if (exceptionListener != null)
111                 {
112                     logger
113                         .info("Exception Caught in Transaction template.  Handing off to exception handler: "
114                                         + exceptionListener);
115                     exceptionListener.exceptionThrown(e);
116                 }
117                 else
118                 {
119                     logger
120                         .info("Exception Caught in Transaction template without any exception listeners defined, exception is rethrown.");
121                     if (tx != null)
122                     {
123                         tx.setRollbackOnly();
124                     }
125                 }
126                 if (tx != null)
127                 {
128                     // The exception strategy can choose to route exception
129                     // messages
130                     // as part of the current transaction. So only rollback the
131                     // tx
132                     // if it has been marked for rollback (which is the default
133                     // case in the
134                     // AbstractExceptionListener)
135                     if (tx.isRollbackOnly())
136                     {
137                         logger.debug("Exception caught: rollback transaction", e);
138                         tx.rollback();
139                     }
140                     else
141                     {
142                         tx.commit();
143                     }
144                 }
145                 // we've handled this exception above. just return null now
146                 if (exceptionListener != null)
147                 {
148                     return null;
149                 }
150                 else
151                 {
152                     throw e;
153                 }
154             }
155             catch (Error e)
156             {
157                 if (tx != null)
158                 {
159                     // TODO MULE-863: Correct level?  With trace?
160                     logger.info("Error caught: rollback transaction", e);
161                     tx.rollback();
162                 }
163                 throw e;
164             }
165         }
166     }
167 
168 }