• Post Reply Bookmark Topic Watch Topic
  • New Topic

Notifying user using JSF after the Asynchronous session bean method completes  RSS feed

 
B Nirvan
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
I have a JSF application which uses a stateless session bean for sending mails to multiple recipients. As the process of sending mails will take time, I have marked the session bean method with @Asynchrnous annotation, so that user can continue using the application without waiting for the send mail process to be complete. I was wondering how (using JSF) would I be able to notify the user when the send mail process is complete.

regards,
Nirvan.
 
Tim Holloway
Bartender
Posts: 18715
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Don't even think about it.

The servlet spec expressly forbids servlet code from spawning threads. Nor should you run synchronously, since you'll starve the HTTP request thread pool in addition to stalling browser response until the process is complete.

When you have a long-running process like this, you need to pass it off to some sort of engine that can handle it out of line. Traditionally, I've done this by setting up a special servlet, where the servlet init() method spawns an engine thread and the GET/POST methods can be used to queue up requests to that thread and to check its progress. This avoids violations of the J2EE spec, since init() doesn't run under a request thread, it runs under the container thread and therefore isn't part of the pool.

Naturally, when you have GET/POST code interacting with an asynchronous process, you need to use synchronized methods and resources.
 
B Nirvan
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim Holloway wrote:Don't even think about it.
The servlet spec expressly forbids servlet code from spawning threads. Nor should you run synchronously, since you'll starve the HTTP request thread pool in addition to stalling browser response until the process is complete.


Thanks for the reply.

I thought that EJB will handle the threads and asynchronous processing. If a stateless session bean (EJB) cannot handle this situation then what is the use of @Asynchronous annotation in SLSB. Also, can it be done by Message Driven Bean instead ?. Or is it that I forgot to mention that I am using EJB and you posted reply assuming I am only using JSF and not EJB.

Regarding handling this using Servlet, are there any resources with you or on the web which will help me understand the whole process more clearly?

regards,
Nirvan.
 
Tim Holloway
Bartender
Posts: 18715
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
EJBs are forbidden from spawning threads as well. However your main problem is that when you want to talk to an EJB from a web page (JSF or otherwise), you have to go through HTTP and HTTP is not an asynchronous protocol. And in particular, HTTP cannot post unsolicited data or messages. You have to make a request to get an HTTP response.

You can use an EJB here, but like I said, for the HTTP part, you need an engine. The engine would then invoke the EJB for the mailing process. When the EJB's mail method completed, you would then change the status variable in the engine which is what a web browser would query to determine when to list the process as having completed.
 
B Nirvan
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim,
If I correctly understand you, I should be using ajax push or http streaming to push the state of the send mail process on the browser. The JSF framework that I am using provides http streaming by use of "Atmosphere Comet Framework". But it is not clear in its guide whether the request thread will be kept active or returned to the thread pool. It does provide a JSF push component which handle publishing of server state. Will this work in my case or should I write my own servlet to handle the process. Thanks a lot for sharing your knowledge.
regards,
Nirvan.
 
Tim Holloway
Bartender
Posts: 18715
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
"Push" is a relative term here. ALL HTTP is request/response. Doesn't matter what language or web technology (Java or anything else) that you use. One Request, once Response, that's the only thing supported. Want another response, send another request. No unsolicited responses are allowed. So the AJAX "push" technology is basically sending a periodic request that can be responded to. There's nothing you can write on the server side that will allow you to send unsolicited "Push", because if there was, it wouldn't be HTTP. Which would probably give you firewall problems. Plus users' web browsers wouldn't know what to do with it.

You should never keep a servlet/JSP thread for yourself and make it wait for long periods of time. HTTP is intended for fast turnaround, and you can swiftly choke your server if the service threads are all tied up waiting for something to happen. JSF is running under the HTTP servlet thread, so that includes long-running actions in JSF code.
 
B Nirvan
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim,
The servlet 3.0 specification has a concept called "Asynchronous Request/Response processing", whose sole purpose is to avoid thread starvation caused by long running requests. I found this in an article at
http://technology.amis.nl/blog/4334/jsf-20-and-servlet-30-specifications-almost-ready-for-take-off
To summarize the author of the article says the following

The asynchronous processing of requests serves several purposes. The underlying issue that is addressed is thread-starvation: asynchronous processing minimizes the number of threads necessary for performing the processing required for the Web Application. This is important in at least two major use cases:

