2 * Copyright 2005-2010 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.support;
18 import java.lang.reflect.InvocationHandler;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.Proxy;
24 * Thread-specific proxy is used to create implementations of interfaces that
25 * delegate to a thread-specific implementation of the service.
27 * It is used for instance to pass a transaction scoped entity manager around.
31 * @author Erik Brakkee
34 public class ThreadSpecificProxyFactory<T> {
35 private class ThreadSpecificInvocationHandler implements InvocationHandler {
38 public Object invoke(Object aProxy, Method aMethod, Object[] aArgs)
41 return aMethod.invoke(svc.get(), aArgs);
42 } catch (InvocationTargetException e) {
48 private ThreadLocal<T> svc = new ThreadLocal<T>();
52 * Constructs the factory.
53 * @param aClass Interface class of the service to proxy.
55 public ThreadSpecificProxyFactory(Class<T> aClass) {
56 if ( !aClass.isInterface() ) {
57 throw new IllegalArgumentException("Class " + aClass.getName() + " is not an interface");
63 * Sets the thread-specific service.
64 * @param aService Service, use null value to reset.
66 public void set(T aService) {
71 * Gets the proxy that delegates to the thread-specific instance set by
72 * {@link #set(Object)}
76 InvocationHandler handler = new ThreadSpecificInvocationHandler();
77 Class proxyClass = Proxy.getProxyClass(clazz.getClassLoader(),
78 new Class[] { clazz });
81 proxy = (T) proxyClass.getConstructor(
82 new Class[] { InvocationHandler.class }).newInstance(
83 new Object[] { handler });
85 } catch (Exception e) {
86 throw new RuntimeException("Could not create proxy for " + clazz.getName(), e);