Search code examples
javaspringconcurrencymigrationejb

Java EJB migration to Spring


I'm migrating my EJBs to Spring beans and i have an issue with concurrency on some beans i have annotation @Lock(LockType.READ) or @Lock(LockType.WRITE) on methods and class when concurrency was managed by container, but in Spring concurrency is managed by bean, what equivalent i could do in Spring regarding for locking two simultaneous read/write actions ?

For example on this class :

@Singleton
@Lock(READ)
public class SharedSingletonBean {
  private String data;
  private String status;

  public String getData() {
    return data;
  }

  public String getStatus() {
    return status;
  }

  @Lock(WRITE)
  public void setStatus(String newStatus) {
    status = newStatus;
  }
}

Solution

  • For @Lock(READ), you have nothing to do as the READ value means that the method does only reading and that it can be concurrently accessed, or shared, with several clients.

    It is the case for example for these two methods :

    public String getData() {
        return data;
    }
    
    public String getStatus() {
        return status;
    }
    

    For @Lock(WRITE) as this one :

    @Lock(WRITE)
    public void setStatus(String newStatus) {
        status = newStatus;
    }
    

    it means that the method does writing.
    So actually, the WRITE value makes the container to prevent any client to invoke the method if another client executing it.
    To do the same thing with Spring, using the volatile modifier for the String field could be enough as you do only an assignment in the method.
    You would not have concurrency or no updated value issue as an assignment for a volatile variable is always atomic and updated for other threads and with this solution, as in your actual case, the last one client is always right.
    Also, as a side note, I am not very convinced of the correct use of @Lock READ and WRITE here.

    If you have more statements and that this could not be invoked atomically and in a transparent way for other clients, you could use a synchronized statement on the current object :

     public void setStatus(String newStatus) {
        synchronize(this){
           myStatement();
           myOtherStatement();
           status = newStatus;
        }
      }