EJB programming & troubleshooting: Re-entrant beans

  1. Re-entrant beans (6 messages)

    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

    Threaded Messages (6)

  2. Re-entrant beans[ Go to top ]

    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).

  3. Re-entrant beans[ Go to top ]

    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.
  4. Re-entrant beans[ Go to top ]

    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.

  5. Re-entrant beans[ Go to top ]

    Heh, that one got posted twice... maybe TSS's new clustered environment isn't perfect yet? :)
  6. Re-entrant beans[ Go to top ]

    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?
  7. Re-entrant beans[ Go to top ]

    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.