I asked a similar question in Code Review forum but was suggested to ask that question here.
I am wondering about the synchronized keyword in the web-method below. Since setPerson is called from a thread pool (meaning that different threads can call it), I should syncronize it in someway. The thead pool is used by EclipseLink when my client is doing SOAP calls to the method. My question is if it is a good practice to make a web method synchronized or can I do the synchronization with em.lock(person, WRITE)?
@Override
public synchronized void setPerson(Person person) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersonLibPU");
EntityManager em = emf.createEntityManager();
if(!em.getTransaction().isActive()) {
em.getTransaction().begin();
}
try {
person.setPersonId(getLastInsertedId() + 1); // Get the last inserted ID and increment it by 1
em.merge(person);
em.getTransaction().commit();
emf.getCache().evict(Person.class);
} catch (Exception ex) {
if(em.getTransaction().isActive())
em.getTransaction().rollback();
} finally {
em.close();
}
}
EDIT
I added one more row in the code above where I set the primary key value of the person object. That is what the synchronization is made for, not for any shared java objects. I need to synchronize it so two threads cannot get the same primary key.
You’re possibly asking the wrong question. Synchronization won’t help you here, as the only part that has concurrency concerns is
getLastInsertedId(): you wouldn’t want two methods to get hold of the same value and try persisting an instance with that ID.Synchronizing
setPersonwould only solve the problem if it’s the only method that persists aPerson.If possible use the underlying data-store’s auto-incrementing functionality; failing that does your ORM solution perform context-wide ID allocation? The last resort would be to have a method of
getNextIdthat could be synchronized and returns an incremented value. This may end up with non-contiguous ID sequences in the database (getNextIdwon’t know if the persist operation succeeded), but this reduces the scope of the locking.As JB Nizet points out, the ID-allocation needs to be persisted and made available in some fashion that is available to all clients of this data store. If you had two instances of your application persisting
Personinstances, you would need to ensure that they share an ID-allocator.