KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > gems > adapters > ThreadLocalComponentAdapterFactory


1 /*****************************************************************************
2  * Copyright (c) PicoContainer Organization. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  * *
8  * Original code by Joerg Schaible *
9  *****************************************************************************/

10
11 package org.picocontainer.gems.adapters;
12
13 import com.thoughtworks.proxy.ProxyFactory;
14 import com.thoughtworks.proxy.factory.StandardProxyFactory;
15
16 import org.picocontainer.ComponentAdapter;
17 import org.picocontainer.Parameter;
18 import org.picocontainer.PicoIntrospectionException;
19 import org.picocontainer.defaults.AssignabilityRegistrationException;
20 import org.picocontainer.defaults.CachingComponentAdapter;
21 import org.picocontainer.defaults.ComponentAdapterFactory;
22 import org.picocontainer.defaults.DecoratingComponentAdapterFactory;
23 import org.picocontainer.defaults.NotConcreteRegistrationException;
24
25
26 /**
27  * A {@link ComponentAdapterFactory} for components kept in {@link ThreadLocal} instances.
28  * <p>
29  * This factory has two operating modes. By default it ensures, that every thread uses its own component at any time.
30  * This mode ({@link #ENSURE_THREAD_LOCALITY}) makes internal usage of a {@link ThreadLocalComponentAdapter}. If the
31  * application architecture ensures, that the thread that creates the component is always also the thread that is th
32  * only user, you can set the mode {@link #THREAD_ENSURES_LOCALITY}. In this mode the factory uses a simple
33  * {@link CachingComponentAdapter} that uses a {@link ThreadLocalReference} to cache the component.
34  * </p>
35  * <p>
36  * See the use cases for the subtile difference:
37  * </p>
38  * <p>
39  * <code>THREAD_ENSURES_LOCALITY</code> is applicable, if the pico container is requested for a thread local component
40  * from the working thread e.g. in a web application for a request. In this environment it is ensured, that the request
41  * is processed from the same thread and the thread local component is reused, if a previous request was handled in the
42  * same thread. Note that thi scenario fails badly, if the thread local component is created because of another cached
43  * component indirectly by a dependecy. In this case the cached component already have an instance of the thread local
44  * component, that may have been created in another thread, since only the component adapter for the thread local
45  * component can ensure a unique component for each thread.
46  * </p>
47  * <p>
48  * <code>ENSURES_THREAD_LOCALITY</code> solves this problem. In this case the returned component is just a proxy for
49  * the thread local component and this proxy ensures, that a new component is created for each thread. Even if another
50  * cached component has an indirect dependency on the thread local component, the proxy ensures unique instances. This
51  * is vital for a multithreaded application that uses EJBs.
52  * </p>
53  * @author J&ouml;rg Schaible
54  */

55 public class ThreadLocalComponentAdapterFactory extends DecoratingComponentAdapterFactory {
56
57     /**
58      * <code>ENSURE_THREAD_LOCALITY</code> is the constant for created {@link ComponentAdapter} instances, that ensure
59      * unique instances of the component by delivering a proxy for the component.
60      */

61     public static final boolean ENSURE_THREAD_LOCALITY = true;
62     /**
63      * <code>THREAD_ENSURES_LOCALITY</code> is the constant for created {@link ComponentAdapter} instances, that
64      * create for the current thread a new component.
65      */

66     public static final boolean THREAD_ENSURES_LOCALITY = false;
67
68     private final boolean ensureThreadLocal;
69     private ProxyFactory proxyFactory;
70
71     /**
72      * Constructs a wrapping ThreadLocalComponentAdapterFactory, that ensures the usage of the ThreadLocal. The Proxy
73      * instances are generated by the JDK.
74      * @param delegate The delegated {@link ComponentAdapterFactory}.
75      */

76     public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate) {
77         this(delegate, new StandardProxyFactory());
78     }
79
80     /**
81      * Constructs a wrapping ThreadLocalComponentAdapterFactory, that ensures the usage of the ThreadLocal.
82      * @param delegate The delegated ComponentAdapterFactory.
83      * @param proxyFactory The {@link ProxyFactory} to use.
84      */

85     public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate, final ProxyFactory proxyFactory) {
86         this(delegate, ENSURE_THREAD_LOCALITY, proxyFactory);
87     }
88
89     /**
90      * Constructs a wrapping ThreadLocalComponentAdapterFactory.
91      * @param delegate The delegated ComponentAdapterFactory.
92      * @param ensure {@link #ENSURE_THREAD_LOCALITY} or {@link #THREAD_ENSURES_LOCALITY}.
93      */

94     public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate, final boolean ensure) {
95         this(delegate, ensure, new StandardProxyFactory());
96     }
97
98     /**
99      * 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 JavaDoc componentKey, Class JavaDoc 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 }
126
Popular Tags