Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

best practice for thread safe session bean in spring?

I'm wondering what is the best practice for making a session bean thread safe.

Let's assume I have this session bean and its service:

@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
class Cart {

    private HashSet<Item> items = new HashSet<Item>();

    private int counter = 0;

    public HashSet<Item> getItems() {
        return items;
    }

    public int getCounter() {
        return counter;
    }

}

@Service
class CartService {

    @Autowired
    private Cart cart;

    public void addItem(Item item) throws FullException {
        if (cart.getCounter() > 1234) {
            throw new FullException();

        }
        cart.getItems().add(item);
    }

}

The code above is not thread safe and will cause issues when multiple threads (of the same session, eg. by asynchronous Ajax-requests) perform a CartService.addItem(Item).

I think I'm not the first with this problem, but my researches didn't bring me to a best practice.

The worst thing I could do would synchronize addItem() as CartService is shared by multiple sessions. Synchronizing on cart in CartService.addItem() seems to me similarly bad, as Cart is a proxied bean. Which I understand as all sessions would still synchronize on the same object.

One acceptable solution seems to be a synchronized block on Cart.getItems() in CartService.addItem():

@Service
class CartService {

    @Autowired
    private Cart cart;

    public void addItem(Item item) {
        synchronized(cart.getItems()) {
            if (cart.getCounter() > 1234) {
                throw new FullException();

            }
            cart.getItems().add(item);
        }
    }

}

Is there any best practice? Maybe spring has something to offer for this problem?

like image 306
Markus Malkusch Avatar asked Oct 18 '13 06:10

Markus Malkusch


1 Answers

After digging a bit through the Spring API I found RequestMappingHandlerAdapter.setSynchronizeOnSession(boolean) which seems to synchronize every controller on a session mutex. This might be overkill. But it makes at least controllers thread safe on the session without blocking other users, plus I don't have to worry about synchronization in my controller. But this is still not acceptable for a highly responsive Ajax-GUI.

I get the feeling that there is no general answer to this question and it totally depends on the GUI. If I have plain simple HTML pages where sequential requests are expected RequestMappingHandlerAdapter.setSynchronizeOnSession(true) seems to be perfect, as I don't have to think about synchronization in my Controllers.

If the GUI becomes more fancy with loads of parallel AJAX-requests I have to take care about synchronization by choosing an eligible mutex.

like image 72
Markus Malkusch Avatar answered Oct 10 '22 12:10

Markus Malkusch