Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ThreadLocal in Tomcat servlets

I'm having a problem where Exceptions are popping up in my production system but I really don't have good information about who is causing them. The person's username is stored as a variable in their tomcat session, which I have access to in my doPost or doGet method obviously, but unless I pass that information down as a parameter to each of my business objects, I don't have access to the session. For obvious reasons, I'd like to tack the username into the logging message so I have an idea of what is going on.

So my solution is to do something like this

public class ExceptionUtil {
    private ExceptionUtil() { } // no instantiation
    private static final ThreadLocal<String> local = new ThreadLocal<String>();
    public static void set(String user) { local.set(user); }
    public static String get() { return local.get(); }
}

Then in my posts/gets, I can do this

String username = request.getSession().getAttribute("username");
ExceptionUtil.set(username);

Then in my exceptions, I might do this (contrived, bad practice example)

catch(SQLException e) {
    logger.error(ExceptionUtil.get() + " did something dumb in sql", e);
    throw e;
}

The only problem I'm concerned about is how Tomcat will manage my threads. What if they keep the threads? Will they persist? Will the ThreadLocal values also persist? If I was storing the entire Session in the ThreadLocal instead of just a String, that would be a serious memory leak potential. It also means if someone forgot to re-set (or forgets to clear when done) the username/session on a thread that persisted for multiple requests, there might be stale data in there.

Call my cynical, but I don't want to have to rely on programmers (even, especially myself!) not forgetting to do things for a program's correctness. If I can idiot-proof my code, I'd like to. And that means getting a better understanding of how Tomcat will use the threads.

So, the question in a single-sentence form:

If I use ThreadLocal in a webapp running on Tomcat (7.0.27), do I run the risk of a Thread being used for multiple requests, and with it data from a previous request being persisted?

I should note that even though they don't answer the exact question of "Tomcat/ThreadLocal shenanigans", I am open to alternative solutions that allow me to elegantly access session variables for logging purposes. I am also open to commentary about potential pitfalls of my solution. I have a business problem to solve, and I'm not married to any one solution. I just want to know who keeps causing the exceptions on my prod system :)

like image 254
corsiKa Avatar asked Aug 10 '12 23:08

corsiKa


1 Answers

Yes, tomcat uses the ThreadPool concept , that means the threads are being reused and hence as you suggested "Your Thread Local retains the values" ,

alternatives what i would suggest could be

  1. clean up threads after you are done, somewhere in the view controller

  2. Write a Request Filter and on start of filter Clean up everything and push new values, and assign this to every url pattern on ur server.

for the approach you are following instead of saving certain values in classes, Store the request in Thread Local and then use the request to pull values out of session using a homemade util class, that takes request and then returns you desired value, that way you save yourself of saving session in Thread and get the value, but please ensure that u add fresh every time and clean up request after you are done(use 2nd option for that ) .

like image 50
Akash Yadav Avatar answered Oct 17 '22 12:10

Akash Yadav