Reputation: 45553
In a struts 2 and spring web based application, please consider below sample.
The BookManager
has an action which returns a Map
of books to client. It get the map from service layer which is injected
by Spring
public class BookManager extends ActionSupport {
//with setter and getter
private Map<String, BookVO> books;
@inject
BookService bookservice
@Action("book-form")
public String form(){
setBooks(bookservice.getAllBooks());
}
}
The service layer gets the book list from DB an returns a MAP.
@Named
public class BookService(){
private Map<String,BookVO> books;
public Map<String,BookVO> getAllBooks(){
books = new HashMap<String,BookVO>();
//fill books from DB
return books;
}
}
I have tested and found that the above implementation is not thread safe.
books
from BookService
and use it like method HashMap<String,BookVO>() books = new HashMap<String,BookVO>();
. Why this change make the code thread safe ?new
service object instead of using spring inject, I will face no issue. Why? If the service is not thread safe why making a new instance and calling it will be thread safe!Upvotes: 1
Views: 192
Reputation: 50261
I can make the code thread safe by removing private field books from BookService and use it like method HashMap() books = new HashMap();. Why this change make the code thread safe ?
Because method-level variables are thread safe, while class-level variables are not.
The struts action is thread safe, shouldn't this assure that the even non thread safe spring service runs in a thread safe manner ?
Nope. It depends.
If I use the non thread safe version of service in my action, by making a new service object instead of using spring inject, I will face no issue. Why? If the service is not thread safe why making a new instance and calling it will be thread safe!
If you instantiate it manually in the action, you are creating an instance of that object private to that action, thread-safe since the actions are ThreadLocal, and managed by you (that's means if your BookService
class has some @Inject
in it, the container won't resolve them).
If instead you have the DI managed by the container, the instance is not thread-safe; what you're using (@Inject
, @Named
) is more than "Spring", it's Java EE, is an implementaton of the JSR-330 (Dependency Injection) available only in CDI-enabled applications (JSR-299).
CDI beans are not thread safe. You should use EJB3's @Singleton
for this to be thread-safe, but you really don't need to retain that attribute at class-level, since it's used only to be returned, then left there to be overwritten the next time.
BTW consider using reference CDI (Weld in JBOSS) with the Struts2 CDI-plugin, it's worthy of a try.
Upvotes: 1