Re: Can a batch job pass back its completion results to Wicket session?

2013-02-26 Thread Paul Bors
I would look at Observable and Observer class in java to achieve signal
sort of behavior.

On Tue, Feb 26, 2013 at 5:47 PM, Nigel Sheridan-Smith wtfi...@gmail.comwrote:

 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



Re: Can a batch job pass back its completion results to Wicket session?

2013-02-26 Thread Ernesto Reinaldo Barreiro
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.comwrote:

 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


Re: Can a batch job pass back its completion results to Wicket session?

2013-02-26 Thread Nigel Sheridan-Smith
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 */ 

Re: Can a batch job pass back its completion results to Wicket session?

2013-02-26 Thread Ernesto Reinaldo Barreiro
Hi,

On Wed, Feb 27, 2013 at 7:32 AM, Nigel Sheridan-Smith wtfi...@gmail.comwrote:

 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.

 I remember using a quartz listener to attach/remove this progress
reporting class to the Job... So that that progress class did not need to
be stored. I don't remember if it was a thread local context like class


 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 =