Not sure if this is the right place to collect help.
Scenario: Web client submits a request along with some data to the server. It takes the server quite a while to process the data. The whole process includes 6 steps, needs averagely 50-60 seconds to be done.
Requirement: The web client is able to synchronously monitor the state change of the processing while it is going on and to display the state update during the process, i.e, every time a process step is done successfully, the web page should be refreshed.
Env: J2EE. Applet not considered
Any advice welcome.
-
How to handle this nicely? (20 messages)
- Posted by: Sober Hawk
- Posted on: April 12 2004 09:51 EDT
Threaded Messages (20)
- How to handle this nicely? by Paul Strack on April 12 2004 10:04 EDT
- That's what I have right now by Sober Hawk on April 12 2004 10:36 EDT
-
That's what I have right now by Paul Strack on April 13 2004 12:05 EDT
-
Thanks a lot for your advice by Sober Hawk on April 13 2004 09:07 EDT
-
Thanks a lot for your advice by Paul Strack on April 13 2004 10:41 EDT
-
unique state object and singleton servlet by Sober Hawk on April 13 2004 01:06 EDT
-
unique state object and singleton servlet by Paul Strack on April 14 2004 02:08 EDT
-
No META-REFRESH is used any more in my solution by Sober Hawk on April 14 2004 09:43 EDT
-
Agree with wait()/notify() thread solution by Herk Pain on April 15 2004 02:49 EDT
- Is wait()/notify() rarely used in web application? by Sober Hawk on April 15 2004 09:33 EDT
-
No META-REFRESH is used any more in my solution by Paul Strack on April 15 2004 09:29 EDT
-
No META-REFRESH is used any more in my solution by Sober Hawk on April 15 2004 10:14 EDT
-
No META-REFRESH is used any more in my solution by Paul Strack on April 18 2004 05:33 EDT
-
Need some time by Sober Hawk on April 23 2004 02:37 EDT
-
Need some time by Paul Strack on April 23 2004 02:40 EDT
- messageing is so complicated by Herk Pain on April 27 2004 03:38 EDT
-
Am I right? by Sober Hawk on May 04 2004 03:23 EDT
-
Am I right? by Paul Strack on May 04 2004 05:52 EDT
- You said it by Sober Hawk on May 05 2004 09:55 EDT
-
Am I right? by Paul Strack on May 04 2004 05:52 EDT
-
Need some time by Paul Strack on April 23 2004 02:40 EDT
-
Need some time by Sober Hawk on April 23 2004 02:37 EDT
-
No META-REFRESH is used any more in my solution by Paul Strack on April 18 2004 05:33 EDT
-
No META-REFRESH is used any more in my solution by Sober Hawk on April 15 2004 10:14 EDT
-
Agree with wait()/notify() thread solution by Herk Pain on April 15 2004 02:49 EDT
-
No META-REFRESH is used any more in my solution by Sober Hawk on April 14 2004 09:43 EDT
-
unique state object and singleton servlet by Paul Strack on April 14 2004 02:08 EDT
-
unique state object and singleton servlet by Sober Hawk on April 13 2004 01:06 EDT
-
Thanks a lot for your advice by Paul Strack on April 13 2004 10:41 EDT
-
Thanks a lot for your advice by Sober Hawk on April 13 2004 09:07 EDT
-
That's what I have right now by Paul Strack on April 13 2004 12:05 EDT
- That's what I have right now by Sober Hawk on April 12 2004 10:36 EDT
- How to handle this nicely? by Senthil Chinnaiyan on April 12 2004 10:16 EDT
-
How to handle this nicely?[ Go to top ]
- Posted by: Paul Strack
- Posted on: April 12 2004 10:04 EDT
- in response to Sober Hawk
1) Run the server-process in a separate thread, with status updates in a Status object. When you start the server process, store a reference to the Status object in the HttpSession.
2) After starting the server-process, send the client to a Please-Wait.jsp, which refreshes every 5 seconds: <meta http-equiv="refresh" content="5">
3) Whenever the Please-Wait.jsp is invoked, it checks the Status object in the session and displays the updated status.
4) When the Status gets to "complete", the Please-Wait.jsp redirects to a Results.jsp page with the final results.
This is not completely synchronous, but is probably close enough for your purposes. -
That's what I have right now[ Go to top ]
- Posted by: Sober Hawk
- Posted on: April 12 2004 10:36 EDT
- in response to Paul Strack
Thanks a lot for your response. My current implementation is exactly the same as you suggested. However, I am thinking a "push" way, which would be closer to ideal.
How about this:
1.instantiates a data object, bind it to JNDI, this object is ready to hold the processing states and result.
2.Page1 submits the request to Servlet1, which invokes a method to take care of real business process (MDB works here).
3.MDB will update the data object every time it finishes a step.
4.Servlet1 use a loop to keep querying the data object until one step is done. Response forwards to Page2. (Destroy this servlet instance manually?)
5. Page2 open a hidden Page3 in its "onLoad". Page3 submits to Servlet1 again immediately, while Page2 stays still to waiting for next response from Servlet1.
6. Go to step-4 if the process is not completed, else redirects to next Action once process is completed.
I would say this is a half-pull-half-push idea, but at least we make it refresh-every-step. Is it doable? -
That's what I have right now[ Go to top ]
- Posted by: Paul Strack
- Posted on: April 13 2004 00:05 EDT
- in response to Sober Hawk
Before you go with the server-push model, bear in mind that this will require a continuous TCP/IP connection between the client and the server for the entire operation, which will have a major impact on scaleability. It will put an upper limit on the number of concurrent client connections.
If you do go with a server-push model (maybe because timing is very important), I suggest you use a wait/notify thread model instead of a continuous loop. The continuous loop will require some sort of delay in order not to saturate your CPU, and is really no better than the refresh approach; it just pushes the refresh to the server rather than the client. -
Thanks a lot for your advice[ Go to top ]
- Posted by: Sober Hawk
- Posted on: April 13 2004 09:07 EDT
- in response to Paul Strack
In my application, there is not much of concurrent access to the server, say, 15 users maximum. It is safe to hold the connnetion open for 10 seconds, isn't it?
You suggestion leads me to further questions: Is there any callback method available for servlets? How could I notify a servlet instance in the container?
Besides, I googled a "push" framework called "Pushlet", I read some articles about it, still not quite buy it. What do you think about it? -
Thanks a lot for your advice[ Go to top ]
- Posted by: Paul Strack
- Posted on: April 13 2004 10:41 EDT
- in response to Sober Hawk
Given your small number of users, the concern over the max number of TCP/IP connections is probably a non-issue.
There is no callback mechanism for servlets. When I said "wait/notify", I meant using low-level thread wait() and notify() methods. You could write code something like this in your Status object:
class Status ...
String synchronized getStatus() {
return this.status;
}
String synchronized isDone() {
return this.status.equals("Done");
}
String synchronized waitForUpdate() {
if (!isDone()) {
wait(); // Thread sleeps until notify()
}
}
String synchronized setStatus(String newStatus) {
this.status = newStatus;
notifyAll(); // Wake up waiting threads
}
}
In your Serlvet:
while(!status.isDone()) {
output(status.getStatus());
status.waitForUpdate(); // Sleep until update
}
// Redirect to Result.jsp
In your process:
// Do step one ...
status.setStatus("Step 1"); // Wakes up servlet
// Do step two ...
status.setStatus("Step 2"); // Wakes up servlet
// Do other steps ...
// Finish up ...
status.setStatus("Done"); // Servlet finishes work
This will only function correctly if your servlet and the process are running the same JVM and have access to the exact same Status object (which means the MDB approach won't work).
You can also add a timeout into the wait() method in case the process hangs or crashes.
I thought of another major issue with this approach, though. Servlets are singletons, so with the push approach, your servlet will be dedicated to servicing a single client. You will probably need to create a GenericServlet with custom HTTP processing logic, which will probably be server-specific. -
unique state object and singleton servlet[ Go to top ]
- Posted by: Sober Hawk
- Posted on: April 13 2004 13:06 EDT
- in response to Paul Strack
Can't afford the servlet and process logic in the same JVM, so I figure I have to live with loop-querying.
Binding the state object to JNDI is to guarantee that state object is unique in the entire context.
HttpServlet is singleton, but it is able to deal with requests concurrently, am I right? First time the request is submit to the servlet, a correlation ID could be generated and returned with the response for future querying. -
unique state object and singleton servlet[ Go to top ]
- Posted by: Paul Strack
- Posted on: April 14 2004 02:08 EDT
- in response to Sober Hawk
HttpServlet is singleton, but it is able to deal with requests concurrently, am I right? First time the request is submit to the servlet, a correlation ID could be generated and returned with the response for future querying.
You are right here. I had a brain-hiccup. I was thinking about the issue of synchronizing on the servlet object itself (which you should not need to do).Can't afford the servlet and process logic in the same JVM, so I figure I have to live with loop-querying. Binding the state object to JNDI is to guarantee that state object is unique in the entire context.
If you are going with loop-querying, you may as well stick with the meta-refresh. The loop-querying effectively performs the same refresh operation from servlet-to-JNDI-bound-object rather than browser-to-servlet, and therefore won't be any more timely. Unless you set up some kind of callback object, you won't be any better off.
If you do set up a callback object, it will have to be bound to thread processing the servlet, not the servlet itself (though you may be able to do some sort of clever trick using the servlet session). No matter what you do, this is going to be an ugly mess.
Ask yourself if you really need this. The refresh mechanism is going to give the users messages accurate to within 5 or 6 seconds. The server-push mechanism is going to be a huge amount of work, and will at best increase the accuracy to 1 second or so (given the latency from browser-to-servlet, servlet-to-MDB). -
No META-REFRESH is used any more in my solution[ Go to top ]
- Posted by: Sober Hawk
- Posted on: April 14 2004 09:43 EDT
- in response to Paul Strack
In my solution posted before:
4.Servlet1 use a loop to keep querying the data object until one step is done. Response forwards to Page2. (Destroy this servlet instance manually?)
5. Page2 open a hidden Page3 in its "onLoad". Page3 submits to Servlet1 again immediately, while Page2 stays still to waiting for next response from Servlet1.
The hidden Page3 actually plays the role of submit-to-refresh. :)
META-REFRESH is good enough for now, which is running pretty satisfying. I just seek more backup options here in case more critical requirements come in. -
Agree with wait()/notify() thread solution[ Go to top ]
- Posted by: Herk Pain
- Posted on: April 15 2004 02:49 EDT
- in response to Sober Hawk
I agree with thread's wait()/notify() solution. According to this way, you just put the "Meta-Reflesh" work to the server rather than deal it manually.
That will make the client to get response as soon as the state been changed,rather than aways checking the state in the server side by himself.
That's a pure "push" solution.
But i have no idea about the topic "Can't afford the servlet and process logic in the same JVM". Will this affect the performance or the security?
and "more backup options here in case more critical requirements come in"
such as ??? -
Is wait()/notify() rarely used in web application?[ Go to top ]
- Posted by: Sober Hawk
- Posted on: April 15 2004 09:33 EDT
- in response to Herk Pain
Notify/wait solution only works in one JVM, while the process logic currently is in MDBs. Although I am not very clear about how application servers handle MDB in JVM perspective. assumption of servlet and MDB being in the same JVM is kinda risk.
Such as....to detecting the exact time each step is completed. :) -
No META-REFRESH is used any more in my solution[ Go to top ]
- Posted by: Paul Strack
- Posted on: April 15 2004 09:29 EDT
- in response to Sober Hawk
4. Servlet1 use a loop to keep querying the data object until one step is done. Response forwards to Page2. (Destroy this servlet instance manually?)
This idea has merit, and would help scaleability a lot. If you use servlet push as a mechanism to push out a refresh page to the browser, it cuts down on the amount of time the TCP/IP connection is open. With this approach, the connection is open until a given step is complete. Then you get a forced refresh, and a new connection until the next step is complete.
5. Page2 open a hidden Page3 in its "onLoad". Page3 submits to Servlet1 again immediately, while Page2 stays still to waiting for next response from Servlet1.
You should not need to destroy the servlet after the force refresh. Just let the doGet/doPost method terminate normally.
I still think you need some sort of wait()/notify() mechanism between the servlet and the MDB processing for this to be really effective, though. -
No META-REFRESH is used any more in my solution[ Go to top ]
- Posted by: Sober Hawk
- Posted on: April 15 2004 10:14 EDT
- in response to Paul Strack
I figure now the question simplifies to:
web browser <-> servlet <-> process logic
or
web browser <-> servlet -> state object <- process logic
The mechanism wait/notify or observer/observable, I think it hard to implement between J2EE layers and containers (in case the web layer deployed in a different node other than the process logic resides).
Bidirectional web service would solve it, if both the web application and EJBs are configed as web services, right? -
No META-REFRESH is used any more in my solution[ Go to top ]
- Posted by: Paul Strack
- Posted on: April 18 2004 17:33 EDT
- in response to Sober Hawk
Sorry to take so long to get back to you. I have been busy.
Here are my latest thoughts. The big issue seems to be how to manage the connection from servlet to process logic. If you are planning on using MDB for the process logic, the simplest way to manage the call-backs might be messaging.
Here is how it might work:
1) Create a StatusTracker object in the Servlet. Store it in the session so that it persists in a user-specific way during refreshes. Have the tracker initiate a connection to the process logic by sending a message with a correlation ID for replies, and then wait for a reply messages in a reply queue with the given correlation ID.
2) The process logic is launched in an MDB by the incoming message. As it completes each step of the process, it can send "Step Completed" messages to the reply queue as it completes each step.
3) When the StatusTracker in the servlet layer receives reply messages, it can force a browser refresh using the server-push suggested earlier by Senthil. Then the tracker can go back to waiting for new replies. This continues until the process is complete.
So long as the correlation IDs are unique to each user session, the servlet can properly separate messages for each process. You can add in timeouts and automatic refreshes to deal with browser timeouts and process logic failures.
An alternative to correlation ID is to use a temporary reply-to queue, and make the queue unique to the session rather than the ID. I am not sure which option would be more effecient; it would depend on your messaging system, and I am no expert on messaging anyway.
Messaging is probably the best distributed approximation of wait/notify or event systems, and I am embarassed that I didn't think of it earlier. -
Need some time[ Go to top ]
- Posted by: Sober Hawk
- Posted on: April 23 2004 14:37 EDT
- in response to Paul Strack
Need some time to look into Messaging technologies to understand your solution. :P -
Need some time[ Go to top ]
- Posted by: Paul Strack
- Posted on: April 23 2004 14:40 EDT
- in response to Sober Hawk
No worries. It is a pretty interesting thought-exercise. -
messageing is so complicated[ Go to top ]
- Posted by: Herk Pain
- Posted on: April 27 2004 03:38 EDT
- in response to Paul Strack
I've never thought Message mechanism to be so complicated. -
Am I right?[ Go to top ]
- Posted by: Sober Hawk
- Posted on: May 04 2004 15:23 EDT
- in response to Paul Strack
After some time on JMS, I think I got most of the picture of MESSAGING like the following:
1. After the servlet submits the request to the process logic and gets a correlation ID back, creates a StatusTracker object with this ID and the session as the MessageListener of PROCESSING QUEUE, store it in the session.
2. Once a update message puts into the PROCESSING QUEUE by the MDB, the StatusTracker's ONMESSAGE is invoked, which will set some info in session, such as CORRELATIONID = 1234 STEP = 2, indicating the processing of 1234 is in the step No.2 (current step)
3. The servlet render the response as any steps prior to the current step marked as "finished" and the current step as "processing", send it back.
4. Page updated, another request to refresh sends to the servlet if the whole process is not done, go to 3; Otherwise, remove the StatusTracker from session, redirect to next page.
I have to stick to the approach of "hold the connection to the servlet open during each step", because there is no way to force a browser refresh. Multipart is only supported by Netscape. -
Am I right?[ Go to top ]
- Posted by: Paul Strack
- Posted on: May 04 2004 17:52 EDT
- in response to Sober Hawk
This sounds good to. I still think it is way more trouble than it is worth, but the solution you propose would probably have decent throughput and reasonable scaleability. -
You said it[ Go to top ]
- Posted by: Sober Hawk
- Posted on: May 05 2004 09:55 EDT
- in response to Paul Strack
You are right. Unless the client is dying to have this "push" feature, I won't implement it in this way. As you said, a thought-practice. :) -
How to handle this nicely?[ Go to top ]
- Posted by: Senthil Chinnaiyan
- Posted on: April 12 2004 10:16 EDT
- in response to Sober Hawk
I think you can use any of the 2 techniques.
1. Client Pull:
In the client pull, you can set your html page refresh time to some seconds. After the dely, the browser will automatically refresh the page.
http://pub.spccatv.com.cn/~rison/servlet/ch05_06.htm
Server Push:
You can use MultiPartResponse to achive the Server Push in Servlets. You can see the tutorial here: http://pub.spccatv.com.cn/~rison/servlet/ch06_03.htm
Hope this helps
Senthil.