Reputation: 111255
I implemented Dynamic DataSource Routing for Spring+Hibernate according to this article. I have several databases with same structure and I need to select which db will run each specific query.
Everything works fine on localhost, but I am worrying about how this will hold up in real web site environment. They are using some static context holder to determine which datasource to use:
public class CustomerContextHolder {
private static final ThreadLocal<CustomerType> contextHolder =
new ThreadLocal<CustomerType>();
public static void setCustomerType(CustomerType customerType) {
Assert.notNull(customerType, "customerType cannot be null");
contextHolder.set(customerType);
}
public static CustomerType getCustomerType() {
return (CustomerType) contextHolder.get();
}
public static void clearCustomerType() {
contextHolder.remove();
}
}
It is wrapped inside some ThreadLocal container, but what exactly does that mean? What will happen when two web requests call this piece of code in parallel:
CustomerContextHolder.setCustomerType(CustomerType.GOLD);
//<another user will switch customer type here to CustomerType.SILVER in another request>
List<Item> goldItems = catalog.getItems();
Is every web request wrapped into its own thread in Spring MVC? Will CustomerContextHolder.setCustomerType()
changes be visible to other web users? My controllers have synchronizeOnSession=true
.
How to make sure that nobody else will switch datasource until I run required query for current user?
Thanks.
Upvotes: 4
Views: 4439
Reputation: 570285
Is every web request wrapped into its own thread in Spring MVC?
Yes, but this has nothing to do with Spring MVC, the container is doing that (the container has a thread pool and picks one of the them to handle each request).
Will CustomerContextHolder.setCustomerType() changes be visible to other web users?
No. A ThreadLocal
is by definition local to a thread. From the javadoc:
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its
get
orset
method) has its own, independently initialized copy of the variable.ThreadLocal
instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
What you set
in a ThreadLocal
is not visible to other threads. You should be fine
Upvotes: 6