Why are session beans not re-entrant while entity beans are?
By definition, Java monitors are re-entrant. ie, if an object has two synchronized methods and one of them calls the other, the object tries to acquire a monitor which it already has. Java supports this.
With this context in perspective, can somebody throw some light on this?
Thanks in advance
-
Re-entrant beans (6 messages)
- Posted by: Balakrishnan Lakshmanan
- Posted on: October 05 2002 19:43 EDT
Threaded Messages (6)
- Re-entrant beans by Gal Binyamini on October 06 2002 17:19 EDT
- Re-entrant beans by Adnan Rafiq on October 08 2002 14:49 EDT
-
Re-entrant beans by Gal Binyamini on October 09 2002 09:25 EDT
- Re-entrant beans by Gal Binyamini on October 09 2002 09:26 EDT
-
Re-entrant beans by Adnan Rafiq on October 09 2002 01:01 EDT
- Re-entrant beans by Gal Binyamini on October 09 2002 02:28 EDT
-
Re-entrant beans by Gal Binyamini on October 09 2002 09:25 EDT
- Re-entrant beans by Adnan Rafiq on October 08 2002 14:49 EDT
-
Re-entrant beans[ Go to top ]
- Posted by: Gal Binyamini
- Posted on: October 06 2002 17:19 EDT
- in response to Balakrishnan Lakshmanan
First of all, neither session beans nor entity beans are re-entrant by default. Entity beans, unlike session beans, can be configured as such.
Concurrent access to beans is not quite analogous to concurrent aqusition attempts of a Java monitor. There is no general notion of a "thread" which spans remote calls. EJB uses transactions instead. Transactions in an EJB environment are assumed to be single threaded, in the sense that any two concurrent calls performed in the same transaction context are considered an application error, and may allways be rejected by the container. In some cases (e.g re-entrant entity beans) this error may not be detected by the container, but it is still considered illegal and may have unexpected results.
It is generally a good idea for the container to detect the errornous condition above, so that unexpected results do not occur silently. However, detecting this condition is quite complicated, and may not even be possible in some cases. That's why the EJB spec defines beans to be non re-entrant by default, making sure that any concurrent call within a single transaction is detected and reported. This condition, is simple enogth to be checked at runtime. The problem is that this condition is stronger than necessary: even a single threads which re-enters a bean will be denied, although that's not strictly illegal. That is why re-entrant beans are also allowed. Session beans are not allowed to be re-entrant mostly because they are designed to serve one client anyway, and assuming that the session bean doesn't call back into the client (which is generally a fair assumption) there should be no re-entries (otherwise the session bean is serving some additional, different client).
Gal -
Re-entrant beans[ Go to top ]
- Posted by: Adnan Rafiq
- Posted on: October 08 2002 14:49 EDT
- in response to Gal Binyamini
Gal, thanks for a very englightening answer as usual :)
I was wondering if you can give an example of a single thread re-entering an entity bean as you mentioned in your post. How, why and when would this happen (sorry, I know that this is kind of a loaded question)? Thanks. -
Re-entrant beans[ Go to top ]
- Posted by: Gal Binyamini
- Posted on: October 09 2002 09:25 EDT
- in response to Adnan Rafiq
I'll give you an example of one common situation that I encountered a couple of times:
Consider a database where people and their employers (assume the employer is a person as well) are listed. A Person entity bean might model this database. The Person bean might provide access to information like the person's name and employer, but let's assume for the purposes of this example that it also provides a method to access the employer's name directly:
public void getEmployerName() throws RemoteException {
return getEmployer().getName();
}
A problem then arises when dealing with self-employed people. For such a person A, the getEmployer() call returns A, and the getName() call re-enters A. This all happens in the same transaction. Therefore, if Person had not been re-entrant, the call would fail.
In this case the error can be spotted and solved without much trouble, but in more complicated cases involving many beans that call into each other it's effectively impossible. This might also give you a bit of perspective on why enforcing the rule of no concurrent access within a transaction is so difficult. The container would have to check the call stack (including remote calls) to see if the bean is re-entering itself, or if it is a completely different call. If the thread extends through remote hosts that are not under the control of the app server (i.e, CORBA calls) the container wont even have access to that information, so it would be impossible to enfroce the rule.
Gal -
Re-entrant beans[ Go to top ]
- Posted by: Gal Binyamini
- Posted on: October 09 2002 09:26 EDT
- in response to Gal Binyamini
Heh, that one got posted twice... maybe TSS's new clustered environment isn't perfect yet? :) -
Re-entrant beans[ Go to top ]
- Posted by: Adnan Rafiq
- Posted on: October 09 2002 13:01 EDT
- in response to Gal Binyamini
Gal, thanks for your insightful answer. So, basically, what you're saying is that ideally we should always check the re-entrant option for an entity bean. But since it is such a resource-intensive process, in practice we should only turn it on for special cases such as the Person entity bean example you gave above. Am I on the right track here? -
Re-entrant beans[ Go to top ]
- Posted by: Gal Binyamini
- Posted on: October 09 2002 14:28 EDT
- in response to Adnan Rafiq
Making a bean re-entrant is not resource intensive. The reason why you might want to make a bean non-reentrant is that this way you can stop concurrent calls within a transaction, which are really illegal and may cause unexpected results.
In a perfect world app server would simply check against these concurrent calls, and you wouldn't have to configure anything. The problem is that checking against it is simply impossible. So you can mark a bean as non-reentrant, which will check against any re-entry into bean code, even non-concurrent. This is easy to check, but it also rules out valid cases like in the person example, where the call is a re-entry, not a concurrent call.
If you don't need re-entry, you can use non-reentrant beans to make sure no concurrent calls are made. If you do need reentry you can use reentrant entity beans, making you the one responsible for avoiding concurrent calls.
Gal