Re: struts & generating progress messages

2001-01-05 Thread Craig R. McClanahan

Kitching Simon wrote:

> Hi,
>
> I currently have a model-1 web application
> ie in which the .jsp pages are responsible
> for invoking the business logic.
>
> I am planning to move the webapp to struts,
> for all the obvious and traditional reasons.
> However, there is one nice feature of the
> current code that I can't see how to perform
> inside an MVC framework like struts:
>
> On submitting a particular form, there is a
> sequence of 4 operations to perform, each of
> which takes somewhere between 5 and 30
> seconds to perform. Currently, what is done is
> to generate an almost complete HTML page,
> and force it to be flushed to the browser; as
> each long-duration step starts and completes,
> a fragment of page containing CSS-positioned
> html/ javascript is flushed to the browser. The
> effect is very nice - a list of the steps appears
> on the screen, an hourglass appears next to
> each step as it starts, and a tick or error message
> appears next to each one as it completes.
>
> Does anyone have any idea how to generate the
> same sort of effect (essentially alternating between
> business logic and presentation output) in struts?
>

As you've gathered, a model 2 approach is not amenable to using flushing to show
progress.  A strategy that might work better is something like this, in the
initial Action that starts all of the work:

* Fire off a background thread to do the long-duration work.
* Give this thread access to the user's session, so it can
  update a status variable when it is done
* Return a "work in progress .. click here to check for completion"
  page, which returns to the same action
* When the action is entered, it will check to see that a
  background thread is currently running, so it will display
  another "work in progress" page, or the final results, depending
  on what's been done so far.
* When the background thread completes its work, it updates
  the final status and exits.

Variations on the theme:
* The status variable need not be binary -- for a multiple
  stage background operation, it could be a state identifier,
  or a percentage completed, or something like that, so you
  can be more descriptive on the "in progress" page.
* You might want to generate a meta refresh tag on the
  "in progress" page, so that the user doesn't have to remember
  to hit the link.

>
> Thanks in advance,
>
> Simon

Craig





RE: struts & generating progress messages

2001-01-05 Thread Kitching Simon



> -Original Message-
> From: Craig R. McClanahan [SMTP:[EMAIL PROTECTED]]
> Sent: Friday, January 05, 2001 8:28 PM
> To:   [EMAIL PROTECTED]
> Subject:      Re: struts & generating progress messages
> 
> Kitching Simon wrote:
> 
> > Hi,
> >
> > I currently have a model-1 web application
> > ie in which the .jsp pages are responsible
> > for invoking the business logic.
> >
> > I am planning to move the webapp to struts,
> > for all the obvious and traditional reasons.
> > However, there is one nice feature of the
> > current code that I can't see how to perform
> > inside an MVC framework like struts:
> >
> > On submitting a particular form, there is a
> > sequence of 4 operations to perform, each of
> > which takes somewhere between 5 and 30
> > seconds to perform. Currently, what is done is
> > to generate an almost complete HTML page,
> > and force it to be flushed to the browser; as
> > each long-duration step starts and completes,
> > a fragment of page containing CSS-positioned
> > html/ javascript is flushed to the browser. The
> > effect is very nice - a list of the steps appears
> > on the screen, an hourglass appears next to
> > each step as it starts, and a tick or error message
> > appears next to each one as it completes.
> >
> > Does anyone have any idea how to generate the
> > same sort of effect (essentially alternating between
> > business logic and presentation output) in struts?
> >
> 
> As you've gathered, a model 2 approach is not amenable to using flushing
> to show
> progress.  A strategy that might work better is something like this, in
> the
> initial Action that starts all of the work:
> 
> * Fire off a background thread to do the long-duration work.
> * Give this thread access to the user's session, so it can
>   update a status variable when it is done
> * Return a "work in progress .. click here to check for completion"
>   page, which returns to the same action
> * When the action is entered, it will check to see that a
>   background thread is currently running, so it will display
>   another "work in progress" page, or the final results, depending
>   on what's been done so far.
> * When the background thread completes its work, it updates
>   the final status and exits.
> 
> Variations on the theme:
> * The status variable need not be binary -- for a multiple
>   stage background operation, it could be a state identifier,
>   or a percentage completed, or something like that, so you
>   can be more descriptive on the "in progress" page.
> * You might want to generate a meta refresh tag on the
>   "in progress" page, so that the user doesn't have to remember
>   to hit the link.
> 
> >
> > Thanks in advance,
> >
> > Simon
> 
> Craig
> 
[Kitching Simon]  
Thanks very much for your reply!
I don't like the link or refresh idea much,
but your suggestion of a "background thread" 
triggered another idea for me...

How about the action starts a threaded business
class, then forwards to the presentation page.

This business class has methods waitForStep1(),
waitForStep2(), etc, which when called do
a wait() on a member variable. As the thread
completes each step, it calls notify() on the
corresponding member variable.

The presentation page generates & flushes
output, then calls waitForStep1(), thereby
blocking. When the function returns, it outputs
the results, and calls waitForStep2(), etc.

In effect, we have an action "piping" results
to a presentation page that is running in
parallel with it.

Do you think this will work? And do you think
that this might be worth making part of the
framework? It sounds quite tidy to me

Thanks again,

Simon



Re: struts & generating progress messages

2001-01-05 Thread Jim Newsham

Kitching Simon wrote:

