|
||||||||
|
|
![]() |
|
|
|
|
||
|
Leveraging ThreadLocal Variables in Java Hey, David: Is there any way to pick up the user associated with a servlet request without passing the user as a parameter? If this were RPG, I would add a data area containing the user's name to QTEMP or use the *LDA. This seems like a basic concept, but so far I haven't seen anything like it in Java. --Aaron Java doesn't have a local data area, but it does have something similar with thread local variables. The class ThreadLocal allows you to associate a variable value with a thread. This is useful in a servlet because requests, which are associated with a user, are assigned to threads by the servlet container. If you place the user associated with a servlet request into a ThreadLocal variable, you can pick up and use that user downstream, without passing the user along as a parameter. The easiest way to show how this works is with an example. The following class allows you to associate a string containing a user with a thread:
package demo;
class ThreadLocalUser {
private static ThreadLocal name = new ThreadLocal();
private ThreadLocalUser() {
}
public static String getName() {
return (String) name.get();
}
public static void setName(String name) {
ThreadLocalUser.name.set(name);
}
}
Notice that the methods in this class are all static, which means that they can be called anywhere in your code without an instance variable. All you need to do is make a call like this:
ThreadLocalUser.setName("DAVID");
You can retrieve the user that is now associated with the thread using a call like this. It will set the name variable contained in the ThreadLocalUser class to the value "DAVID". Once the ThreadLocalUser name is set, it can be picked up by calling "get name," like this: String user = ThreadLocalUser.getName(); To prove that this works, I created a class that will start five overlapping threads and display the user associated with the thread. I gave each thread a name that corresponded with the ThreadLocalUser, to make it easier to track the results. I ran this test with jUnit. If you don't use jUnit, you could move the code contained in testSetname to the main method of your own Java class. Here is the test code:
package demo;
import demo.ThreadLocalUser;
import junit.framework.TestCase;
public class ThreadLocalUserTest extends TestCase {
public ThreadLocalUserTest(String arg0) {
super(arg0);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(ThreadLocalUserTest.class);
}
public void testGetName() {
}
public void testSetName() {
new Thread(new Runner(), "David").start();
new Thread(new Runner(), "Aaron").start();
new Thread(new Runner(), "Sam").start();
new Thread(new Runner(), "Fred").start();
new Thread(new Runner(), "Rufus").start();
try {
Thread.sleep((int) (1000));
}
catch (InterruptedException ignored) {
}
}
class Runner
implements Runnable {
public void run() {
Thread thread = Thread.currentThread();
ThreadLocalUser.setName(thread.getName());
for (int i = 0; i < 15; ++i) {
System.out.println("Thread name: " + thread.getName()
+ " user: " + ThreadLocalUser.getName());
assertEquals(thread.getName(),
ThreadLocalUser.getName());
try {
Thread.sleep(10);
}
catch (InterruptedException ignored) {
}
}
ThreadLocalUser.setName(null);
assertEquals(ThreadLocalUser.getName(), null);
}
}
}
The output of this class looks something like this: Thread name: David user: David Thread name: Aaron user: Aaron Thread name: Aaron user: Aaron Thread name: David user: David Thread name: Sam user: Sam Thread name: Fred user: Fred Thread name: Rufus user: Rufus Thread name: Rufus user: Rufus… The most comprehensive way to take advantage of this in a servlet environment is to write a servlet filter. A servlet filter implements the javax.servlet.Filter interface and is called whenever a request is made. This allows you to intercept requests and to set your thread local user without altering existing code. Filters are relatively new to servlets, so you should check to see if your servlet container supports filters before you invest too much time in building a filter. With filters, or in your servlet, you can use the getRemoteUser method that is provided by HttpServletRequest to retrieve the user associated with a request. So the first line of your servlet or request might look something like this: ThreadLocalUser.setName(request.getRemoteUser()); I hope that gives you enough to get started using thread local variables, which are the *LDA of the Java world. --David
|
Editors
Contact the Editors |
| Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved. |