11

In my Spring JDBC project I have a class called DBStuff which i use to connect to DB and make simple DB operations. It's a web project and there are users, so naturally i use session mechanism. When i need to retrieve request data in DBStuff class, I use this line of code below:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

But, there is no explanation that if the RequestContextHolder is thread-safe or not. Even the spring's official forum doesn't have an answer for that. Because of using servlet, I need to provide a thread-safe nature for the users.

By definition RequestContextHolder is defined as "Holder class to expose the web request in the form of a thread-bound RequestAttributes object." But I am not sure if "thread-bound" stands for thread-safe.

kiz
  • 47
  • 1
  • 8
cihan adil seven
  • 541
  • 1
  • 4
  • 20
  • 2
    It is thread safe, however why are you binding your data access layer to your web layer... That is a code smell and imho a signal you are doing things wrong. – M. Deinum Apr 29 '16 at 09:22
  • My DataAccess layer and Web layer are seperate but every user request keeps its login data which plays a huge role in DB operations. Should i change the DataAccess class to prototype? But if i make it so, doesn't it cost too much memory and performance for my system? – cihan adil seven Apr 29 '16 at 09:29
  • 2
    No they aren't separated... You data layer depends on the web layer. You cannot take your dbaccess class and put it in a non-web enabled server as it has a tight coupling to `javax.servlet` and web related packages of Spring. Hence a coupling between web and data access. If you need it either pass that stuff around in a method argument or store it in a `ThreadLocal` but don't leak web details in anything other then web bound classes. – M. Deinum Apr 29 '16 at 09:32

1 Answers1

22

"thread-bound" means that every thread has own copy of the data, so it is thread-safe.

It uses ThreadLocal for that

private static final ThreadLocal<RequestAttributes> requestAttributesHolder = 
      new NamedThreadLocal<RequestAttributes>("Request attributes");

public static RequestAttributes getRequestAttributes() {
    RequestAttributes attributes = requestAttributesHolder.get();
    if (attributes == null) {
        attributes = inheritableRequestAttributesHolder.get();
    }
    return attributes;
}

requestAttributesHolder.get() returns RequestAttributes for the current thread, it is a thread that process an HTTP request. Every request has an own thread.

Method get() of ThreadLocal uses a map to bound the data to the Thread.currentThread()

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null)
            return (T)e.value;
    }
    return setInitialValue();
}

When and how should I use a ThreadLocal variable?

v.ladynev
  • 19,275
  • 8
  • 46
  • 67
  • But the class DBStuff is singleton, doesn't that make the RequestContextHolder bound to this class's thread? – cihan adil seven Apr 29 '16 at 08:33
  • 1
    it is true if i have the request and go on with it in the class. But the the problem is i try to get the request inside this singleton `DBStuff` class. If `RequestContextHolder` is bound to the current thread, then how can it handle two simultaneous requests? – cihan adil seven Apr 29 '16 at 08:48