the back end services accessed from the Servlet are slow (perhaps asynchronous themselves) – hanging on to the thread while the back end sits on its response maybe quickly become to costly. The support for asynchronous processing in Servlet 3.0 allows the Servlet to give up the thread and only to resume processing when the results are in

the client (browser) is not satisfied with just the initial response returned upon reception of the request; it is interested in additional results from the server, that should be sent (pushed) to the client as they originate on the server. This would yield an active web client that without end user intervention keeps getting refreshed (a bit like a Chat client, RSS reader or Email client that all get notified and show alerts when new messages arrive). This latter functionality is known as Server Push or Comet-style web applications. They can be achieved today, but most implementations use long running requests that keep server threads occupied and therefore do not scale well.


I think I can use this feature of Servlet.

regards,
Nirvan.
 
Tim Holloway
Bartender
Posts: 18715
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'd have to look more closely at that. However:

First, you'd have to have a container that supports the Servlet 3.0 standard. Tomcat 6 doesn't, and while I don't know offhand about Tomcat 7, it's still not production. Forget about things like WebSphere 6.

Secondly, you'd have to make sure that that feature is actually available. The tone of the article implies that Servlet 3.0 was still being worked out, and not everything that gets discussed while developing a standard actually gets into the standard. Or in the same form as originally expected.

Third, I'm not sure, but some of this just sounds like an assist for the Engine concept I've been referring to all along. Same technique, just more language support. They definitely did mention handing off the long-running work to free up the HTTP thread.

Finally, I get the impression that what they're actually doing is taking advantage of the fact that some browsers can receive incomplete data ("chunking") and doling out the response over an extended period of time. While browsers don't time out as quickly these days as they once did, they do generally still time out, so you can't extend that idea forever. Further, not all clients can handle chunking. If they don't the page won't update at all until ALL data is received (that is, when the job is done).

No matter what they do to the Servlet Standard, however, the real limitation is HTTP. HTTP is not an asynchronous protocol. It doesn't matter whether you're programming in IIS/VB or JEE/JSF or Apache/PHP, the underlying transport is absolutely forbidden by the HTTP spec (RFC) from sending unsolicited data to the client. It couldn't even if it wanted to, since the client doesn' have a listener port to send to. HTTP requests include a "reply port" number, but that port is a temporary opened only for the duration of that particular request/response cycle. It gets closed as soon as the response is complete and a completely different (randomly selected) port is usually going to be used the next time.
 
Tim Holloway
Bartender
Posts: 18715
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Did a little reading. Apparently the Servlet 3.0 spec is intended to provide standardized COMET support.

http://en.wikipedia.org/wiki/Comet_(programming)

This doesn't violate HTTP's request/response constraints, but it does play a little fast and loose with them.

What happens is that the request processor convinces the container to spawn a worker thread (à la Engines) and returns to the pool.

The worker thread posts completion, which causes a new pool thread to be obtained to manage the Response phase of the HTTP Request/Response cycle. The benefit, therefore is that a pool thread isn't required during the long-running process itself.

What requires a little specialization on the client's part is the timing. Because HTTP does forbid unsolicited sending from the server to the client, what actually happens is that the original Request is held open and the "push" is done by adding stuff to the Response. So once the response is complete, nothing more can be sent. Also, if the user has a short timeout on their browser, the whole thing will terminate prematurely.
 
B Nirvan
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim,
A lot of thanks to you for sharing your knowledge. Ultimately the servlet 3 asynchronous processing seems appealing to me and since I am using Glassfish 3 I already have the framework to support it. The only thing that is of some worry is the premature browser timeout if the process takes a considerable time. I will try to find out what the http specs say about that.

One last thing which I am not sure is getting hold of JSF Managed Bean from the SendMail Servlet. The reason I have to get hold of the Managed Bean is that it will contain some state pertaining to the send mail process (like file attachments). Other information will come through the request, and I can get them using request.getParameter. So, the servlet will be using request parameters as well as a session scoped JSF Managed Bean. What could be the best way to get hold of the session scoped JSF Managed Bean in the Servlet.

regards,
Nirvan.
 
Tim Holloway
Bartender
Posts: 18715
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't think there's an absolute number in the HTTP RFC for timeout. Should be a user-adjustable browser setting.
 
Hendy Irawan
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Use PrimeFaces p:push component and you're done.
 
Pat Farrell
Rancher
Posts: 4686
7
Linux Mac OS X VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just have your webapp spawn a daemon thread to do that slow stuff, have your bean send a request. This lets you return quickly to the user.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!