Announcement Announcement Module
Collapse
No announcement yet.
How to monitor the progress of a Tasklet to send to the GUI ? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to monitor the progress of a Tasklet to send to the GUI ?

    Here is my spring batch config (relevant part) :
    Code:
        <batch:job id="fakeJob" parent="simpleJob">
            <batch:step id="fakeLongJobStep" parent="simpleStep">
                <batch:tasklet ref="mytasklet" />
            </batch:step>
        </batch:job>
    So this is just a job calling one step which is a tasklet.

    What I want to do is to report the progress inisde the tasklet.

    At first, I tried :
    Code:
    public class MyTasklet implements Tasklet {   
        @Override
        public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
            JobExecution e = chunkContext.getStepContext().getStepExecution().getJobExecution();
            for (i = 0; i < 100; i++) {
                 e.getExecutionContext().put("progress", i+"/100");
                 Thread.sleep(2000); //simulate heavy operation
            }
        }
    }
    Then, from another thread (i.e another XHR request to my webapp), I ask for the current progress :
    Code:
       public String readProgress(int executionId) {
         return jobExplorer.getJobExcution(executionId).getExecutionContext().get("progress"); 
       }
    This always return null except when the job is finished (which then report 99/100)

    From what I understand, this is logical since the JobExecution is NOT persisted during the execution of a step (only persisted after).
    How can I do to track the progress ?

    The first thing I tried was to inject JobRepository into my tasklet and call jobRepository.updateExecutionContext(jobExecution) .
    I assume this does not work since the transaction is not commited (hence, other threads still do not see the progress).
    So how can I do ? Should I use a TransactionTemplate for each heavy operation or something like that ?

    Please, note that using the reader->writer paradigm is not possible in my case (ask details if you need to know why ).
    Last edited by cblin; Sep 20th, 2011, 10:32 AM. Reason: minor bug fix in code

  • #2
    As a simple response to myself : use the Application event given by spring framework : http://static.springsource.org/sprin...onality-events

    * send an event from your reader/processor/writer like
    ** this.sendEvent(new JobProgressStartEvent(this, jobExecutionId, nbSteps))
    ** this.sendEvent(new JobProgressIncrementEvent(this, jobExecutionId))
    ** this.sendEvent(new JobProgressStopEvent(this, jobExecutionId))
    * listen for the 3 events inside a class with a ConcurrentHashMap<long, Progress> with Progress = {cur, total}
    * when you need the progress, ask to the ProgressServices

    Comment


    • #3
      Need help regarding what you have done

      Originally posted by cblin View Post
      As a simple response to myself : use the Application event given by spring framework : http://static.springsource.org/sprin...onality-events

      * send an event from your reader/processor/writer like
      ** this.sendEvent(new JobProgressStartEvent(this, jobExecutionId, nbSteps))
      ** this.sendEvent(new JobProgressIncrementEvent(this, jobExecutionId))
      ** this.sendEvent(new JobProgressStopEvent(this, jobExecutionId))
      * listen for the 3 events inside a class with a ConcurrentHashMap<long, Progress> with Progress = {cur, total}
      * when you need the progress, ask to the ProgressServices
      I know its a very old thread but I also have same need as your so could you explain me how you called this.sendEvent() fromTasklet.
      Last edited by piyushpatel2809; Nov 22nd, 2012, 03:50 AM.

      Comment


      • #4
        in your tasklet, inject the ApplicationEventPublisher as mentionned in the doc.

        Comment


        • #5
          Need help regarding what you have done

          Originally posted by cblin View Post
          in your tasklet, inject the ApplicationEventPublisher as mentionned in the doc.
          First of all thanks alot by your last answer Now i am getting onApplicationEvent() called after each step.The line saying about progress and ConcurrentHashMap if you could explain me more that will do the whole task for me.
          Thanks.

          Comment


          • #6
            it means that you have to create a class that is listening to the events

            something like that :

            public class Progress implements EventListener<ApplicationEvent> {
            ConcurrentHashMap<Long, Long> progress;

            public onApplciationEvent(ApplicationEvent e) {
            if (e instanceof StartJob) { progress.put(((StartJob)e).getExecId(), 0) }
            else if (e instanceof ProgressJob) { progress.get(((StartJob)e).getExecId())++; }
            else if (e instanceof EndJob) { progress.remove(((StartJob)e).getExecId()); }
            }
            }

            Comment


            • #7
              How to access this HashMap in controller.

              Originally posted by cblin View Post
              it means that you have to create a class that is listening to the events

              something like that :

              public class Progress implements EventListener<ApplicationEvent> {
              ConcurrentHashMap<Long, Long> progress;

              public onApplciationEvent(ApplicationEvent e) {
              if (e instanceof StartJob) { progress.put(((StartJob)e).getExecId(), 0) }
              else if (e instanceof ProgressJob) { progress.get(((StartJob)e).getExecId())++; }
              else if (e instanceof EndJob) { progress.remove(((StartJob)e).getExecId()); }
              }
              }
              I have set up like you suggested but i am wondering how can i access this map in controller and send progress back to jsp via ajax thread.i tried adding it in request scope but the AppliactionListner implementation is out of scope from DispatcherServlet.
              Thanks.

              Comment

              Working...
              X