KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > gems > 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;
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
30  * component at any time. This mode ({@link #ENSURE_THREAD_LOCALITY}) makes internal usage of
31  * a {@link ThreadLocalComponentAdapter}. If the application architecture ensures, that the
32  * thread that creates the component is always also the thread that is th only user, you can set
33  * the mode {@link #THREAD_ENSURES_LOCALITY}. In this mode the factory uses a simple
34  * {@link CachingComponentAdapter}that uses a {@link ThreadLocalReference}to cache the
35  * component.
36  * </p>
37  * <p>
38  * See the use cases for the subtile difference:
39  * </p>
40  * <p>
41  * <code>THREAD_ENSURES_LOCALITY</code> is applicable, if the pico container is requested for
42  * a thread local component from the working thread e.g. in a web application for a request. In
43  * this environment it is ensured, that the request is processed from the same thread and the
44  * thread local component is reused, if a previous request was handled in the same thread. Note
45  * that thi scenario fails badly, if the thread local component is created because of another
46  * cached component indirectly by a dependecy. In this case the cached component already have an
47  * instance of the thread local component, that may have been created in another thread, since
48  * only the component adapter for the thread local component can ensure a unique component for
49  * each thread.
50  * </p>
51  * <p>
52  * <code>ENSURES_THREAD_LOCALITY</code> solves this problem. In this case the returned
53  * component is just a proxy for the thread local component and this proxy ensures, that a new
54  * component is created for each thread. Even if another cached component has an indirect
55  * dependency on the thread local component, the proxy ensures unique instances. This is vital
56  * for a multithreaded application that uses EJBs.
57  * </p>
58  *
59  * @author J&ouml;rg Schaible
60  */

61 public class ThreadLocalComponentAdapterFactory extends DecoratingComponentAdapterFactory {
62
63     /**
64      * <code>ENSURE_THREAD_LOCALITY</code> is the constant for created
65      * {@link ComponentAdapter}instances, that ensure unique instances of the component by
66      * delivering a proxy for the component.
67      */

68     public static final boolean ENSURE_THREAD_LOCALITY = true;
69     /**
70      * <code>THREAD_ENSURES_LOCALITY</code> is the constant for created
71      * {@link ComponentAdapter}instances, that create for the current thread a new component.
72      */

73     public static final boolean THREAD_ENSURES_LOCALITY = false;
74
75     private final boolean ensureThreadLocal;
76     private ProxyFactory proxyFactory;
77
78     /**
79      * Constructs a wrapping ThreadLocalComponentAdapterFactory, that ensures the usage of the
80      * ThreadLocal. The Proxy instances are generated by the JDK.
81      *
82      * @param delegate The delegated {@link ComponentAdapterFactory}.
83      */

84     public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate) {
85         this(delegate, new StandardProxyFactory());
86     }
87
88     /**
89      * Constructs a wrapping ThreadLocalComponentAdapterFactory, that ensures the usage of the
90      * ThreadLocal.
91      *
92      * @param delegate The delegated ComponentAdapterFactory.
93      * @param proxyFactory The {@link ProxyFactory}to use.
94      */

95     public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate, final ProxyFactory proxyFactory) {
96         this(delegate, ENSURE_THREAD_LOCALITY, proxyFactory);
97     }
98
99     /**
100      * Constructs a wrapping ThreadLocalComponentAdapterFactory.
101      *
102      * @param delegate The delegated ComponentAdapterFactory.
103      * @param ensure {@link #ENSURE_THREAD_LOCALITY}or {@link #THREAD_ENSURES_LOCALITY}.
104      */

105     public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate, final boolean ensure) {
106         this(delegate, ensure, new StandardProxyFactory());
107     }
108
109     /**
110      * Constructs a wrapping ThreadLocalComponentAdapterFactory.
111      *
112      * @param delegate The delegated ComponentAdapterFactory.
113      * @param ensure {@link #ENSURE_THREAD_LOCALITY}or {@link #THREAD_ENSURES_LOCALITY}.
114      * @param factory The {@link ProxyFactory}to use.
115      */

116     protected ThreadLocalComponentAdapterFactory(
117             final ComponentAdapterFactory delegate, final boolean ensure, final ProxyFactory factory) {
118         super(delegate);
119         ensureThreadLocal = ensure;
120         proxyFactory = factory;
121     }
122
123     /**
124      * {@inheritDoc}
125      *
126      * @see org.picocontainer.defaults.DecoratingComponentAdapterFactory#createComponentAdapter(java.lang.Object,
127      * java.lang.Class, org.picocontainer.Parameter[])
128      */

129     public ComponentAdapter createComponentAdapter(Object JavaDoc componentKey, Class JavaDoc componentImplementation, Parameter[] parameters)
130             throws PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
131         final ComponentAdapter componentAdapter;
132         if (ensureThreadLocal) {
133             componentAdapter = new ThreadLocalComponentAdapter(super.createComponentAdapter(
134                     componentKey, componentImplementation, parameters), proxyFactory);
135         } else {
136             componentAdapter = new CachingComponentAdapter(super.createComponentAdapter(
137                     componentKey, componentImplementation, parameters), new ThreadLocalReference());
138         }
139         return componentAdapter;
140     }
141
142 }
143
Popular Tags