I have created a component to hide all the gubbins that I mentioned
earlier. All you need to do is create a more beautiful progress bar (my css
skills aren't great). I have created a simple page which adds 3
progressRunnableLinks on a page. Each fires a task that takes 10 seconds,
updating it's percentage complete as it goes.

1. Download the code from here
http://dl.dropbox.com/u/63354/tapestry-progress.zip
2. run "mvn jetty:run"
3. Go to http://localhost:8080/tapestry/progress

Cheers,
Lance.

Interesting bits of code:

AppModule.java
----------------------

    public ProgressRunnableManager buildProgressRunnableManager() {
        return new ProgressRunnableManagerImpl(20);
    }


Progress.tml
------------------
    <t:progressRunnableLink zoneId="zone1" linkText="start 1"
progressRunnable="progressRunnable" pollDelayMillis="500" />
    <t:progressRunnableLink zoneId="zone2" linkText="start 2"
progressRunnable="progressRunnable" pollDelayMillis="500" />
    <t:progressRunnableLink zoneId="zone3" linkText="start 3"
progressRunnable="progressRunnable" pollDelayMillis="500" />

Progress.java (page class)
--------------------

public class Progress {
    public ProgressRunnable getProgressRunnable() {
        return new AbstractProgressRunnable() {
            public void run() {
                for (int i = 1; i <= 10; ++i) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    setProgressPercentage(i * 10);
                }
            }
        };
    }
}

ProgressRunnableLink.java (component)
----------------------------------------------------------
@Import (library="zonemanager.js")
public class ProgressRunnableLink {
    @Inject
    private ProgressRunnableManager manager;

    @Inject
    private AjaxResponseRenderer ajaxRenderer;

    @Inject
    private ComponentResources resources;

    @Inject
    private JavaScriptSupport jsSupport;

    @Parameter
    private Integer pollDelayMillis;

    @Parameter(defaultPrefix="literal", required=true)
    @Property
    private String linkText;

    @Parameter(defaultPrefix="literal", required=true)
    @Property
    private String zoneId;

    @Parameter(allowNull=false)
    private ProgressRunnable progressRunnable;

    @Property
    private Double progressPercentage;

    @Property
    private Exception exception;

    @InjectComponent
    private Zone progressZone;

    @OnEvent("startRunnable")
    Block startTask() {
        String taskId = manager.submit(progressRunnable);
        progressPercentage = 0D;
        doPoll(taskId);
        return progressZone.getBody();
    }

    @OnEvent("updateProgress")
    Block updateProgress(String taskId) {
        try {
            progressPercentage = manager.getProgressPercentage(taskId);
            if (progressPercentage < 100D) {
                doPoll(taskId);
            }
        } catch (Exception e) {
            exception = e;
        }
        return progressZone.getBody();
    }

    void doPoll(String taskId) {
        Link link = resources.createEventLink("updateProgress", taskId);
        final String url = link.toAbsoluteURI();
        ajaxRenderer.addCallback(new JavaScriptCallback() {
            public void run(JavaScriptSupport jsSupport) {
                if (pollDelayMillis == null) {
                    jsSupport.addScript("Tapestry.activateZone('%s',
'%s');", zoneId, url);
                } else {

jsSupport.addScript("setTimeout(\"Tapestry.activateZone('%s', '%s');\",
%s);", zoneId, url, pollDelayMillis);
                }
            }
        });
    }
}






On 3 January 2012 10:34, Lance Java <lance.j...@googlemail.com> wrote:

> There are a couple of approaches to do this, since tapestry does not
> support ajax push (aka reverse ajax) out-of-the box, a simple solution
> would be to have the client poll the server for the current percentage
> complete.
>
> In order to display a progress bar to the client, you must do the actual
> work for the task on a separate thread to the Ajax request thread. It is
> probably best to have a singleton ExecutorService (using
> java.util.concurrent.Executors.newFixedThreadPool(threadCount) or similar)
>
> The Ajax request thread should:
> 1. Create a runnable and give it a unique taskId
> 2. Put the runnable in a serverside map keyed on taskId (map could be a
> singleton or perhaps stored in each user's session)
>
> 3. Call executorService.submit(myRunnable)
> 4. Use the AjaxResponseRenderer to fire the "updateProgressBar" event
> passing the taskId in the context
> 5. Return the progress bar zone's getBody() with a percentageComplete of 0
>
> Your runnable would be something like
>
> public class MyWorker implements Runnable {
>    private int taskId;
>    private ConcurrentMap workers;
>    private AtomicInteger percentComplete = new AtomicInteger(0);
>    public MyWorker(ConcurrentMap workers, String taskId) {
>       this.workers = workers;
>       this.taskId = taskId;
>    }
>    public int getPercentComplete() {
>       return percentComplete.get();
>    }
>    public void run() {
>       try {
>          doSomeWork();
>          percentComplete.set(10);
>          doSomeMoreWork();
>          percentComplete.set(50);
>          doEvenMoreWork();
>          percentComplete.set(100);
>       } finally {
>          workers.remove(taskId);
>       }
>    }
> }
>
>
> In your serverside event handler [onUpdateProgressBar(String taskId)]
> lookup the runnable in the map and call getPercentComplete() then return
> the updated progress zone's getBody(). If the percentageComplete() is less
> than 100, use the AjaxResponseRenderer to fire the "updateProgressBar"
> event again.
>
> @see
> http://tawus.wordpress.com/2011/10/01/tapestry-5-3-new-features-part-2/for 
> AjaxResponseRenderer usage
>
> Cheers,
> Lance.
>
>
> On Monday, 26 December 2011, angelochen <angelochen...@yahoo.com.hk>
> wrote:
> > Hi,
> >
> > would like to have some ideas about how to implement following:
> >
> > I have a t:grid, every row has a link, when click, it will do a process
> > which might take a while, once done, it will either disable the link or
> > re-display the link depending on the result. I'd like that, when clicked,
> > the link is replaced with a progress bar in place, until it is done. any
> > hints? Thanks,
> >
> > Angelo
> >
> > --
> > View this message in context:
> http://tapestry.1045711.n5.nabble.com/T5-progress-bar-in-a-grid-tp5101565p5101565.html
> > Sent from the Tapestry - User mailing list archive at Nabble.com.
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
> > For additional commands, e-mail: users-h...@tapestry.apache.org
> >
> >
>

Reply via email to