Win a copy of Head First Agile this week in the Agile forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Can I update my view by running 2 concurrent processes?  RSS feed

 
Rob Micah
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What I am attempting to do is execute a long-running process and iterate over it multiple times. I'd like my page to update with the progress in between each run. What I have tried so far is using a HttpSessionAttributeListener and executing my long-running process from there and using my ViewScoped bean along with richfaces a4j:poll to update my page. Unfortunately no matter what method I try with a listener, the completion of the Partial JSF lifecycle always blocks until my listener method is through processing. So we go from start to finish with no updates in between.

Tomorrow I am going to try another idea I have which is to just have my view re-submit itself and try updates that way. But before I go that route I wanted to see if there was a way to do what I was originally attempting and I'm not just missing something. Any help appreciated.
 
Tim Holloway
Bartender
Posts: 18720
72
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Once you make an HTTP request, the client goes on hold, the server processes and returns the response and the client processes the results and that's it. You can't send a request and get periodic status updates from it.

So to do what you want, the a4j:poll tag needs to invoke a server function that checks the status of the long-running process and immediately returns the status. The poll cannot talk to the long-running process directly, but must instead use some sort of shared object that the long-running process can update and the poll action method can check (usually this is a synchronized object).

Please note that no J2EE request handler can spawn a thread either directly or via listener mechanisms. Anything that spawns a child thread under a request processor thread is not only a violation of the J2EE standard, but may crash your server at unpredictable times. I don't think a session attribute listener is a safe place to spawn from. Consider a centralized engine that is spawned under the ServletContext listener at startup. The HTTP requests can then queue up work by submitting requests to this engine and can also query this engine for process status.

The engine can be very simple, running a single thread that all the requesters queue up against serially or it can in turn spawn child threads and run as many parallel requests as you want.
 
Rob Micah
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim, do you think using a context listener would have a different result than the listener I'm using? I know of the threading limitations of the J2EE containers. Using an HttpSessionAttributeListener was my attempt to get around that but it didn't work. There is nothing that I could see that documents this blocking behavior on the listeners but I don't know if using a different listener would have different results. What I'm attempting to do is begin a process from a request and check the status of it. So my second idea may work but what I will have to do is have an ajax call resubmit the page after every request finishes. I'm thinking some kind of logical check that then calls an ajax listener method. I can't say I'm crazy about that idea but I really can't think of another approach.
 
Tim Holloway
Bartender
Posts: 18720
72
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The ServletContextListener is the place where people generally do such things. I'm not sure whose thread the SessionAttributeListener is running on, so it might not be safe for it to spawn threads. There's also the matter of context, since the SessionAttributeListener is working with HttpSession objects and therefore the data basis for its operations is subject to being "destroyed" (or at least disconnected from the rest of the system) at unpredictable times.

The a4j:poll tag submits periodic AJAX requests that fire a corresponding backing bean action method (assuming that you code an "action=" on the tag). That is the method that should query the backend process and save the process status as a backing bean property (or properties) that can then be displayed via the reRender feature of the tag. The backing bean properties might be as simple as a done/not done indicator or some sort of progress indication message(s) ("phase 1, 17% completed") or whatever amuses you. You can also bind a boolean property to the poll tag's "enabled" property so that it will cease polling once the operation has completed.

Although the docs say that the action method must return an Object, I think that this is actually sloppy cut-and-paste documentation. In Richfaces 3, I always have my AJAX actions returning void, since they don't navigate the way that non-AJAX actions do.

You'll probably also want to specify ajaxSingle="true" on the poll tag. Most of my AJAX operations do, since otherwise they don't work if other controls in the form contain invalid values.
 
Rob Micah
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just to be clear, are you talking about creating a new thread in the ServletContextListener? Or just normal processing?
 
Tim Holloway
Bartender
Posts: 18720
72
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes. Spawn the master engine thread in the ServletContextListener's contextInitialized(ServletContextEvent sce) method. You can store the engine object itself in the servletContext via "setAttribute", and the backing beans can then locate it by rooting out the HttpServletRequest object from the FacesContext getServletContext() method and doing a "getAttribute"

The contextInitialized method doesn't run under a request handler thread, it runs under a permanent internal server thread which can safely spawn children such as your engine.
 
Rob Micah
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim, I did some digging around in the J2EE specifications and found something interesting. I'm curious to know if you've ever seen this or what you think of it. I'm going to try it out.

https://jcp.org/aboutJava/communityprocess/final/jsr236/index.html

The example is on page 3-2.
 
Tim Holloway
Bartender
Posts: 18720
72
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Interesting. Don't expect it to work in Tomcat, since Tomcat doesn't implement full JEE. Since it's a recent spec, even the full-stack servers may not have it implemented yet.
 
Rob Micah
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yeah, looking at it closer I can see this is only available in Java 7. Looks like the new version of Glassfish uses it but not sure about the others or when.
 
Don't get me started about those stupid light bulbs.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!