> Hi,
>
> I currently have a model-1 web application
> ie in which the .jsp pages are responsible
> for invoking the business logic.
>
> I am planning to move the webapp to struts,
> for all the obvious and traditional reasons.
> However, there is one nice feature of the
> current code that I can't see how to perform
> inside an MVC framework like struts:
>
> On submitting a particular form, there is a
> sequence of 4 operations to perform, each of
> which takes somewhere between 5 and 30
> seconds to perform. Currently, what is done is
> to generate an almost complete HTML page,
> and force it to be flushed to the browser; as
> each long-duration step starts and completes,
> a fragment of page containing CSS-positioned
> html/ javascript is flushed to the browser. The
> effect is very nice - a list of the steps appears
> on the screen, an hourglass appears next to
> each step as it starts, and a tick or error message
> appears next to each one as it completes.
>
> Does anyone have any idea how to generate the
> same sort of effect (essentially alternating between
> business logic and presentation output) in struts?
>
> Thanks in advance,
>
> Simon

How about creating a separate thread to perform the tasks, and
forwarding immediately to the jsp page in your main thread.  Create an
object which can wait for the tasks to complete, and attach that object
to the request before forwarding.

As an example, create a TaskMonitor (sample code below; this code is
untested, and I usually don't program threads so don't trust it to work
without some scrutiny).

Task thread.  Create a thread to perform your tasks and give it a
reference to this monitor.  Each time a task is complete, call
monitor.taskComplete(taskid).

Main thread.  Attach monitor to request.  Forward to jsp.  The jsp can
call monitor.waitForTask(taskid) for each task in sequence.

public class TaskMonitor {

  boolean[] taskComplete;

  public TaskMonitor(int taskCount) {
taskComplete = new boolean[taskCount];
  }

  public synchronized waitForTask(int taskid) {
if (taskid < 0 || taskid >= taskComplete.length
|| taskComplete[taskid]) return;
while(true) {
  try {
wait();
  }
  catch(InterruptedException ie) { }
  if (taskComplete[taskid]) return;
}
  }

  public synchronized taskComplete(int taskid) {
if (taskid > 0 && taskid < taskComplete.length) {
  taskComplete[taskid] = true;
  notifyAll();
}
  }

}




RE: struts & generating progress messages

2001-01-05 Thread Kitching Simon

Thanks, Jim!

A reply in about 5 minutes, complete with pseudo-code -
I'm impressed :-)

As you probably saw from my reply to Craig, a similar
idea occurred to me - after the idea of creating a separate
thread to perform business processing was suggested.

I like your idea of a generic TaskMonitor "synchronizer" 
object that essentially mediates between the action and 
the presentation slightly better than my idea of building
it into the class doing the actions too - the TaskMonitor
could even be a standard utility class, with it's array
of Booleans (if I understand your code right). All the
action & page need to agree on is a set of constants
(probably best defined in an interface) to use as the
task ids...

Anyway, plenty to ponder.

Cheers & thanks again,

Simon

> -Original Message-
> From: Jim Newsham [SMTP:[EMAIL PROTECTED]]
> Sent: Friday, January 05, 2001 8:36 PM
> To:   [EMAIL PROTECTED]
> Subject:  Re: struts & generating progress messages
> 
> Kitching Simon wrote:
> 
> > Hi,
> >
> > I currently have a model-1 web application
> > ie in which the .jsp pages are responsible
> > for invoking the business logic.
> >
> > I am planning to move the webapp to struts,
> > for all the obvious and traditional reasons.
> > However, there is one nice feature of the
> > current code that I can't see how to perform
> > inside an MVC framework like struts:
> >
> > On submitting a particular form, there is a
> > sequence of 4 operations to perform, each of
> > which takes somewhere between 5 and 30
> > seconds to perform. Currently, what is done is
> > to generate an almost complete HTML page,
> > and force it to be flushed to the browser; as
> > each long-duration step starts and completes,
> > a fragment of page containing CSS-positioned
> > html/ javascript is flushed to the browser. The
> > effect is very nice - a list of the steps appears
> > on the screen, an hourglass appears next to
> > each step as it starts, and a tick or error message
> > appears next to each one as it completes.
> >
> > Does anyone have any idea how to generate the
> > same sort of effect (essentially alternating between
> > business logic and presentation output) in struts?
> >
> > Thanks in advance,
> >
> > Simon
> 
> How about creating a separate thread to perform the tasks, and
> forwarding immediately to the jsp page in your main thread.  Create an
> object which can wait for the tasks to complete, and attach that object
> to the request before forwarding.
> 
> As an example, create a TaskMonitor (sample code below; this code is
> untested, and I usually don't program threads so don't trust it to work
> without some scrutiny).
> 
> Task thread.  Create a thread to perform your tasks and give it a
> reference to this monitor.  Each time a task is complete, call
> monitor.taskComplete(taskid).
> 
> Main thread.  Attach monitor to request.  Forward to jsp.  The jsp can
> call monitor.waitForTask(taskid) for each task in sequence.
> 
> public class TaskMonitor {
> 
>   boolean[] taskComplete;
> 
>   public TaskMonitor(int taskCount) {
> taskComplete = new boolean[taskCount];
>   }
> 
>   public synchronized waitForTask(int taskid) {
> if (taskid < 0 || taskid >= taskComplete.length
> || taskComplete[taskid]) return;
> while(true) {
>   try {
> wait();
>   }
>   catch(InterruptedException ie) { }
>   if (taskComplete[taskid]) return;
> }
>   }
> 
>   public synchronized taskComplete(int taskid) {
> if (taskid > 0 && taskid < taskComplete.length) {
>   taskComplete[taskid] = true;
>   notifyAll();
> }
>   }
> 
> }