EJB design: Synchronized keyword
I have great respect for some of the stalwarts like Gal Binyamini, Floyd Marinescu, Tyler Jewell et al. for all their valuable tips and suggestions.
I am uncertain about the use of synchronized keyword in EJB environment and would appreciate a thorough discussion on this matter to cleap up my concepts.
For a start, the Specification states the following
"An enterprise Bean must not use thread synchronization primitives to synchronize execution of multiple instances."
To this GAL replied (http://www.theserverside.com/patterns/thread.jsp?thread_id=13933)
"The question is, what exactly does "to synchronize execution of multiple instances" mean. I think it would be very unlikely for anybody (i.e, App server makers) to interpret this rule as "you can't use synchronization to synchronize threads alltogether". The main reason is that many Java libraries use constructs such as Singletons, which require synchronization at some level. It seems quite restrictive to rule out all such libraries (my bet is it would essentially rule out atleast 90% of the libs, but I can't say that for sure :)). Therefore, I interpret this rule to mean "don't use synchronization to make multiple instances of a bean block each other".
According to EJB design patterns there is nothing wrong with using Synchronized keyword as long as developers donot use it in read/write fashion in which case the ejb threads
(Sorry abt the incomplete posting. the keys goofed up!!!)
..... calling in may need to be blocked.
Initially from the way the spec stated, I thought the ejb beans (session) shouldnt have synchronized keyword within themselves but the simple java classes that these beans might call can synchronize since they are not EJB beans themselves. But after what the design pattern book states it seems that any jave object that is being used by the EJB beans should have limited use (essentially for read-purpose) of the synchronize keyword !
Is this really how far we can extend the use of synchronization to when EJB beans are around?
Also if there is a hub that uses session beans for workflow and a generic framework of pure java classes that spawns control threads for some of its purposes - like monitoring configuration files for updates etc. - and accessable to the session beans through the DAO layer how far would this architecture conform to EJB specs?
The problem with synchronization in EJBs is that the EJB server itself will perform synchronization actions on your EJB objects. Since you have no control over these actions, poorly written synchronization logic on your part can lead to thread-deadlock.
You are correct that the one thing that you must not do is use the synchronized keywork on any EJB method, or use a synchronize(this) block inside an EJB. In general, it is save for EJBs to use other (non-EJBs) objects that have synchronized methods, but you should be careful about sharing those objects. Personally, I try to limit synchronized objects to private variables to reduce the likelihood of deadlock.
Also, spawning new threads is technically forbidden by the EJB specification:
"The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread; or to change a threads priority or name. The enterprise bean must not attempt to manage thread groups."
People do it anyway, for the purposes that you suggest. Just bear in mind that any transaction and security context you have will not propogate to the new thread (which is probably OK for monitoring threads).
I used a Singleton "ConfigUtil" Object essentially to read the attribute values corresponding to the nodes in the XML configuration file. Thus deadlock situations will not occur in this scenario. (The beans and the file will be packaged in one machine and NOT distributed. The environment isnt clustered either) Looking back, this functionality is essentially a Read-Operation and hence does conform to the "EJB design pattern" statement.Thinking about it, most of the operations (90%) performed with Singleton are read-operations like resource lookups.
Your comment was very helpful specially where you say that "In general, it is safe for EJBs to use other (non-EJBs) objects that have synchronized methods".
Is someone willing to disagree on this ? If you do, then please back yourself with solid reasonings...
The restriction on thread primitives usage in the EJB spec has two reasons as far as I can tell:
- To make sure the synchronization methods used by the bean do not clash with those used by the EJB container in a way that would cause deadlock, starvation or other synchronization problems.
- To make EJBs "location independent" in the sense that if the bean is deployed on more than one machine (for instance in a cluster) it's behaviour does not change. Since the synchronization operations by one bean only affect other beans running in *the same* JVM, synchronization primitives in general can hurt this independence unless the code is cautiosly written.
I see no reason why these restrictions should only be applied to the bean's class itself. Moving unsafe thread management code to a helper class doesn't help. The exception to this are seperately deployed JCA components, which have their own contracts which do allow thread management. If you must do some serious thread-related operations, and you must be EJB compliant, JCA could be the solution.
Generally it is safe to use synchronization primitives (preferrably not on any container-visible classes like the bean implementation class or the PK) as long as you don't use them to synchronize the execution of multiple bean instances. If you just use the "add" method of some Vector which is not shared by multiple bean instances, there is no problem.
With singletons you do potentially synchronize the execution of multiple bean instances. However, I don't think singletons violate the two restrictions given above, under the following condition:
- Your application would still function correctly if the "getInstance" returned a different instance for each bean that called it.
The container could potentially put each bean in a seperate VM, so this condition is necessary.
Using singletons to avoid reloading the configuration each time is no problem. If the "getInstance" method returned a different instance to each caller, the application would still work (although it wouldn't be as fast).
Spawning threads in EJBs is generally not a very good idea, because the container would not be aware of the threads so they won't be pooled and their transaction/security contexts would be unclear. The application server might also assume all of it's threads are subclasses of some superclass. That might be used for implementing faster ThreadLocal-style classes, and god knows what else.
Like I said above, if you need to do serious thread management JCA can do the job. If you just need a couple of simple threads you can spawn them directly, as long as they don't access the application server (i.e, don't use JDBC connections managed by the application server, don't call EJBs directly, etc). This applies not only to the bean class itself, but also to helper classes that it calls.