We are developing an application that allows more than one client update an entity with the same PK at the same time.
Client A - gets data using an sql call
Client B - gets same data using an sql call.
Client B - updates data with new value.
(at this stage client A does not know the data has changed)
Client A - updates data with new value but is working with a view of data that was relevent before Client B updated the data.
1) How can we use EJBs in this context to ensure that if Client B updates the data Client A can be made aware of updates.
2) One suggestion is to use optomistic updates with a timestamp to check if the data being used by a client is dirty. In this scenario we have a timestamp field as a cmp field in the entity and before updating the bean check if the timestamp is different to that passed in by the client. Can you tell me if I am approaching this the correct way.
I'm not sure what you are getting at here, mainly because you say you are designing a system that will allow concurrent updates, but have a problem knowing how to keep things in sync.
Anyway, here goes.
Firstly, what EJB server are you using. If it's WL5.1.0 then forget optomistic concurrency, you can't do it. WebLogic will use pessimistic concurrency. If you only have one server, you only have one instance of the Entity bean for each primary key. If you have a cluster, then there will be only one entity bean for that primary key in the cluster and all requests for that key will be routed to the relevant server. For now, I'll assume you don't have multiple servers looking at the same database but not in a cluster, it's too depressing! :-)
So, in a pessimistic system you have no problem, provided you are only talking about a single method call to the bean.
Since the system is pessimistically concurrent only one client will be allowed to modify the contents at a time, hence, no problem. Note this is regardless of transactional settings.
If the system is optimistically concurrent, or, if you need to update multiple entities in one hit then you need to look at transaction isolation levels. The problem you describe is the classic dirty read problem. This means you need to use a READ_COMITTED transactional isolation level on your bean. That will solve the problem.
There are many other options, but they really depend on the exact nature of your problem. Give some more detail and we can go from there. Basically, you control concurrency in entity beans using transactional settings. Tell me more and I'll see what makes sense.
I am working on weblogic 6.0, single server, one database. I probably misstated the problem. The problem is that I dont want to allow a client to update data if the data has been altered since they last retrieved it by another client.
OK, in that case, you need to set the isolation level to TX_READ_COMITTED.
That will do it. The server will stop a client making a change while some other client is in the middle of a transaction.
You will also need to set the transaction requirements of the methods correctly. If you are talking a single method, then set that single method to be something like TX_SUPPORTED.
If you need to update several entities the provide a session bean wrapper, set it's method to TX_SUPPORTED and set the entity beans to TX_REQUIRED. That way, if someone does NOT pass in a transaction context the bean will kick them out immediately.
That should take care of it.
On the other hand, unless they changed it, (I haven't read enough on it to know for sure) then WebLogic is pessimistically concurrent and with your setup you will be OK in any case.
you need to set the isolation level to repeatable read, read commited is not enough for you.
It looks like your question was not answered here. May be, I am wrong...I thought you were talking about a scenario when two clients get their data at different points in time, but one client updates the data and leaves the other client with the old data.
No Entity Bean or Stateless Session Bean will solve your problem, since a method in these Beans run in TXN scope. Say if you have a getData() method in an Entity Bean. At the end of getData(), the TXN is complete. If you try to update this Bean with setData(), passing in some old data values, there is nothing that you can do that will prevent such an update.
It looks like what you need is a Stateful Session Bean. With Stateful Session Beans, you can hold on to a TXN in more than one method. This is true even when the Activation/Passivation occurs. You will be using JTA's UserTransaction inside your Stateful bean, with BMT (bean managed txn) for the Entity beans...
Let me know what you guys think....Thanks,
Say if you have a getData() method in an Entity Bean. At >the end of getData(), the TXN is complete.
Not true, depend on transaction setting in the DD.
>If you try to update this Bean with setData(), passing in >some old data values, there is nothing that you can do >that will prevent such an update.
Not true, you can either set the db isolation level or
use optimistic lock.
>This is true even when the Activation/Passivation occurs.
Not true, such thing will never happen according to spec.
> with BMT (bean managed txn) for the Entity beans...
..This is also prohibited by EJB 1.1.
I agree with you on the third one...You will be using JTA's UserTransaction inside your Stateful bean, with BMT (bean managed txn) for the Entity beans...
Entity Beans here is a typo...As you see, I was referring to using UserTransaction inside a Stateful bean, with the Stateful bean's transactional attribute set to "TX_BEAN_MANAGED"...
With respect to your other comments, I am not sure....I will read more on this topic...
I agree, if you need to ensure that client A reads the same data the second time it tries to read it, then the isolation level you need is REPEATABLE_READ.
If all you are trying to do is avoid the situation where client A updates the data whilst B is doing so, then READ_COMMITTED is enough.
Since the applications read their data and update them at different times, we have to keep the Txn alive across multiple methods. This means that we have to take control of the Txn using JTA.
1. We can do this in the Entity EJB. (REPEATABLE_READ, TXN_BEAN_MANAGED). When the user calls getData() in the Entity EJB, we can begin a Txn and when they call setData() LATER, we can commit() the Txn.
Let us say the first app called getData() and we created a new Txn. Now, let us say the second app calls getData()? Wouldn't this be a problem, since we have already created a Txn? Is this the reason they say that Entity & Stateless have Txn scope only in a single method (begin & commit within a method) as opposed to multiple method calls?
2. The next choice then is to use 2 Stateful Session beans, in combination with an Entity Bean.
Stateful Session Beans (REPEATABLE_READ, TXN_BEAN_MANAGED)
Entity Bean (REPEATABLE_READ, TXN_REQUIRED)
Client 1 uses Stateful bean 1 & Client 2 uses Stateful Bean 2. When they call the getData() in the Stateful Bean, we begin a new Txn. This getData() will in turn call the Entity bean's getData(), which will result in a JOIN, as described in page 280 of Mastering EJB by Ed Roman. (Available in this site). So, at this point, the Entity EJB will be associated with the Txn in the corresponding Stateful bean. Whichever client calls the setData() first will succeed. The other client calling setData() later will fail...
Will this work? The problem we are trying to solve is not simple, since the two apps read the data at around the same time, but update them at two different times?
Thanks for all your insights...
"Entity EJB. (REPEATABLE_READ, TXN_BEAN_MANAGED)."
Nope, TXN_BEAN_MANAGED not permitted in entity beans. ;-)
In response to the two transaction scenario....
StatefulBean1 creates transaction and passes to entity bean. Entity bean joins transaction.
StatefulBean2 creates transaction and passes to entity bean......
Now it depends on your server implementation. If it's pessimistically concurrent then it will simply queue up and wait for the first one to exit, and will then run through.
If it's optomistically concurrent then it "should" still wait, due to the isolation level of the transactions, but in some cases the server delegates the transaction to the database, in which case it can be database dependant. (Look at how Sybase and Oracle behave differently with TX_SERIALIZABLE for more info on this.)
In either case, if what you want is this...
CLIENT A - READ DATA
CLIENT B - READ DATA CLIENT A - MODIFY LOCAL DATA
CLIENT A - WRITE DATA CLIENT B - MODIFY LOCAL DATA
CLIENT B - WRITE DATA (DO NOT ALLOW!!!)
...then you need to set TX_REPEATABLE_READ as the isolation level AND keep the transaction alive from CLIENT A READ to CLIENT A WRITE. If memory serves (and I admit this stuff does my head in at times) the CLIENT B READ should not happen until the A WRITE is complete. I could be wrong here, I can't remember exactly. Try it and see.
You are essentially trying to "check out" the data and then "check it in" again, with the lock held on it in the middle.
You could always have your session bean create a transaction, read the data from the bean as it is now and compare to the values it has been passed (You would have to have old and new values somewhere in the session bean in this case.) If the old values don't match what the bean says, then you kick out the update.
If you do that inside the appropriate transaction then you ensure the value of the bean won't change while you make your mind up and do the update. It's another bean hit though.
This is the kind of thing people used stored procedures for in the olden days. :-)
A little off the topic :-) You said:
>Since the system is pessimistically concurrent only one client will be allowed to modify the contents at a time, hence, no problem.
>Note this is regardless of transactional settings.
According to Weblogic 5.1 doc:
"The EJB 1.1 container in WebLogic Server Version 5.1 uses a pessimistic locking mechanism for entity EJB instances. As clients enlist an EJB or
EJB method in a transaction, WebLogic Server places an exclusive lock on the EJB instance or method for the duration of the transaction. Other
clients requesting the same EJB or method block until the current transaction completes. "
I am wondering if I set the Entity Bean to TX_NotSupported, can 2 clients access the same entity bean instance at the same time? Since you said it's regardless of transactional settings.
The short answer. No they can't. One thread blocks. Essentially the access to the entity will be serialized. Hence if you are simply trying to stop concurrent updates, then you're OK here with WebLogic regardless of your transaction settings IF, AND ONLY IF, you are only talking about updating a single entity bean, in a single method call. Go beyond that and you need transactions to keep the locks.
However, as I read the original question more, it became clear that this is actually a case of a long lived transaction, for which you can't use the JTA classes really, they are not for long lived stuff. Hence my last comment.
The discussion on Mastering EJB II actually covers this exact same problem as well, and the solutions offered are similar.
You could also use a timestamp in the bean and a timestamp on some value object that you suck out of the bean. When you call the set method, if the timestamps don't match, kick out the request.
(Note: This makes perfect sense to me, but it wasn't my idea, see the discussion on Mastering EJB II for the real author.)