Source Code Cross Referenced for TransactionAspectSupport.java in  » J2EE » spring-framework-2.5 » org » springframework » transaction » interceptor » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.transaction.interceptor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
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, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.transaction.interceptor;
018:
019:        import java.lang.reflect.Method;
020:        import java.util.Properties;
021:
022:        import org.apache.commons.logging.Log;
023:        import org.apache.commons.logging.LogFactory;
024:
025:        import org.springframework.beans.factory.InitializingBean;
026:        import org.springframework.transaction.NoTransactionException;
027:        import org.springframework.transaction.PlatformTransactionManager;
028:        import org.springframework.transaction.TransactionStatus;
029:        import org.springframework.transaction.TransactionSystemException;
030:        import org.springframework.util.ClassUtils;
031:
032:        /**
033:         * Base class for transactional aspects, such as the AOP Alliance
034:         * {@link TransactionInterceptor} or an AspectJ aspect.
035:         *
036:         * <p>This enables the underlying Spring transaction infrastructure to be used
037:         * easily to implement an aspect for any aspect system.
038:         *
039:         * <p>Subclasses are responsible for calling methods in this class in the
040:         * correct order.
041:         *
042:         * <p>If no transaction name has been specified in the
043:         * <code>TransactionAttribute</code>, the exposed name will be the
044:         * <code>fully-qualified class name + "." + method name</code>
045:         * (by default).
046:         *
047:         * <p>Uses the <b>Strategy</b> design pattern. A
048:         * <code>PlatformTransactionManager</code> implementation will perform the
049:         * actual transaction management, and a <code>TransactionAttributeSource</code>
050:         * is used for determining transaction definitions.
051:         *
052:         * <p>A transaction aspect is serializable if it's
053:         * <code>PlatformTransactionManager</code> and
054:         * <code>TransactionAttributeSource</code> are serializable.
055:         *
056:         * @author Rod Johnson
057:         * @author Juergen Hoeller
058:         * @since 1.1
059:         * @see #setTransactionManager
060:         * @see #setTransactionAttributes
061:         * @see #setTransactionAttributeSource
062:         */
063:        public abstract class TransactionAspectSupport implements 
064:                InitializingBean {
065:
066:            // NOTE: This class must not implement Serializable because it serves as base
067:            // class for AspectJ aspects (which are not allowed to implement Serializable)!
068:
069:            /**
070:             * Holder to support the <code>currentTransactionStatus()</code> method,
071:             * and to support communication between different cooperating advices
072:             * (e.g. before and after advice) if the aspect involves more than a
073:             * single method (as will be the case for around advice).
074:             */
075:            private static final ThreadLocal transactionInfoHolder = new ThreadLocal();
076:
077:            /**
078:             * Subclasses can use this to return the current TransactionInfo.
079:             * Only subclasses that cannot handle all operations in one method,
080:             * such as an AspectJ aspect involving distinct before and after advice,
081:             * need to use this mechanism to get at the current TransactionInfo.
082:             * An around advice such as an AOP Alliance MethodInterceptor can hold a
083:             * reference to the TransactionInfo throughout the aspect method.
084:             * <p>A TransactionInfo will be returned even if no transaction was created.
085:             * The <code>TransactionInfo.hasTransaction()</code> method can be used to query this.
086:             * <p>To find out about specific transaction characteristics, consider using
087:             * TransactionSynchronizationManager's <code>isSynchronizationActive()</code>
088:             * and/or <code>isActualTransactionActive()</code> methods.
089:             * @return TransactionInfo bound to this thread, or <code>null</code> if none
090:             * @see TransactionInfo#hasTransaction()
091:             * @see org.springframework.transaction.support.TransactionSynchronizationManager#isSynchronizationActive()
092:             * @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()
093:             */
094:            protected static TransactionInfo currentTransactionInfo()
095:                    throws NoTransactionException {
096:                return (TransactionInfo) transactionInfoHolder.get();
097:            }
098:
099:            /**
100:             * Return the transaction status of the current method invocation.
101:             * Mainly intended for code that wants to set the current transaction
102:             * rollback-only but not throw an application exception.
103:             * @throws NoTransactionException if the transaction info cannot be found,
104:             * because the method was invoked outside an AOP invocation context
105:             */
106:            public static TransactionStatus currentTransactionStatus()
107:                    throws NoTransactionException {
108:                TransactionInfo info = currentTransactionInfo();
109:                if (info == null) {
110:                    throw new NoTransactionException(
111:                            "No transaction aspect-managed TransactionStatus in scope");
112:                }
113:                return currentTransactionInfo().transactionStatus;
114:            }
115:
116:            protected final Log logger = LogFactory.getLog(getClass());
117:
118:            /** Delegate used to create, commit and rollback transactions */
119:            private PlatformTransactionManager transactionManager;
120:
121:            /** Helper used to find transaction attributes */
122:            private TransactionAttributeSource transactionAttributeSource;
123:
124:            /**
125:             * Set the transaction manager. This will perform actual
126:             * transaction management: This class is just a way of invoking it.
127:             */
128:            public void setTransactionManager(
129:                    PlatformTransactionManager transactionManager) {
130:                this .transactionManager = transactionManager;
131:            }
132:
133:            /**
134:             * Return the transaction manager.
135:             */
136:            public PlatformTransactionManager getTransactionManager() {
137:                return this .transactionManager;
138:            }
139:
140:            /**
141:             * Set properties with method names as keys and transaction attribute
142:             * descriptors (parsed via TransactionAttributeEditor) as values:
143:             * e.g. key = "myMethod", value = "PROPAGATION_REQUIRED,readOnly".
144:             * <p>Note: Method names are always applied to the target class,
145:             * no matter if defined in an interface or the class itself.
146:             * <p>Internally, a NameMatchTransactionAttributeSource will be
147:             * created from the given properties.
148:             * @see #setTransactionAttributeSource
149:             * @see TransactionAttributeEditor
150:             * @see NameMatchTransactionAttributeSource
151:             */
152:            public void setTransactionAttributes(
153:                    Properties transactionAttributes) {
154:                NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
155:                tas.setProperties(transactionAttributes);
156:                this .transactionAttributeSource = tas;
157:            }
158:
159:            /**
160:             * Set multiple transaction attribute sources which are used to find transaction
161:             * attributes. Will build a CompositeTransactionAttributeSource for the given sources.
162:             * @see CompositeTransactionAttributeSource
163:             * @see MethodMapTransactionAttributeSource
164:             * @see NameMatchTransactionAttributeSource
165:             * @see AttributesTransactionAttributeSource
166:             * @see org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
167:             */
168:            public void setTransactionAttributeSources(
169:                    TransactionAttributeSource[] transactionAttributeSources) {
170:                this .transactionAttributeSource = new CompositeTransactionAttributeSource(
171:                        transactionAttributeSources);
172:            }
173:
174:            /**
175:             * Set the transaction attribute source which is used to find transaction
176:             * attributes. If specifying a String property value, a PropertyEditor
177:             * will create a MethodMapTransactionAttributeSource from the value.
178:             * @see TransactionAttributeSourceEditor
179:             * @see MethodMapTransactionAttributeSource
180:             * @see NameMatchTransactionAttributeSource
181:             * @see AttributesTransactionAttributeSource
182:             * @see org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
183:             */
184:            public void setTransactionAttributeSource(
185:                    TransactionAttributeSource transactionAttributeSource) {
186:                this .transactionAttributeSource = transactionAttributeSource;
187:            }
188:
189:            /**
190:             * Return the transaction attribute source.
191:             */
192:            public TransactionAttributeSource getTransactionAttributeSource() {
193:                return this .transactionAttributeSource;
194:            }
195:
196:            /**
197:             * Check that required properties were set.
198:             */
199:            public void afterPropertiesSet() {
200:                if (getTransactionManager() == null) {
201:                    throw new IllegalArgumentException(
202:                            "Property 'transactionManager' is required");
203:                }
204:                if (getTransactionAttributeSource() == null) {
205:                    throw new IllegalArgumentException(
206:                            "Either 'transactionAttributeSource' or 'transactionAttributes' is required: "
207:                                    + "If there are no transactional methods, then don't use a transaction aspect.");
208:                }
209:            }
210:
211:            /**
212:             * Create a transaction if necessary, based on the given method and class.
213:             * <p>Performs a default TransactionAttribute lookup for the given method.
214:             * @param method method about to execute
215:             * @param targetClass class the method is on
216:             * @return a TransactionInfo object, whether or not a transaction was created.
217:             * The hasTransaction() method on TransactionInfo can be used to tell if there
218:             * was a transaction created.
219:             * @see #getTransactionAttributeSource()
220:             */
221:            protected TransactionInfo createTransactionIfNecessary(
222:                    Method method, Class targetClass) {
223:                // If the transaction attribute is null, the method is non-transactional.
224:                TransactionAttribute txAttr = getTransactionAttributeSource()
225:                        .getTransactionAttribute(method, targetClass);
226:                return createTransactionIfNecessary(txAttr,
227:                        methodIdentification(method));
228:            }
229:
230:            /**
231:             * Convenience method to return a String representation of this Method
232:             * for use in logging. Can be overridden in subclasses to provide a
233:             * different identifier for the given method.
234:             * @param method the method we're interested in
235:             * @return log message identifying this method
236:             * @see org.springframework.util.ClassUtils#getQualifiedMethodName
237:             */
238:            protected String methodIdentification(Method method) {
239:                return ClassUtils.getQualifiedMethodName(method);
240:            }
241:
242:            /**
243:             * Create a transaction if necessary based on the given TransactionAttribute.
244:             * <p>Allows callers to perform custom TransactionAttribute lookups through
245:             * the TransactionAttributeSource.
246:             * @param txAttr the TransactionAttribute (may be <code>null</code>)
247:             * @param joinpointIdentification the fully qualified method name
248:             * (used for monitoring and logging purposes)
249:             * @return a TransactionInfo object, whether or not a transaction was created.
250:             * The <code>hasTransaction()</code> method on TransactionInfo can be used to
251:             * tell if there was a transaction created.
252:             * @see #getTransactionAttributeSource()
253:             */
254:            protected TransactionInfo createTransactionIfNecessary(
255:                    TransactionAttribute txAttr,
256:                    final String joinpointIdentification) {
257:
258:                // If no name specified, apply method identification as transaction name.
259:                if (txAttr != null && txAttr.getName() == null) {
260:                    txAttr = new DelegatingTransactionAttribute(txAttr) {
261:                        public String getName() {
262:                            return joinpointIdentification;
263:                        }
264:                    };
265:                }
266:
267:                TransactionStatus status = null;
268:                if (txAttr != null) {
269:                    PlatformTransactionManager tm = getTransactionManager();
270:                    if (tm != null) {
271:                        status = tm.getTransaction(txAttr);
272:                    } else {
273:                        if (logger.isDebugEnabled()) {
274:                            logger
275:                                    .debug("Skipping transactional joinpoint ["
276:                                            + joinpointIdentification
277:                                            + "] because no transaction manager has been configured");
278:                        }
279:                    }
280:                }
281:                return prepareTransactionInfo(txAttr, joinpointIdentification,
282:                        status);
283:            }
284:
285:            /**
286:             * Prepare a TransactionInfo for the given attribute and status object.
287:             * @param txAttr the TransactionAttribute (may be <code>null</code>)
288:             * @param joinpointIdentification the fully qualified method name
289:             * (used for monitoring and logging purposes)
290:             * @param status the TransactionStatus for the current transaction
291:             * @return the prepared TransactionInfo object
292:             */
293:            protected TransactionInfo prepareTransactionInfo(
294:                    TransactionAttribute txAttr,
295:                    String joinpointIdentification, TransactionStatus status) {
296:
297:                TransactionInfo txInfo = new TransactionInfo(txAttr,
298:                        joinpointIdentification);
299:                if (txAttr != null) {
300:                    // We need a transaction for this method
301:                    if (logger.isTraceEnabled()) {
302:                        logger.trace("Getting transaction for ["
303:                                + txInfo.getJoinpointIdentification() + "]");
304:                    }
305:                    // The transaction manager will flag an error if an incompatible tx already exists
306:                    txInfo.newTransactionStatus(status);
307:                } else {
308:                    // The TransactionInfo.hasTransaction() method will return
309:                    // false. We created it only to preserve the integrity of
310:                    // the ThreadLocal stack maintained in this class.
311:                    if (logger.isTraceEnabled())
312:                        logger.trace("Don't need to create transaction for ["
313:                                + joinpointIdentification
314:                                + "]: This method isn't transactional.");
315:                }
316:
317:                // We always bind the TransactionInfo to the thread, even if we didn't create
318:                // a new transaction here. This guarantees that the TransactionInfo stack
319:                // will be managed correctly even if no transaction was created by this aspect.
320:                txInfo.bindToThread();
321:                return txInfo;
322:            }
323:
324:            /**
325:             * Execute after successful completion of call, but not after an exception was handled.
326:             * Do nothing if we didn't create a transaction.
327:             * @param txInfo information about the current transaction
328:             */
329:            protected void commitTransactionAfterReturning(
330:                    TransactionInfo txInfo) {
331:                if (txInfo != null && txInfo.hasTransaction()) {
332:                    if (logger.isTraceEnabled()) {
333:                        logger.trace("Completing transaction for ["
334:                                + txInfo.getJoinpointIdentification() + "]");
335:                    }
336:                    getTransactionManager().commit(
337:                            txInfo.getTransactionStatus());
338:                }
339:            }
340:
341:            /**
342:             * Handle a throwable, completing the transaction.
343:             * We may commit or roll back, depending on the configuration.
344:             * @param txInfo information about the current transaction
345:             * @param ex throwable encountered
346:             */
347:            protected void completeTransactionAfterThrowing(
348:                    TransactionInfo txInfo, Throwable ex) {
349:                if (txInfo != null && txInfo.hasTransaction()) {
350:                    if (logger.isTraceEnabled()) {
351:                        logger.trace("Completing transaction for ["
352:                                + txInfo.getJoinpointIdentification()
353:                                + "] after exception: " + ex);
354:                    }
355:                    if (txInfo.transactionAttribute.rollbackOn(ex)) {
356:                        try {
357:                            getTransactionManager().rollback(
358:                                    txInfo.getTransactionStatus());
359:                        } catch (TransactionSystemException ex2) {
360:                            logger
361:                                    .error(
362:                                            "Application exception overridden by rollback exception",
363:                                            ex);
364:                            ex2.initApplicationException(ex);
365:                            throw ex2;
366:                        } catch (RuntimeException ex2) {
367:                            logger
368:                                    .error(
369:                                            "Application exception overridden by rollback exception",
370:                                            ex);
371:                            throw ex2;
372:                        } catch (Error err) {
373:                            logger
374:                                    .error(
375:                                            "Application exception overridden by rollback error",
376:                                            ex);
377:                            throw err;
378:                        }
379:                    } else {
380:                        // We don't roll back on this exception.
381:                        // Will still roll back if TransactionStatus.isRollbackOnly() is true.
382:                        try {
383:                            getTransactionManager().commit(
384:                                    txInfo.getTransactionStatus());
385:                        } catch (TransactionSystemException ex2) {
386:                            logger
387:                                    .error(
388:                                            "Application exception overridden by commit exception",
389:                                            ex);
390:                            ex2.initApplicationException(ex);
391:                            throw ex2;
392:                        } catch (RuntimeException ex2) {
393:                            logger
394:                                    .error(
395:                                            "Application exception overridden by commit exception",
396:                                            ex);
397:                            throw ex2;
398:                        } catch (Error err) {
399:                            logger
400:                                    .error(
401:                                            "Application exception overridden by commit error",
402:                                            ex);
403:                            throw err;
404:                        }
405:                    }
406:                }
407:            }
408:
409:            /**
410:             * Reset the TransactionInfo ThreadLocal.
411:             * <p>Call this in all cases: exception or normal return!
412:             * @param txInfo information about the current transaction (may be <code>null</code>)
413:             */
414:            protected void cleanupTransactionInfo(TransactionInfo txInfo) {
415:                if (txInfo != null) {
416:                    txInfo.restoreThreadLocalStatus();
417:                }
418:            }
419:
420:            /**
421:             * Opaque object used to hold Transaction information. Subclasses
422:             * must pass it back to methods on this class, but not see its internals.
423:             */
424:            protected class TransactionInfo {
425:
426:                private final TransactionAttribute transactionAttribute;
427:
428:                private final String joinpointIdentification;
429:
430:                private TransactionStatus transactionStatus;
431:
432:                private TransactionInfo oldTransactionInfo;
433:
434:                public TransactionInfo(
435:                        TransactionAttribute transactionAttribute,
436:                        String joinpointIdentification) {
437:                    this .transactionAttribute = transactionAttribute;
438:                    this .joinpointIdentification = joinpointIdentification;
439:                }
440:
441:                public TransactionAttribute getTransactionAttribute() {
442:                    return this .transactionAttribute;
443:                }
444:
445:                /**
446:                 * Return a String representation of this joinpoint (usually a Method call)
447:                 * for use in logging.
448:                 */
449:                public String getJoinpointIdentification() {
450:                    return this .joinpointIdentification;
451:                }
452:
453:                public void newTransactionStatus(TransactionStatus status) {
454:                    this .transactionStatus = status;
455:                }
456:
457:                public TransactionStatus getTransactionStatus() {
458:                    return this .transactionStatus;
459:                }
460:
461:                /**
462:                 * Return whether a transaction was created by this aspect,
463:                 * or whether we just have a placeholder to keep ThreadLocal stack integrity.
464:                 */
465:                public boolean hasTransaction() {
466:                    return (this .transactionStatus != null);
467:                }
468:
469:                private void bindToThread() {
470:                    // Expose current TransactionStatus, preserving any existing TransactionStatus
471:                    // for restoration after this transaction is complete.
472:                    this .oldTransactionInfo = (TransactionInfo) transactionInfoHolder
473:                            .get();
474:                    transactionInfoHolder.set(this );
475:                }
476:
477:                private void restoreThreadLocalStatus() {
478:                    // Use stack to restore old transaction TransactionInfo.
479:                    // Will be null if none was set.
480:                    transactionInfoHolder.set(this.oldTransactionInfo);
481:                }
482:            }
483:
484:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.