Thanks Paul and Ernesto,

After much stuffing around, I managed to get this to work: modifying the
JobDataMap within the Quartz job. However, you must re-publish the map
after it has been changed, as Quartz serializes it and doesn't update it
until after the job finishes executing. You might also need the
@PersistJobDataAfterExecution and @DisallowConcurrentExecution annotations
on the Quartz job to make it stateful.

The callback:

     if (callback != null) {
>       callback.updateProgress(resultSummary.successullyImportedRecords +
> resultSummary.unSuccessullyImportedRecords, false);
>      }



The updateProgress( ) callback on the Quartz job:

public void updateProgress(int count, boolean error) {
> try {
>     dataMap.put("results_counter", (int) count);
>     dataMap.put("results_error", error);
>
>     // Update the job detail and the associated data map (serialized in
> RAM?)
>     TorScheduler.getScheduler().addJob(jobDetail, true);
>
> } catch (SchedulerException e) {
> e.printStackTrace();
> logger.error("Error when updating the job details: " + e.getMessage());
> }
> }


The Progress Bar within the Wicket page:


        add(new AbstractAjaxTimerBehavior(Duration.seconds(3)) {
> private static final long serialVersionUID = 1L;
> @Override
>             protected void onTimer(AjaxRequestTarget target) {
> TorSession session = TorSession.get();
>                 progressbar.value(target, counter);
>                 JobKey jobKey = (JobKey) session.getAttribute(
> "importJobKey");
>                 System.out.println ("job key: " + jobKey);
>
>                 boolean error = false;
> try {
>                 Scheduler scheduler = TorScheduler.getScheduler();
>                 JobDetail jobDetails = scheduler.getJobDetail(jobKey);
>
>                 if (jobDetails == null) {
>                  System.out.println ("Job finished?");
>                 PageParameters pp = new PageParameters().set("p", deck
> .getId().getTudi());
>                 setResponsePage(Wiz14ImportComplete.class, pp);
>                 return;
>                 }
>
>                 JobDataMap jobDataMap = jobDetails.getJobDataMap();
>
>                 counter = jobDataMap.getIntValue("results_counter");
>                 error = jobDataMap.getBooleanValue("results_error");
>
> } catch (SchedulerException e) {
> error("Error with import batch process: " + e.getMessage());
> setUpdateInterval(Duration.NONE);
> target.add(curr);
> return;
> }
>
> if (error) {
> error("Error occurred during the import batch process");
> setUpdateInterval(Duration.NONE);
> } else {
>             // Redirect if we get the max count
>                 if (counter >= maxItems) {
>                 PageParameters pp = new PageParameters().set("p", deck
> .getId().getTudi());
>                 setResponsePage(Wiz14ImportComplete.class, pp);
>                 }
> }
>
>                 target.add(curr);
>             }
>         });


Cheers,

Nigel




On Wed, Feb 27, 2013 at 5:14 PM, Ernesto Reinaldo Barreiro <
reier...@gmail.com> wrote:

> Hi,
>
> I remember I have done this by creating a class that serves a "progress
> watching context" and sharing an instance of this class between Wicket
> Session (or a page or component) and the "quartz job". This class acted as
> a "wire" to pass information between the two "threads" (e.g. progress,
> cancel the JOB, etc). I also used an AJAX timer too poll server. I think
> there is an example of how to do that at
>
>
> http://code.google.com/p/antilia/source/browse/#svn%2Ftrunk%2Fcom.antilia.export%2Fsrc%2Fcom%2Fantilia%2Fexport%2Fpdf
>
> Thought code is quite old...
>
>
> On Tue, Feb 26, 2013 at 11:47 PM, Nigel Sheridan-Smith <wtfi...@gmail.com
> >wrote:
>
> > Hi all,
> >
> > I'm hooking up a data import batch job with Quartz to Wicket and have
> > struck an issue - how do you notify a Wicket page that the batch job is
> > complete?
> >
> > I originally planned to update the Wicket session with the running count
> of
> > how many items are processed. However, the Wicket request cycle expires
> so
> > it is not possible to update the session after the page is rendered.
> >
> >
> > To create the job:
> >
> > JobDataMap dataMap = new JobDataMap();
> > > dataMap.put("service", getService());
> > > dataMap.put("deck", deck);
> > > dataMap.put("importType", importType);
> > > dataMap.put("fieldMapping", fieldMapping);
> > > dataMap.put("fileUploaded", fileUploaded);
> > > dataMap.put("totalRecords", prevImportSummary.totalRecordsInImport);
> > > dataMap.put("callback", this);
> > > // Create a new job with a basic trigger
> > > JobDetail job = newJob(DataImportJob.class
> > > ).usingJobData(dataMap).build();
> > > Trigger trigger =
> > > newTrigger().startNow().withSchedule(simpleSchedule()).build();
> > > try {
> > > // Schedule the job for immediate start
> > > TorScheduler.getScheduler().scheduleJob(job, trigger);
> > > } catch (SchedulerException se) {
> > > TorScheduler.getLogger().error(se.getMessage());
> > > throw new TorException("Cannot start the data import job");
> > > }
> >
> >      The data import job uses a callback to the Wicket page:
> >
> > callback.updateTotal(totalRecords);
> > >
> >     callback.updateProgress(/* 0 */ totalRecords, false); // TODO:
> > > Temporarily skip the progress bar page
> > >
> >
> > >
> >     // Now add the entries to the repository
> > >
> >     ImportSummary importSummary = dataImportProcess.commit(callback);
> > >
> >     callback.updateImportSummary(importSummary);
> > >
> >
> > The callback has this implementation (in the page):
> >
> >  public void updateProgress(int count, boolean error) {
> > >
> > >   // Attempt to reuse the same session as before (left open)
> > >
> > >  session.setAttribute("importItemsDone", (Integer) count);
> > >
> > >  session.setAttribute("importIsInError", (Boolean) error);
> > >
> > > }
> > >
> > >  @Override
> > >
> > > public void updateTotal(int total) {
> > >
> > >
> > >  // Attempt to reuse the same session as before (left open)
> > >
> > >  session.setAttribute("importItemsTotal", (Integer) total);
> > >
> > > }
> > >
> > >
> > >  @Override
> > >
> > > public void updateImportSummary(ImportSummary importSummary) {
> > >
> > >
> > >  // Attempt to reuse the same session as before (left open)
> > >
> > >  session.setAttribute("importSummary", importSummary);
> > >
> > > }
> > >
> >
> > However, I get this exception when attempting to update the Wicket
> session
> > with the progress counter:
> >
> > java.lang.IllegalStateException: Cannot set the attribute: no
> RequestCycle
> > available.  If you get this error when using
> WicketTester.startPage(Page),
> > make sure to call WicketTester.createRequestCycle() beforehand.
> > at org.apache.wicket.Session.setAttribute(Session.java:773)
> > at
> >
> >
> com.xxx.tor.webapp.profile.Wiz13ImportResults.updateTotal(Wiz13ImportResults.java:208)
> > at
> com.xxx.tor.webapp.batch.DataImportJob.importNow(DataImportJob.java:53)
> > at com.xxx.tor.webapp.batch.DataImportJob.execute(DataImportJob.java:83)
> > at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
> > at
> >
> >
> org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)
> >
> >
> > Is this the best approach? Or should I attempt to use methods on the
> Quartz
> > scheduler to get the current progress of the batch job from within
> > AbstractAjaxTimerBehavior.onTimer( )?
> >
> > I am using the JQWicket (jQuery UI) progress bar... with a 5 second delay
> > on updates to the page.
> >
> > Cheers,
> >
> > Nigel
> >
> >
> > --
> > e: ni...@joinsomeone.com
> > m: +61 403 930 963
> >
> > Get together for fun activities at www.joinsomeone.com
> >
> > Like us on Facebook www.facebook.com/JoinSomeone
> > Follow us on Twitter @JoinSomeone
> >
>
>
>
> --
> Regards - Ernesto Reinaldo Barreiro
> Antilia Soft
> http://antiliasoft.com/ <http://antiliasoft.com/antilia>
>



-- 
e: ni...@joinsomeone.com
m: +61 403 930 963

Get together for fun activities at www.joinsomeone.com

Like us on Facebook www.facebook.com/JoinSomeone
Follow us on Twitter @JoinSomeone

Reply via email to