Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring: Is this pattern thread-safe? [closed]

I've been learning how to use the Spring framework for hibernate transaction management, and so far it has been a great help for that purpose. The problem is that recently, I realized that I hadn't been giving much thought to how the pattern that I chose handles concurrency, specially in the case of a web application.

Below is the code that exemplifies the pattern that I'm using, which is a combination of some examples I found, and a custom servlet implementation. I have a few doubts about how this pattern works and whether it is thread-safe since I customized it a bit. Some of my concerns are:

  • Even though servlets are technically not singletons, I'm under the impression that most of the time there will be only a single instance for each servlet class.
  • If I understand correctly, each auto-wired property will be a singleton, so if the above its true, then there'll be a single servlet instance with a single service instance, which in turn has a single DAO instance, which has its own SessionFactory instance.
  • If the above is correct then I can imagine that every request on the servlet will be using the same objects and I wonder whether this is a good thing. After giving it some thought I can't tell whether it would be better for thread-safety to have singletons or to have new instances created for each http request.
  • Usually these spring patterns have a @Controller class which I skipped in favor of our custom servlet and I'm wondering whether that could break the concurrency of the pattern somehow.

Thanks

public interface UserDAO
{
    public void save(User user);
}

@Repository
public class HibernateUserDAO implements UserDAO
{
    @Autowired(required=true)
    protected SessionFactory sessionFactory;

    public void save(User user)
    {
        this.sessionFactory.getCurrentSession().save(user);
    }
}

public interface UserService
{
    public void saveUser(User user);
}

@Service
public class DefaultUserService implements UserService
{
    @Autowired(required=true)
    private UserDAO userDAO;

    @Transactional
    public void saveUser(User user)
    {
        this.userDAO.save(user);
    }
}

public class UserServlet extends CustomServlet
{   
    @Autowired(required=true)
    private UserService userService;

    public void init() throws ServletException
    {
        super.init();
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        //would call the appropriate method depending on parameters, etc.
        //simplified here for demonstration purposes
        this.userService.saveUser(user);
    }
}
like image 850
JayPea Avatar asked Dec 07 '11 18:12

JayPea


People also ask

Does Spring provide thread safe?

Are Spring Beans Thread Safe? No. Spring has different bean scopes (e.g. Prototype, Singleton, etc.) but all these scopes enforce is when the bean is created.

Are Spring singletons thread safe?

Singleton beans does not provide thread safety and now you know that instance variables usage may lead to unexpected result, you have 2 options to solve the same : Don't use instance variables in multithreaded environment.

How do I know if a method is thread safe?

To test if the combination of two methods, a and b, is thread-safe, call them from two different threads. Put the complete test in a while loop iterating over all thread interleavings with the help from the class AllInterleavings from vmlens. Test if the result is either an after b or b after a.

Is Spring dependency injection thread safe?

You should not worry about thread safety of the dependency injection, Spring does (most likely, spring is going to use just one thread to inject all the dependencies).


2 Answers

If you have a suitable strategy set up in the Hibernate configuration, then sessionFactory.getCurrentSession() will return a scoped session, not a global one. Session factories are intended to be singletons, that's quite correct; getCurrentSession() is the usual method to bridge to the current context scope.

"suitable strategy" varies, but if you're using the spring transaction management wrapped around your DAO, then a session will have a lifetime of a DAO method call, and Spring will orchestrate calling commit/rollback as appropriate on exit.

like image 175
araqnid Avatar answered Sep 22 '22 18:09

araqnid


Spring beans are by default in application scope, i.e. there will only be a single instance in your application. You could change this with @Scope, but the typical pattern is to keep them in application scope and make them thread safe by not storing any state in the beans, i.e. all fields of application scoped beans should not be changed, or refer to objects that are changed, after the application has started.

like image 43
meriton Avatar answered Sep 22 '22 18:09

meriton