001    /*****************************************************************************
002     * Copyright (c) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the LICENSE.txt file.                                                     *
007     *                                                                           *
008     * Original code by Joerg Schaible                                           *
009     *****************************************************************************/
010    
011    package org.picocontainer.gems.adapters;
012    
013    import com.thoughtworks.proxy.ProxyFactory;
014    import com.thoughtworks.proxy.factory.StandardProxyFactory;
015    
016    import org.picocontainer.ComponentAdapter;
017    import org.picocontainer.Parameter;
018    import org.picocontainer.PicoIntrospectionException;
019    import org.picocontainer.defaults.AssignabilityRegistrationException;
020    import org.picocontainer.defaults.CachingComponentAdapter;
021    import org.picocontainer.defaults.ComponentAdapterFactory;
022    import org.picocontainer.defaults.DecoratingComponentAdapterFactory;
023    import org.picocontainer.defaults.NotConcreteRegistrationException;
024    
025    
026    /**
027     * A {@link ComponentAdapterFactory} for components kept in {@link ThreadLocal} instances.
028     * <p>
029     * This factory has two operating modes. By default it ensures, that every thread uses its own component at any time.
030     * This mode ({@link #ENSURE_THREAD_LOCALITY}) makes internal usage of a {@link ThreadLocalComponentAdapter}. If the
031     * application architecture ensures, that the thread that creates the component is always also the thread that is th
032     * only user, you can set the mode {@link #THREAD_ENSURES_LOCALITY}. In this mode the factory uses a simple
033     * {@link CachingComponentAdapter} that uses a {@link ThreadLocalReference} to cache the component.
034     * </p>
035     * <p>
036     * See the use cases for the subtile difference:
037     * </p>
038     * <p>
039     * <code>THREAD_ENSURES_LOCALITY</code> is applicable, if the pico container is requested for a thread local component
040     * from the working thread e.g. in a web application for a request. In this environment it is ensured, that the request
041     * is processed from the same thread and the thread local component is reused, if a previous request was handled in the
042     * same thread. Note that thi scenario fails badly, if the thread local component is created because of another cached
043     * component indirectly by a dependecy. In this case the cached component already have an instance of the thread local
044     * component, that may have been created in another thread, since only the component adapter for the thread local
045     * component can ensure a unique component for each thread.
046     * </p>
047     * <p>
048     * <code>ENSURES_THREAD_LOCALITY</code> solves this problem. In this case the returned component is just a proxy for
049     * the thread local component and this proxy ensures, that a new component is created for each thread. Even if another
050     * cached component has an indirect dependency on the thread local component, the proxy ensures unique instances. This
051     * is vital for a multithreaded application that uses EJBs.
052     * </p>
053     * @author J&ouml;rg Schaible
054     */
055    public class ThreadLocalComponentAdapterFactory extends DecoratingComponentAdapterFactory {
056    
057        /**
058         * <code>ENSURE_THREAD_LOCALITY</code> is the constant for created {@link ComponentAdapter} instances, that ensure
059         * unique instances of the component by delivering a proxy for the component.
060         */
061        public static final boolean ENSURE_THREAD_LOCALITY = true;
062        /**
063         * <code>THREAD_ENSURES_LOCALITY</code> is the constant for created {@link ComponentAdapter} instances, that
064         * create for the current thread a new component.
065         */
066        public static final boolean THREAD_ENSURES_LOCALITY = false;
067    
068        private final boolean ensureThreadLocal;
069        private ProxyFactory proxyFactory;
070    
071        /**
072         * Constructs a wrapping ThreadLocalComponentAdapterFactory, that ensures the usage of the ThreadLocal. The Proxy
073         * instances are generated by the JDK.
074         * @param delegate The delegated {@link ComponentAdapterFactory}.
075         */
076        public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate) {
077            this(delegate, new StandardProxyFactory());
078        }
079    
080        /**
081         * Constructs a wrapping ThreadLocalComponentAdapterFactory, that ensures the usage of the ThreadLocal.
082         * @param delegate The delegated ComponentAdapterFactory.
083         * @param proxyFactory The {@link ProxyFactory} to use.
084         */
085        public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate, final ProxyFactory proxyFactory) {
086            this(delegate, ENSURE_THREAD_LOCALITY, proxyFactory);
087        }
088    
089        /**
090         * Constructs a wrapping ThreadLocalComponentAdapterFactory.
091         * @param delegate The delegated ComponentAdapterFactory.
092         * @param ensure {@link #ENSURE_THREAD_LOCALITY} or {@link #THREAD_ENSURES_LOCALITY}.
093         */
094        public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate, final boolean ensure) {
095            this(delegate, ensure, new StandardProxyFactory());
096        }
097    
098        /**
099         * Constructs a wrapping ThreadLocalComponentAdapterFactory.
100         * @param delegate The delegated ComponentAdapterFactory.
101         * @param ensure {@link #ENSURE_THREAD_LOCALITY} or {@link #THREAD_ENSURES_LOCALITY}.
102         * @param factory The {@link ProxyFactory} to use.
103         */
104        protected ThreadLocalComponentAdapterFactory(
105                final ComponentAdapterFactory delegate, final boolean ensure, final ProxyFactory factory) {
106            super(delegate);
107            ensureThreadLocal = ensure;
108            proxyFactory = factory;
109        }
110    
111        public ComponentAdapter createComponentAdapter(
112                Object componentKey, Class componentImplementation, Parameter[] parameters)
113                throws PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
114            final ComponentAdapter componentAdapter;
115            if (ensureThreadLocal) {
116                componentAdapter = new ThreadLocalComponentAdapter(super.createComponentAdapter(
117                        componentKey, componentImplementation, parameters), proxyFactory);
118            } else {
119                componentAdapter = new CachingComponentAdapter(super.createComponentAdapter(
120                        componentKey, componentImplementation, parameters), new ThreadLocalReference());
121            }
122            return componentAdapter;
123        }
124    
125    }