Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* ThreadLocalListener.java
  
  {{IS_NOTE
  	Purpose:
  
  	Description:
  
  	History:
  		Sun Jun  10 23:48:51     2007, Created by henrichen
 }}IS_NOTE
 
 Copyright (C) 2007 Potix Corporation. All Rights Reserved.
 
 {{IS_RIGHT
 	This program is distributed under GPL Version 3.0 in the hope that
 	it will be useful, but WITHOUT ANY WARRANTY.
 }}IS_RIGHT
 */
 package org.zkoss.zkplus.util;
 
 
 import java.util.Map;
 
 import java.util.List;

Listener to make sure servlet thread and ZK event thread got the same ThreadLocal values. You have to declare this listener in WEB-INF/zk.xml as follows.


  <listener>
  <description>ThreadLocal Synchronization Listener</description>
  <listener-class>org.zkoss.zkplus.util.ThreadLocalListener</listener-class>
 </listener>
 

Besides that, you have to specify what ThreadLocal variables you want to sync. They are also spcified in WEB-INF/zk.xml file in the form as below.


  <preference>
    <name>ThreadLocal</name>
    <value>
   class1=field1,field2,...;
   class2=field1,field2,...;
   ...
    </value>
  </preference>
 

For example, to support synchronizing Spring's thread bounded resources, you have to specify the following ThreadLocal variables:


 <preference>
  <name>ThreadLocal</name>
  <value>
  org.springframework.transaction.support.TransactionSynchronizationManager=resources,synchronizations,currentTransactionName,currentTransactionReadOnly,actualTransactionActive;
  org.springframework.orm.hibernate3.SessionFactoryUtils=deferredCloseHolder;
  org.springframework.transaction.interceptor.TransactionAspectSupport=transactionInfoHolder; <!-- ver. 2+ -->
  <!--org.springframework.transaction.interceptor.TransactionAspectSupport=currentTransactionInfo; ver. 1.28 -->
  </value>
 </preference>
 

Another example, when you specify the Spring's bean as scope="session", you have to specify the following ThreadLocal variables since Spring 2.0 use RequestContextHolder to handle the bean's scope.


 <preference>
 <name>ThreadLocal</name>
 <value>
  org.springframework.web.context.request.RequestContextHolder=requestAttributesHolder,inheritableRequestAttributesHolder;
 </value>
 

Author(s):
henrichen
Since:
2.4.1
 
 	private static final Log log = Log.lookup(ThreadLocalListener.class);
 	private Map _fieldsMap//(class name, String[] of fields)
 	private Map _threadLocalsMap//(class name, ThreadLocal_Contents[] for fields)
 	private final boolean _enabled//whether event thread enabled
 
 	public ThreadLocalListener() {
 		final WebApp app = Executions.getCurrent().getDesktop().getWebApp();
		 = (Mapapp.getAttribute("zkplus.util.ThreadLocalListener.fieldsMap");
		if ( == null) {
			 = new HashMap(8);
			app.setAttribute("zkplus.util.ThreadLocalListener.fieldsMap");
			//read preference
			final Configuration config = app.getConfiguration();
			final String val = config.getPreference("ThreadLocal"null);
			if (val != null) {
				final Collection klassSets = CollectionsX.parse(nullval';');
				for(Iterator its = klassSets.iterator(); its.hasNext(); ) {
					final String klassSetStr = (Stringits.next();
					final Collection klassSet = CollectionsX.parse(nullklassSetStr'=');
					final Iterator itz = klassSet.iterator();
					final String klass = (Stringitz.next();
					final String fieldsStr = (Stringitz.next();
					final Collection fields = CollectionsX.parse(nullfieldsStr',');
					.put(klassfields.toArray(new String[fields.size()]));
				}
			}
		}
	}
	//-- 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() {
		for(final Iterator it.entrySet().iterator(); it.hasNext(); ) {
			final Entry me = (Entryit.next();
			try {
				final String clsName = (Stringme.getKey();
				final Class cls = Classes.forNameByThread(clsName);
				final String[] fields = (String[]) me.getValue();
				final Object[] threadLocals = new Object[fields.length];
				.put(clsNamethreadLocals);
				for(int j = 0; j < threadLocals.length; ++j) {
					try {
						threadLocals[j] = getThreadLocal(clsfields[j]).get();
catch (SystemException ex) {
						//ignore
						continue;
					}
				}
catch (ClassNotFoundException ex) {
				//ignore
				continue;
			}
		}
	}
	private void setThreadLocals() {
			final Entry me = (Entryit.next();
			try {
				final String clsName = (Stringme.getKey();
				final Class cls = Classes.forNameByThread(clsName);
				final Object[] threadLocals = (Object[]) me.getValue();
				final String[] fields = (String[]) .get(clsName);
				for(int j = 0; j < threadLocals.length; ++j) {
					getThreadLocal(clsfields[j]).set(threadLocals[j]);
				}
catch (ClassNotFoundException ex) {
				continue;
			}
		}
	}
	private ThreadLocal getThreadLocal(Class clsString fldname) {
		return ThreadLocals.getThreadLocal(clsfldname);
	}
New to GrepCode? Check out our FAQ X