Threads rule! Seriously though... only use threads if you know how they work :)
Quartz can do a lot for you (and is a piece of cake to use in struts apps). It provides cron like functionality, and can also use persistant tasks that survive container restarts. Threads are good for simple unimportant asynchronous stuff. Eg. sending emails. If an action triggers the sending of emails, and there's no need to know if they've been sent, then why make the user wait for slowwww smtp servers. Fire off the emails in a new thread (i wrote a 'BackgroundSender' for commons email which does this for you). As a rule this kind of thing is ok if you wont be generating a huge number of threads, and you write the code carefully. Eg if you take a look at the code i copied below, you'll see the run method takes the form: public void run() { try { theMail.send(); } catch (MessagingException ex) { } } This is ok as it runs, and if it fails, it fails - it doesnt loop! The following would be taking your life into your own hands: public void run() { boolean success=false; while (!success){ try { theMail.send(); success=true; } catch (MessagingException ex) { } } } This code looks like a good idea - keep trying to send the message until it is sent. But lets say the smtp server it uses goes down, and you get a few hundred mails all trying to go out at the same time. It wont be pretty! Also, a malformed message that the smtp server rejects would be stuck in an infinite loop! So if you use threads, be careful! Daniel. -----------BackgroundSender.java----------- package org.apache.commons.mail; import javax.mail.MessagingException; /** * A class to send messages in the background. Compose the mail as normal, then * use the static method: BackgroundSender.send(Email mail) to send the email. * * @author Daniel Perry */ public class BackgroundSender extends Thread { Email theMail; /** * Constructor takes an Email object, and sends it from a background thread. */ private BackgroundSender(Email mail) { super(); this.theMail = mail; } /** * Static method to send a org.apache.commons.mail.Email message in the * background. Note that if the message fails to get sent there is NO * notification! * * @param mail */ public static void send(Email mail) { new BackgroundSender(mail).start(); } /** * The run method of the thread that actually sends the mail. */ public void run() { try { theMail.send(); } catch (MessagingException ex) { // print out exception for reference, this is running in a // background thread, and noone will do anything about the error. ex.printStackTrace(); } } } > -----Original Message----- > From: Erik Weber [mailto:[EMAIL PROTECTED] > Sent: 07 December 2004 06:26 > To: Struts Users Mailing List > Subject: Re: [OT]Threads and Servlets Question > > > > > Erik Weber wrote: > > > This is covered by JMX. For example, see javax.management.timer.Timer > > (which can be initialized/destroyed by a ServletContextListener). The > > idea is that you can schedule asynchronous operations but leave the > > Threads to be managed by the server. > > > > JBoss supports this but I haven't had any luck determining if Tomcat > > has any support in this area. > > Which is not to say that it won't work in Tomcat. I have used this > technique in a couple of production applications running on Tomcat, and > it seems to be reliable. But in those cases the Timer instance is not > created by Tomcat (it is simply instantiated directly by a > ServletContextListener) or registered with Tomcat (as would be the case > with WebLogic's Timer extension) and I suppose would be subject to the > security constraints that Craig mentioned. So I'm not sure it's much > different from instantiating your own java.util.Timer (which by the way > is, according to the Sun documentation, optimized for availability). > > Erik > > > WebLogic appears to have superior support in this area. > > > > Erik > > > > > > > > Andrew Hill wrote: > > > >> <snip> > >> DON'T spawn threads inside a servlet container unless you > really, REALLY > >> have to. It'll tend to save you headaches more times than not. But if > >> you gotta do it, do it with care :) > >> </snip> > >> > >> Or as they say "dont try this at home kids" :-) > >> > >> <snip> > >> a policy that prohibits them. (For example, > >> if I was running an ISP hosting service, that's something I would > >> almost certainly restrict.) > >> <snip> > >> That's an excellent point... especially for someone developing an app > >> that they intend to deploy to a shared environment > >> </snip> > >> </snip> > >> > >> Which leads me to wonder how one does scheduled jobs in such an > >> environment? Would this be a technique that is specific to the host > >> in question? > >> > >> > >> Frank W. Zammetti wrote: > >> > >>> Craig McClanahan wrote: > >>> > >>>> You might be thinking of the J2EE platform spec, which > identifies some > >>>> of the issues with threads in EJB containers, or when you're > trying to > >>>> use transactions. The servlet spec describes a bunch of things that > >>>> are either likely to or guaranteed to not work when you deal with > >>>> multiple threads in the context of a single request. > >>> > >>> > >>> > >>> > >>> That sounds like it, but I'm admittedly working from fuzzy > >>> half-memories... reading the big specs isn't something I tend to do > >>> as a hobby :) > >>> > >>>> It is. Who ever said that "popular" and "a good idea" were always > >>>> synoymous? :-) > >>> > >>> > >>> > >>> > >>> Certainly not me :) > >>> > >>>> It's also the case that a very large number of webapps are installed > >>>> on standalone servlet containers like Tomcat, which don't enforce the > >>>> "no threads" restriction unless you configure them to run a security > >>>> manager, and then provide a policy that prohibits them. (For example, > >>>> if I was running an ISP hosting service, that's something I would > >>>> almost certainly restrict.) > >>> > >>> > >>> > >>> > >>> That's an excellent point... especially for someone developing an > >>> app that they intend to deploy to a shared environment, they > >>> definitely want to keep this in mind. > >>> > >>>> Just out of curiousity, how do ensure that the threads are ever shut > >>>> down correctly? > >>> > >>> > >>> > >>> > >>> I frankly don't. Because of the nature of these threads, they can > >>> die inelegantly with no problem (unless the server goes down WHILE > >>> they are processing, but I'm sure that's true of any thread). They > >>> are like scheduled tasks really, one fires once a day, on fires once > >>> an hour, etc. But because they make use of a lot of business logic > >>> from the app, logic that isn't exposed any other way, making them > >>> daemon threads made sense (we also get to use the connection pool > >>> already established for the app, and some other minor resources that > >>> only exist when the app is running). These threads don't service > >>> requests in any way, they do periodic processing (one ages records > >>> according to some complex business rules, another re-sends > >>> non-time-critical asynchronous messages to a mainframe-based system > >>> if the message had previously failed, things like that). > >>> > >>>> Are there any controls to ensure that other parts of > >>>> your app won't hang forever waiting for a response from such > a thread? > >>>> Are there any places where you pass in a servlet request or session > >>>> object to another thread (even as a parameter to a method > that returns > >>>> synchronously)? Are you assuming that you can propogate transaction > >>>> context across threads (most implementations use a thread local > >>>> variable to store this context, so passing a message to a new thread > >>>> will typically *not* have the same transaction privileges as the old > >>>> one). > >>> > >>> > >>> > >>> > >>> As per my last comment, they aren't servicing requests, so these > >>> points don't apply in this particular case. Good points to be sure > >>> though. > >>> > >>>> If you're not having any of those problems, you're probably fine ... > >>>> that's only the things to watch out for I thought of in the time it > >>>> took me to type the paragraph (there's undoubtedly a bunch more). > >>> > >>> > >>> > >>> > >>> Isn't there always with threading? :) Anyone that has done anything > >>> even remotely non-trivial with threads has inevitably run into > >>> troubles at some point, it's just the nature of the beast. > >>> > >>>> Threads are a powerful problem solving technique, for the right kinds > >>>> of problems. It's just that the exercise of power also comes with > >>>> associated responsibility to understand what you're doing, and what > >>>> you shouldn't do, with your powers :-). > >>> > >>> > >>> > >>> > >>> Yes, what he said! :) > >>> > >>> >>What I'm really getting to here, and I suspect it would be for the > >>> > >>>>> benefit of a great many people reading this, is the simple question, > >>>>> what is actually OK to do with threads in a servlet container and > >>>>> what > >>>>> isn't? Perhaps more importantly, what is the reasoning behind the > >>>>> answers? Any thoughts? (not necessarily just from Craig :) ) > >>>>> > >>>> > >>>> > >>>> There isn't going to be universally applicabe answers to > that question > >>>> -- it's going to depend a lot on things like whether you're > running in > >>>> a container that supports this (some containers might support > >>>> appication-spawned threads as a value-add feature with extra help to > >>>> avoid or solve some of teh problems), what your use case is, > what else > >>>> is going on in the same container, what your security policies are, > >>>> how skilled your developers are, ... > >>>> > >>>> It's hard to give relevant general answers on a question like this. > >>>> > >>>> But I would tend to worry less when the number of users is small, the > >>>> amount of available CPU and memory is large, and your developers have > >>>> done some basic study on threading and/or you have somebody who > >>>> understands this stuff doing code reviews. > >>> > >>> > >>> > >>> > >>> Of all those, the skill of the developer tends to matter most > >>> (assuming us architects haven't speced out something ridiculous that > >>> is). At least, that's been my experience. > >>> > >>> I agree that a general answer to this question is near impossible, > >>> but I'll take a stab at in anyway... > >>> > >>> DON'T spawn threads inside a servlet container unless you really, > >>> REALLY have to. It'll tend to save you headaches more times than > >>> not. But if you gotta do it, do it with care :) > >>> > >>> (Am I the King of simplistic double-talk or what?!?) > >>> > >>> Frank W. Zammetti > >>> Founder and Chief Software Architect > >>> Omnytex Technologies > >>> http://www.omnytex.com > >>> > >>>> Craig > >>>> > >>>> > >>>> > >>>>> -- > >>>>> Frank W. Zammetti > >>>>> Founder and Chief Software Architect > >>>>> Omnytex Technologies > >>>>> http://www.omnytex.com > >>>>> > >>>>> > >>>>> > >>>>> > >>>>> Craig McClanahan wrote: > >>>>> > >>>>>> You're using the typical pattern for this use case (although it's > >>>>>> also > >>>>>> feasible you could use something like JMS to accomplish the > >>>>>> asynchronicity). The most important thing to do, though, is to > >>>>>> ensure > >>>>>> that you eventually kill the thread no matter what > actually happens, > >>>>>> so that you don't have something needlessly consuming resources for > >>>>>> the remainder of the lifetime of your server instance. > >>>>>> > >>>>>> Craig > >>>>>> > >>>>>> > >>>>>> > >>>>>> On Tue, 7 Dec 2004 10:50:06 +0800, Yves Sy <[EMAIL PROTECTED]> > >>>>>> wrote: > >>>>>> > >>>>>> > >>>>>>> Here's a follow-up question: > >>>>>>> > >>>>>>> I remember creating a thread in one of my Action classes because I > >>>>>>> needed to show a "Wait while your request is being processed..." > >>>>>>> page. > >>>>>>> > >>>>>>> The flow goes something like: > >>>>>>> 1. the MAIN thread returns an ActionForward right away that > >>>>>>> contains the "processing" page; > >>>>>>> 2. the NEW thread I created goes ahead and makes the back-end call > >>>>>>> that takes a considerable amount of time to process; > >>>>>>> 3. After NEW thread returns with the results, it sets a flag in > >>>>>>> the session that it's done with the processing; > >>>>>>> 4. Meanwhile, the processing page keeps refreshing itself and > >>>>>>> sending execution to an action which checks for the session flag > >>>>>>> set > >>>>>>> in #3; > >>>>>>> 5. When it finally finds the session flag, it forwards to the > >>>>>>> results page. > >>>>>>> > >>>>>>> Its working fine for me. No weird behavior on Weblogic or SAP WAS. > >>>>>>> Although now I'm curious: Is there a better way to approach this > >>>>>>> problem? > >>>>>>> > >>>>>>> Regards, > >>>>>>> -Yves- > >>>>>>> > >>>>>>> On Mon, 6 Dec 2004 15:03:09 -0600, [EMAIL PROTECTED] > >>>>>>> > >>>>>>> > >>>>>>> <[EMAIL PROTECTED]> wrote: > >>>>>>> > >>>>>>> > >>>>>>>> As has been noted by others, JMS would be the better solution > >>>>>>>> for an > >>>>>>>> asynchronous 'process'. > >>>>>>>> > >>>>>>>> But, if you have to use threads then it is probably a better > >>>>>>>> approach to > >>>>>>>> create a thread pool at appliction initialization and have the > >>>>>>>> actions use > >>>>>>>> those threads via a common synchronized data structure (hidden > >>>>>>>> behind an > >>>>>>>> interface). > >>>>>>>> > >>>>>>>> Ensure that you have a good unique context for correlating the > >>>>>>>> request and > >>>>>>>> response (not to be confused with the http req/resp) > >>>>>>>> > >>>>>>>> depending upon the volume of traffic you should be able to get > >>>>>>>> away with a > >>>>>>>> small number of threads. The actual count can be controlled via > >>>>>>>> an extenal > >>>>>>>> property. > >>>>>>>> > >>>>>>>> good luck. > >>>>>>>> > >>>>>>>> JC > >>>>>>>> > >>>>>>>> "Jim Barrows" > >>>>>>>> <[EMAIL PROTECTED] To: "Struts Users Mailing List" > >>>>>>>> <[EMAIL PROTECTED]>, > >>>>>>>> m> [EMAIL PROTECTED] > >>>>>>>> cc: > >>>>>>>> 12/06/2004 02:52 Subject: RE: [OT]Threads and Servlets Question > >>>>>>>> > >>>>>>>> > >>>>>>>> PM > >>>>>>>> Please respond to > >>>>>>>> "Struts Users > >>>>>>>> Mailing List" > >>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>>> -----Original Message----- > >>>>>>>>> From: bryan [mailto:[EMAIL PROTECTED] > >>>>>>>>> Sent: Monday, December 06, 2004 1:15 PM > >>>>>>>>> To: Struts Users Mailing List > >>>>>>>>> Subject: Re: [OT]Threads and Servlets Question > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> threads are also a finite resource ( particularly on Linux ). > >>>>>>>>> > >>>>>>>>> --b > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> On Mon, 6 Dec 2004 21:13:57 +0100, bryan <[EMAIL PROTECTED]> > >>>>>>>>> wrote: > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>> because you should use a message driven bean to do > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> something like that. > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>> --b > >>>>>>>>> > >>>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> If the brass monkeys upstairs would let me, I would. However, > >>>>>>>> they won't, > >>>>>>>> and I've used up all of my "oops I did it anyway" cards for a > >>>>>>>> while. So, > >>>>>>>> while helpful, doesn't really answer my question. > >>>>>>>> > >>>>>>>> As for a finite resource...... as someone else said so is > >>>>>>>> memory, disk > >>>>>>>> space, CPU, etc etc. As for being on linux.... I've done some > >>>>>>>> pretty nasty > >>>>>>>> multi-threading, in java, on linux and haven't hit that ceiling > >>>>>>>> yet... > >>>>>>>> ymmmv. > >>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>>>> > >>>>>>>>>> > >>>>>>>>>> On Mon, 6 Dec 2004 11:48:15 -0700, Jim Barrows > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> <[EMAIL PROTECTED]> wrote: > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>>> Okay... I know I've read this somewhere, but can't remember. > >>>>>>>>>>> Why is it recommended you NOT start a thread inside a > >>>>>>>>>> > >>>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> servlet, which would translate to "Why is it a bad idea to > >>>>>>>>> start a thread inside an action?". > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>>> And, can you point me at some documentation? > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>>> > >>>>>>>>> > --------------------------------------------------------------------- > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED] > >>>>>>>>>>> For additional commands, e-mail: [EMAIL PROTECTED] > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>>>> > >>>>>>>>>> > >>>>>>>>>> -- > >>>>>>>>>> http://www.revoltingdigits.com > >>>>>>>>>> https://jestate.dev.java.net > >>>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> -- > >>>>>>>>> http://www.revoltingdigits.com > >>>>>>>>> https://jestate.dev.java.net > >>>>>>>>> > >>>>>>>>> > --------------------------------------------------------------------- > >>>>>>>>> > >>>>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED] > >>>>>>>>> For additional commands, e-mail: [EMAIL PROTECTED] > >>>>>>>>> > >>>>>>>>> > >>>>>>>> > >>>>>>>> > --------------------------------------------------------------------- > >>>>>>>> > >>>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED] > >>>>>>>> For additional commands, e-mail: [EMAIL PROTECTED] > >>>>>>>> > >>>>>>>> > >>>>>>>> > ------------------------------------------------------------------ > ------------ > >>>>>>>> > >>>>>>>> ********** > >>>>>>>> The information contained in this communication is > >>>>>>>> confidential, private, proprietary, or otherwise privileged and > >>>>>>>> is intended only for the use of the addressee. Unauthorized > >>>>>>>> use, disclosure, distribution or copying is strictly prohibited > >>>>>>>> and may be unlawful. If you have received this communication in > >>>>>>>> error, please notify the sender immediately at (312)653-6000 in > >>>>>>>> Illinois; (972)766-6900 in Texas; or (800)835-8699 in New Mexico. > >>>>>>>> ********** > >>>>>>>> > ================================================================== > ============ > >>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> > --------------------------------------------------------------------- > >>>>>>>> > >>>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED] > >>>>>>>> For additional commands, e-mail: [EMAIL PROTECTED] > >>>>>>>> > >>>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> -- > >>>>>>> A bus station is where a bus stops. A train station is where a > >>>>>>> train > >>>>>>> stops. On my desk I have a work station... > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > --------------------------------------------------------------------- > >>>>>>> > >>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED] > >>>>>>> For additional commands, e-mail: [EMAIL PROTECTED] > >>>>>>> > >>>>>>> > >>>>>> > >>>>>> > >>>>>> > --------------------------------------------------------------------- > >>>>>> > >>>>> > >>>>> > >>>>> > >>>>> > >>>>> > >>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED] > >>>>>> For additional commands, e-mail: [EMAIL PROTECTED] > >>>>>> > >>>>>> > >>>>>> > >>>>>> > >>>>>> > >>>>> > >>>>> > --------------------------------------------------------------------- > >>>>> To unsubscribe, e-mail: [EMAIL PROTECTED] > >>>>> For additional commands, e-mail: [EMAIL PROTECTED] > >>>>> > >>>>> > >>>> > >>>> > >>>> > >>>> > >>>> > >>> > >> > >> > >> --------------------------------------------------------------------- > >> To unsubscribe, e-mail: [EMAIL PROTECTED] > >> For additional commands, e-mail: [EMAIL PROTECTED] > >> > >> > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]