• Post Reply Bookmark Topic Watch Topic
  • New Topic

Thread in a Servlet  RSS feed

 
Jason Barker
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm developing a web service that accomplishes a business process but it requires the user to walk through a process and provide input at several stages of the process. I've got separate web pages for each of the different steps. There is one step that takes about 5 to 10 minutes of processing time to complete. So, to get around this, I thought I would create a "stand by" page that would refresh itself every 30 seconds. I've set this up so that my "controller" class receives the request, starts a thread that runs in the background, and then the controller executes the following line of code:

This page is included in the output to the browser. It is set to refresh itself (with Javascript's setInterval() function). Up to this point, my stuff works fine and the "standby.jsp" page is diplayed the first time. However, when the page attempts to refresh itself for the first time, the page times out on me and it won't show itself again. (This is in the Oracle Portal environment for those who care and I get the following message: "Error: The portlet cannot be contacted.") I think this is more of a matter of me getting something wrong with my expectations of threads rather than my environment. (ie. I may be wrong in thinking that the thread would run in the background and have no further effect with my servlet.)

Does anyone have any suggestions on what I could do to get my servlet to continue running unaffected by this thread?
[ August 09, 2005: Message edited by: Jason Barker ]
 
Gregg Bolinger
Ranch Hand
Posts: 15304
6
Chrome IntelliJ IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't know if this will help solve your problem but waiting for 5-10 minutes on a Stand By page is horrible from an end user perspective. Why not screw the whole thread issue and just navigate to a page that says something like:

You will receive an email when your process has completed.

And then have the service send an email with a link to the user to pickup where they left off with the 5-10 minutes process completed. Does that make sense? Obviously I don't know your project requirements so you might not have the option of doing this or some similar way.
 
Jason Barker
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ha, ha! You're right. This would be silly if the user had to sit at their computer and watch it. Actually, the user would get to this point, submit the information and do other tasks at their desk, while keeping an eye on the computer screen. However, the users who choose to sit and wait until this is done will get fired.
 
Gregg Bolinger
Ranch Hand
Posts: 15304
6
Chrome IntelliJ IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jason Barker:
Ha, ha! You're right. This would be silly if the user had to sit at their computer and watch it. Actually, the user would get to this point, submit the information and do other tasks at their desk, while keeping an eye on the computer screen. However, the users who choose to sit and wait until this is done will get fired.


Even so, it isn't very user friendly. What if the user is doing other work on the web and closes the "Standby" page by accident? Seriously, if I had to wait 5-10 minutes and "keep an eye on" the process to complete, I'd be very annoyed. What is this long process anyway?
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66207
151
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As Gregg pointed out, that would be eggregiously bad UI. I've done this sort of thing many times before and either use Gregg's suggestion of a completion e-mail, or provide a status page that users can visit at their own volition to monitor the progress of the operation. Or both.
 
Yuriy Zilbergleyt
Ranch Hand
Posts: 429
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And I see that no one actually answered the original question, which is how to launch a thread that would run independent of the current request/response cycle. One way would be to use something like a JMS Queue - the servlet puts a request in the queue, and completes. Or you could do it using Ajax (XMLHttpRequest) on the client side - initiate the request, and then either let the handler function take care of informing the user when the job's finished, or use another XMLHttpRequest object to poll the servlet at intervals. If you're not familiar with Ajax, you can find out more about it on the HTML/Javascript forum.

Finally you can even have the servlet flush the "Please Wait" HTML to the output, THEN do the timeconsuming work, and afterwards flush the rest of the output, including Javascript that would hide or CSS'd elements that would cover up the original "Please Wait".

If you go with the Email notification approach, I suggest you either use Ajax to send the request without blocking for the response, or flush the "You may now close this window" message to the output before doing the timeconsuming operation.

-Yuriy
 
Jason Barker
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Even so, it isn't very user friendly... Seriously, if I had to wait 5-10 minutes and "keep an eye on" the process to complete, I'd be very annoyed.


I appreciate your concern for the end user's time. However, this process has reduced the time to complete this same task by other means from over two hours to 5-10 minutes. They are quite pleased with this solution. In fact, they prefer to not have to be on their computer so much as other items require more of their attention that do not relate to their computer.

What is this long process anyway?

A bunch of database queries, inserts and updates to process customer data in batches.

...that would be eggregiously bad UI...

That's a matter of opinion. The end users would strongly disagree with you.

...either use Gregg's suggestion of a completion e-mail...

So, they would sit and wait for an email to pop up in their in box. This is what my stand by page does -- notifies the user that something is done...and they only wait at most, 30 seconds longer to know that the process is finished (rather than waiting for mail servers to send and receive the message out over the Internet).

...or provide a status page that users can visit at their own volition to monitor the progress of the operation.

This is part of an input process. A status page adds a longer break to the process.

Back to my issue. I'm trying to figure out how to get my servlet to run again, seeing as how it seems to be stuck with the execution of this thread. Any ideas?


Thanks!
 
Yuriy Zilbergleyt
Ranch Hand
Posts: 429
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
See my post above yours

IMO the simplest method would be flushing the output before all the DB calls. The servlet still wouldn't complete until the DB stuff is finished, but the user would get a nice "Please Wait" message that could be overwritten with the output after the DB calls complete.

-Yuriy
 
Jason Barker
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When you say flushing the output, what do you mean by that? Is that something I do by putting my include line of code before initializing and starting the thread? Or is it something else?


Thanks for your input.
 
Gregg Bolinger
Ranch Hand
Posts: 15304
6
Chrome IntelliJ IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, they would sit and wait for an email to pop up in their in box. This is what my stand by page does -- notifies the user that something is done...and they only wait at most, 30 seconds longer to know that the process is finished (rather than waiting for mail servers to send and receive the message out over the Internet).

In your first post you said this page sits there for 5-10 minutes. That was the reason for mine and Bear's UI suggestions. Sorry for not helping with your issue more precisely but sometimes the answers lie not in answering the question you've asked but by suggesting alternative means of reaching a similar goal. I'll bow out from here.
 
Jason Barker
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'll bow out from here.

Don't do that. You might know how to figure this out.

Well, let's say that I can possibly get the wait time down to 1-2 minutes. I would still like to approach this with a "stand-by" page that refreshes itself. However, when the initial view of the stand-by page sends the request back to the web server and then to the servlet, it still hangs. I thought that using a thread to do my background database processing would run independently of my servlet. Instead, it seems to lock me out of the servlet until the thread has completed execution. Is this behavior to be expected? Shouldn't I be able to start the thread and have it run asynchronously with the servlet?

Please help. Thanks.
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66207
151
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I need to bow out at this point as well. While you may be able to get things to work the way that you are describing, the reason that Gregg and I have said what we did is because we see you going down a path full of brambles and dead-falls trying to do something in a way that the protocol wasn't really intended for, as well as being just plain bad UI design (despite your assertion to the contrary -- not only is making them stay on the same page without being able to do anything else for an extended period not a great idea, what happens if they accidentally click away? or close the browser? or the browser crashes? How do you propose they pick up where they left off?)

While I've done thread programming outside of the servlet environment, I've not done any in conjunction with servlets and don't know of any special pitfalls that you need to watch for. It almost sounds like your servlet is blocking waiting for the thread -- which doesn't make a lot of sense for subsequent requests since each should fire in their own thread.
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66207
151
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
P.S. You a fan of GPF?
 
Jason Barker
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
...trying to do something in a way that the protocol wasn't really intended for...


Have you been to priceline.com or orbitz.com? Are you familiar with their "Stand-By" page your are sent to when looking up flights, hotels and other travel plans? Are you saying they have poorly designed web sites, that their process of making the user "wait" is a bad idea? Would you rather plug in your travel dates and then wait a while to be notified via email so that you could go back and check on what it was you were looking up?

If the browser crashes or they close the window accidentally before the process is through, they will re-enter the data from before (the whole process could take about 7 to 12 minutes from start to finish). Also, by restarting the process, any old data gathered from their previous session is cleared out (if it was not successfully completed).

Do we still need to debate your opinion of good/bad UI design or can we address the issue of what could be holding up the servlet?
 
D Rog
Ranch Hand
Posts: 472
Linux Objective C Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you open more your code. I have a similar approach and it works perfectly, so when page is updating a user can see a progress of a process. A user can also select other part of application and then return back to verify what's going on. Using Ajax is brilliant idea however it's browser dependent. I'd prefer to use a simple hidden frame. If talk about browser dependent solution, then check out one of my old projects:
http://www.gena.crocodile.org/chathouse/readme.htm
 
Yuriy Zilbergleyt
Ranch Hand
Posts: 429
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When you say flushing the output, what do you mean by that? Is that something I do by putting my include line of code before initializing and starting the thread? Or is it something else?

The response's PrintWriter has a flush() method which flushes the writer's buffer to the output. That means that while the servlet has not finished execute, the user's browser receives a part of the response. Note that flushing commits the response, so you'll get an IllegalStateException if you try to do something that requires an uncommited response (setting headers, cookies, forwarding, etc.)

You could do it like this:



barebones waitMessage.jsp:


barebones results.jsp :


I haven't actually tested this, but it should work. Unless the browser decides to time out while waiting for the servlet to finish - you'll have to test that. What happens is that there is still only one thread, but the user sees the "Please Wait" message before the thread finishes.

Hope this helps,
Yuriy
 
Tim Holloway
Bartender
Posts: 18715
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, I've found it much simpler/more portable to do the following:

1. In the servlet init() method, spawn an engine thread to manage the long-running process.

2. In the webapp, initiate the process when requested by posting a request to the engine. Normally, my engines are single-threaded, but it's also possible to spawn sub-threads if parallelization is an advantage.

3. In the same HTTP request as 2, above, return a status-display page that has the META refresh tag. This is a pretty fundamental facility and isn't as likely to get mangled by people's JavaScript settings and the like. When the process is done, simply replace the status-display/timer page with a "Done" page.

Having said that, for something that routinely takes 5 minutes or more, an email notification is not a bad idea.

You can do variations on this theme, of course, if you prefer to offload the long-running process via JMS or something similar.
 
Eric Pascarello
author
Rancher
Posts: 15385
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by D Rog:
[QB] Using Ajax is brilliant idea however it's browser dependent. QB]


What browser do you plan on supporting that does not support Ajax? Just wondering?

Eric
 
D Rog
Ranch Hand
Posts: 472
Linux Objective C Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I use PDA, like sharp zaurus, and it seems not supporting this feature. I do not think that wap or simple mobile phone browsers support it as well. I also use embedded Java browser in my client application. So, it's a real problem for me.
Anyway, since you are very experienced in Ajax technology, I will certainly ask for your help.
 
D Rog
Ranch Hand
Posts: 472
Linux Objective C Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
E-mail notification looks really weird. Your app can not maintain any user profiles and/or e-mails, your app can not deal with any SMTP server. If any of e-mail server has a problem, that a user can get very delayed e-mail or do not get it at all, for example spam filter can fail and consider it as spam or having viruses.
 
Paul Bourdeaux
Ranch Hand
Posts: 783
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jason,

Rather than attacking the bartenders here, you may be better served by taking some of their criticism to heart. One of the main reasons they were trying to steer you away from a standby page is because of the extraordinary amount of time the user would be at this page. I think you would find that this is considered bad UI industry wide.

I am also familiar with the standby pages of travel sites, real estate sites, etc., and Tim does an excellent job of explaining a simple process for doing this. But the longest I have ever waited at Orbitz or Travelocity was less than a minute, even on dial up. Your requirements seem to indicate a much longer time:
  • "There is one step that takes about 5 to 10 minutes of processing time to complete."
  • "However, this process has reduced the time to complete this same task by other means from over two hours to 5-10 minutes. They are quite pleased with this solution"
  • "Well, let's say that I can possibly get the wait time down to 1-2 minutes."

  • I would say that 1-2 minutes is much more manageable. Good luck with your solution.
     
    Ben Souther
    Sheriff
    Posts: 13411
    Firefox Browser Redhat VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    First, sorry for resurrecting a zombie thread but reading this after coming back from vacation prompted me to add another example app to my demo site: http://simple.souther.us/not-so-simple.html

    This example shows one way to handle long running processes by kicking off the process in another thread and returning the user to a status screen that refreshes itself every n seconds - letting the user know that the process is still running and giving them an estimate for completion time.

    The user can leave the page and come back without interrupting the process and can't kick off another process within their current session until the running one is complete.

    This technique has been described several times in this and in the JSP forum in the last few months. Hopefully an example app will help.

    Look for LongRunningProcess.war
     
    D Rog
    Ranch Hand
    Posts: 472
    Linux Objective C Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Exact my point, thank you for illustration, because my sample a bit heavy for this purpose.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!