Alireza Fattahi February 2016

Thread safe struts web app with spring

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.

  1. I can make the code thread safe by removing private field books from BookService and use it like method HashMap<String,BookVO>() books = new HashMap<String,BookVO>();. Why this change make the code thread safe ?
  2. The struts action is thread safe, shouldn't this assure that the even non thread safe spring service runs in a thread safe manner.
  3. 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!

Answers


Andrea Ligios February 2016

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.

Post Status

Asked in February 2016
Viewed 1,532 times
Voted 5
Answered 1 times

Search




Leave an answer