The situation is like this. Two clients are reading the same data in a short span of interval. The first client made some changes and doing an update using EnityBean. Now, the second client is also updating after modifying some changes on the data he/she already read. In such situation, the update should not happen and the client should be informed that somebody already changed the data. This is the requirement from my side. Please help me how to design an EJB which takes care of this problem. Expecting your kind help.
There is no such callback mechanism that informs you about the change in the underlying data of your Entity bean. But why do you need to know that? I mean container on its own calls ejbStore and ejbLoad between remote method calls on your entity bean in order to synchronize the bean state with the underlying store. Then why do you need that? Please make your question very clear.
This problem is addressed by the "isolation level" setting in your database.
For example, Oracle allows "Serializable Transactionality", which is isolation-level-3, and when you set this level, Oracle will throw ORA-08177, when the case you describe happens. (Two clients reading data simultaneously, and one first committing, and the second committing the stale data)
Look out for your EJB Descriptor Property that configures this transaction setting. For weblogic, it's "transaction-isolation" tag in cmp-rdbms-jar.xml
Hope it helps.
Isolation level set to serializable will make sure that resultset does not have dirty reads or unrepeatable read problems. But I dont think that gives notifications of whether the underlying data has changed by some other transaction to the current transaction. And that is what this gentleman is seeking for.
Such scenerio will not happen,second client will get
blocked or refused depend on isolation level.
I ran into the same issue once and it is not addressed by any of the above comments...
The issue is keeping track of changes made between a "reading" and a "modification" which are two separate processes separated by some amount of time.
This problem is solved with DESIGN...
If keeping track of these changes is a business logic requirement, then add a "lastUpdated" field.
1) Process A reads the entity data, lastUpdate is July 4th
2) Process B makes some change to the entity, thus lastUpdate is set to the present timestamp, say July 5th.
3) Process A starts to modify the entity, but first checks the lastUpdate. Since process A initially read a value of July 4, and lastUpdate is now July 5th, process A knows the data was modified since the last reading.
The orignal question says "in a short span of interval",
this is exactly what database transaction/isolation design for,there is no need to duplicate logic and waste efforts in the app layer.
This depends on the underlying database
eg in Oracle use
select col1, col2 ...etc
for update nowait
This will prevent anyone else from reading the same record with the update clause
You can still do a "select" and retrieve the record but your design should have a "find & edit method".
The find method will use "select" and the Edit method will use "Select with update". You should allow for any change to be made after a successful read in "Edit Mode"
Hope this helps
Thanks for your reply. I found your reply is very much relevant. I think of implementing your solution in the following fashion.
A field called lastModified will be added to the EntityBean (This won't be mapped to the database). While reading the EntityBean data, the server time also will be read and will be sent to the client as the part of response. The client has to send that time stamp, while updating that data by using entitybean. After, update the present server time will be taken as the value for lastModified field. If any other client come up with the request for update then, this field value will be cross checked with the read time stamp of the client request and the decision will be taken accordingly.
Do you find it my way of checking time stamp correct? Please give your valuable comments.
You must store the value in the database since that is where data is persisted.
The problem with what you wrote is that lastModifed is not saved into the database, thus when that entity gets recalled you have no way of knowing the lastModified value.
To clarify using my previous example: If the lastModified value is not saved in step (2) then Process A will not be able to tell that an update took place in step (3) since you did not save the timestamp.
To summarize, you will need to add a column to your table...
Hope this helps,
The idea used by the architect of my previous employer is based on optimistic locking:
- each entity bean has a extra (persistent) field for locking of type eg. long. Let's call the field counter.
- when a client does a read operation, along with all the data you also return the value of the counter to your client
- before an update you do the "before update check": does the counter field of the client equal the counter field in the bean?
- If both counters are still equal, then no other clients have done an update. Execute the update and don't forget to increment the counter with 1. This piece of code is a
- If the counters are not equal, some other client did an update. The update should not be allowed and the bean could eg. throw an OptimisticLockingException.
- counter is 1
- client A reads bean. Counter in entity bean is 1.
- client B reads bean. Counter in entity bean is 1.
- client B does update. Counter of client B (1) and bean (1) are equal. Execute update and increment counter. Counter in bean now equals 2.
- Client A attempts update. Counter of client A (1) and entity bean (now 2) are not equal. Sorry client A, but I can't execute update. PLease re-read the entity bean and try to do your update again.
This technique, know as optimistic locking, should not be used when racing conditions between various client occur often. But for most applications this will not be the case
and thus it is a very elegant technique.
If you have legacy applications using your database, make your counter field persistent and move the "before update check" to your database.
Hey guys ...have any of u guys looked into the pattern repository in this site(Long-Lived Optimistic PseudoTransactions - Version Numbering)
...it talks about a pattern for version coltrol...and thatz what we are implementing in our project..
kvenkataraman at symphoni dot com
412 414 5385(mobile)
412 446 2219(Work)
1 800 439 7757 (# 2219) (Work)
412 343 6549(Res)