Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* SpringTransactionSynchronizationListener.java
  
  	Purpose:
  		
  	Description:
  		
  	History:
  		Tue Sep  15 13:55:11     2006, Created by henrichen
  
 Copyright (C) 2006 Potix Corporation. All Rights Reserved.
 
 {{IS_RIGHT
 	This program is distributed under LGPL Version 2.1 in the hope that
 	it will be useful, but WITHOUT ANY WARRANTY.
 }}IS_RIGHT
 */
 package org.zkoss.zkplus.spring;
 
 import java.util.List;
 

Listener to make sure each ZK thread got the same ThreadLocal value of the spring's org.springframework.transaction.support.TransactionSynchronizationManager; especially those thread bound resources.

This listener is used with Spring Framework (version 1.2.8+) "thread" bounded resources.


  <listener>
  <description>Spring TransactionSynchronizationManager handler</description>
  <listener-class>org.zkoss.zkplus.spring.SpringTransactionSynchronizationListener</listener-class>
 </listener>
 

Applicable to Spring Framework version 2.x or later

Author(s):
henrichen
 
 	private static final Logger log = LoggerFactory.getLogger(SpringTransactionSynchronizationListener.class);
 	
 	private Object[] _threadLocals = null;
 	private final boolean _enabled//whether event thread enabled
 
 		final WebApp app = Executions.getCurrent().getDesktop().getWebApp();
 	}
 
 	//-- EventThreadInit --//
 	public void prepare(Component compEvent evt) {
 		if () {
 			getThreadLocals(); //get from servlet thread's ThreadLocal
 		}
 	}
 	
 	public boolean init(Component compEvent evt) {
 		if () {
 			setThreadLocals(); //copy to event thread's ThreadLocal
 		}
 		return true;
 	}
 
 	//-- EventThreadCleanup --//
 	public void cleanup(Component compEvent evtList errs) {
 		if () {
 			getThreadLocals(); //get from event thread's ThreadLocal
 			//we don't handle the exception since the ZK engine will throw it again!
 		}
 	}
 
 	public void complete(Component compEvent evt) {
 		if () {
 			setThreadLocals(); //copy to servlet thread's ThreadLocal
 		}
 	}
 
 	//-- EventThreadResume --//
 	public void beforeResume(Component compEvent evt) {
 		if () {
 			getThreadLocals(); //get from servlet thread's ThreadLocal
 		}
 	}
 	
	public void afterResume(Component compEvent evt) {
		if () {
			setThreadLocals(); //copy to event thread's ThreadLocal
		}
	}
	public void abortResume(Component compEvent evt){
		//do nothing
	}
	//-- utilities --//
	private void getThreadLocals() {
		try {
			Class cls = Classes.forNameByThread("org.springframework.transaction.support.TransactionSynchronizationManager");
			 = new Object[7];
			[0] = getThreadLocal(cls"resources").get();
			[1] = getThreadLocal(cls"synchronizations").get();
			[2] = getThreadLocal(cls"currentTransactionName").get();
			[3] = getThreadLocal(cls"currentTransactionReadOnly").get();
			[4] = getThreadLocal(cls"actualTransactionActive").get();
			//20070907, Henri Chen: bug 1785457, hibernate3 might not used
			try {
				cls = Classes.forNameByThread("org.springframework.orm.hibernate3.SessionFactoryUtils");
				[5] = getThreadLocal(cls"deferredCloseHolder").get();
catch (ClassNotFoundException ex) {
				//ignore if hibernate 3 is not used.
			}
			cls = Classes.forNameByThread("org.springframework.transaction.interceptor.TransactionAspectSupport");
			//Spring 1.2.8 and Spring 2.0.x, the ThreadLocal field name has changed, default use 2.0.x
			//2.0.x transactionInfoHolder
			//1.2.8 currentTransactionInfo
			try { 
				[6] = getThreadLocal(cls"transactionInfoHolder").get();
catch (SystemException ex) {
				if (ex.getCause() instanceof NoSuchFieldException) {
					[6] = getThreadLocal(cls"currentTransactionInfo").get();
else {
					throw ex;
				}
			}
catch (ClassNotFoundException ex) {
			throw UiException.Aide.wrap(ex);
		}
	}
	@SuppressWarnings("unchecked")	
	private void setThreadLocals() {
		if ( != null) {
			try {
				Class cls = Classes.forNameByThread("org.springframework.transaction.support.TransactionSynchronizationManager");
				getThreadLocal(cls"resources").set([0]);
				getThreadLocal(cls"synchronizations").set([1]);
				getThreadLocal(cls"currentTransactionName").set([2]);
				getThreadLocal(cls"currentTransactionReadOnly").set([3]);
				getThreadLocal(cls"actualTransactionActive").set([4]);
				//20070907, Henri Chen: bug 1785457, hibernate3 might not used
				try {
					cls = Classes.forNameByThread("org.springframework.orm.hibernate3.SessionFactoryUtils");
					getThreadLocal(cls"deferredCloseHolder").set([5]);
catch (ClassNotFoundException ex) {
					//ignore if hibernate 3 is not used.
				cls = Classes.forNameByThread("org.springframework.transaction.interceptor.TransactionAspectSupport");
				//Spring 1.2.8 and Spring 2.0.x, the ThreadLocal field name has changed, default use 2.0.x
				//2.0.x transactionInfoHolder
				//1.2.8 currentTransactionInfo
				try { 
					getThreadLocal(cls"transactionInfoHolder").set([6]);
catch (SystemException ex) {
					if (ex.getCause() instanceof NoSuchFieldException) {
						getThreadLocal(cls"currentTransactionInfo").set([6]);
else {
						throw ex;
					}
				}
				 = null;
catch (ClassNotFoundException ex) {
				throw UiException.Aide.wrap(ex);
			}
		}
	}
	private ThreadLocal getThreadLocal(Class clsString fldname) {
		return ThreadLocals.getThreadLocal(clsfldname);
	}
New to GrepCode? Check out our FAQ X