I'm currently learning about EE threads (e.g., TimerService, Asynchronous EJB, Asynchronous Servlet) because on upgrading some very legacy code to the latest and greatest, I learned doing threads on your own (e.g., Runnable, TimerTask, Thread) in an EJB environment is a no-no. I think I understand the basics but have some questions.
I ran across some legacy code that spawns one thread. This thread has a run() method w/ a while(true) and inner try/catch that ensures the thread never dies. The logic w/in the run() method checks a condition and if the condition is met does something and on completion re-checks the condition. If the condition is not met it calls wait(). Somewhere else in the code, something else happens and calls notifyAll() which in essence wakes the thread up causing it to re-check the condition.
In the example above I see 2 things. First, there is only and ever one thread. If there are multiple things to do, the thread does each sequentially (by re-checking the condition). Second, when there is nothing to do there is no overhead - the thread sleeps until it's notified there is something to do.
Can I implement something equivalent to this w/ the EE approved thread mechanisms? It seems to me if I used TimerService w/ a single invocation timer and the existing run() implementation, I'm still in violation of the EE spec (e.g., should not susped or resume threads)...or am I? If I used TimerService w/ an interval time and the existing run() method minus the while(true) loop, it would result in multiple threads and also incur overhead checking the condition every interval. Also, the run() method might need added complexity to ensure only one thing is handled at one time. For example, assume the timer fires and starts to handle one thing and before it finishes, the timer fires again. This could be undesirable and I'm not sure it's possible to find an interval time that guarantees this. Lastly, it seems if I used an Asynchronous EJB/Servlet call (instead of invoking notifyAll()), this makes sure a thread only occurs when necessary but still makes things complicated to ensure only one thing occurs at a time.
It seems like it is going to be quite a mess and time consuming to upgrade the legacy code to comply w/ the EE specification. The code that creates/uses the threads and have fine-grained control over them are tightly integrated and conversion does not appear to be straightforward. It's a shame complete control no longer seems to be there (unless I'm totally missing something). I understand the managed vs. unmanaged issues ... will there ever come a time when we can still do threads like we used to but perhaps "request" them from the container? I'm also thinking about the use of 3rd party libraries like Quartz which spawns threads to execute jobs - these are now unmanaged and therefore should be unmanaged but the TimerService just doesn't seem to come close to the functionality Quartz can provide and some of what we're currently using and can't lose.
Any and all thoughts to provide understanding are welcome,
low-level thread handling inside a JEE application doesn't sound like a very good idea. Especially because there are much better ways to deal with your requirement (at least if you can use EJB 3.1). If I understand correctly all you need is a mechanism to call some functionality in intervals, right?
To accomplish this you could simply create an EJB and annotate a method containing your "real" application logic with the @Schedule annotation to specify the interval/scheduling plan at wich this method will be automatically called by the container. Have a look at this tutorial.
Joined: Jan 08, 2002
Thanks, I saw this tutorial along w/ many others. I also just figured out that the annotation only apply to EJB classes...something I missed. I tried adding them to a simple POJO and found nothing fired.
My beef w/ the TimerService in the specific case I referenced is that it must "wake up" every so often to check to see if anything needs done. The "check" can be expensive and therefore this unnecessarily eats resources - it's yet another thread, it's taking up CPU cycles, DB cycles and it's possible the check does not complete before the next fire. This is something that does not occur w/ the current Thread implementation. Also as I mentioned before it requires adding complexity to the business logic to ensure only one item is processed at a time.
I'm sure the existing code can be converted into something compliant. This will be time consuming because the business logic is not designed to work the new way (e.g., the thread run() method is in an inner class or part of an object hierarchy) - in other words, this is not an easy or straight-forward modification. It seems like one needs to create EJBs for every little last thing (lots and lots of EJBs). Also, it seems I cannot guarantee the exact same behavior. Right now I just feel like my hands have been tied up and I can't do what I need to do. I guess when writing code for the first time in this kind of environment you know what you have to work w/, you set expectations, you design and implement appropriately. However, it's tough when an older application has existing behavior and business rules that don't seem to be supportable (in the what one is supposed to do sense) w/ the new ways of doing things. Just blowing off some steam...