16 Replies Latest reply on Feb 14, 2018 4:57 AM by Jörg Hoh

    Trigger scheduler once after deployment

    tim-schwalbe Level 1

      Hi guys,

       

      is it possible to trigger a scheduler once after every deployment? So the regular schedule time is 4 hours, but it will took 4 hours for the first run.

      Any property to set?

       

      Br,

       

      Tim

       

        • 1. Re: Trigger scheduler once after deployment
          dylanr46798176 Level 1

          Maybe you can schedule it again when activating the component?

           

          @Activate or @Modified

          • 2. Re: Trigger scheduler once after deployment
            tim-schwalbe Level 1

            Can you point me to an example?

            • 3. Re: Trigger scheduler once after deployment
              dylanr46798176 Level 1

              Let me try to see if I understand correctly what you're trying to achieve here.

               

              You have application code (an OSGi component) that schedules a specific task, every 4 hours. You want this task to be done after you've deployed your application code aswell. Let's take the following code as your OSGi component as an example:

               

              import org.apache.sling.commons.scheduler.ScheduleOptions;
              import org.apache.sling.commons.scheduler.Scheduler;
              import org.osgi.service.component.annotations.Activate;
              import org.osgi.service.component.annotations.Component;
              import org.osgi.service.component.annotations.ConfigurationPolicy;
              import org.osgi.service.component.annotations.Reference;
              import org.osgi.service.metatype.annotations.Designate;

               

              @Component(service = CustomSchedulerServiceImpl.class, configurationPolicy = ConfigurationPolicy.REQUIRE, immediate = true)

              public class CustomSchedulerServiceImpl implements CustomSchedulerServiceImpl {

               

                 /**
                * Cron formatted scheduling expression
                */
                 private String schedulerExpression;

                 @Reference
                 private Scheduler scheduler;

                 /**
                * Activate.
                *
                * @param config the polling service config
                */
                 @Activate
                 public void activate(final Map<String, Object> config) {

                      this.schedulerExpression = <YOUR CRON EXPRESSION HERE PREFERABLY FROM CONFIG>

                        scheduleNow();

                      

                       scheduleLater();

                 }

               

                 @Override
                 public void scheduleLater() {

                 final ScheduleOptions scheduleOptions = scheduler.EXPR(schedulerExpression);
                  scheduler.schedule(tireDesignsFetchJobFactory.createJob(), scheduleOptions);
                 }

               

                @Override
                public void scheduleINow() {

                  final ScheduleOptions scheduleOptions = scheduler.NOW();
                  scheduler.schedule(tireDesignsFetchJobFactory.createJob(), scheduleOptions);
                }

              }

              • 4. Re: Trigger scheduler once after deployment
                tim-schwalbe Level 1

                I have an actual scheduler but it runs not on startup only after the 4 hours of waiting and I want it the be run immediately.

                 

                What's that: tireDesignsFetchJobFactory.createJob()

                • 5. Re: Trigger scheduler once after deployment
                  smacdonald2008 Adobe Employee

                  WHen setting up a schedule - are you using the org.apache.sling.commons.scheduler.Scheduler API?

                  • 6. Re: Trigger scheduler once after deployment
                    tim-schwalbe Level 1

                    @Component(enabled = true, immediate = true, metatype = true, label = "cron job",
                       description = "cron job ")

                    @Service(value = Runnable.class)

                    @Properties({

                       @Property(name = "scheduler.expression", value = "0 0/15 * * * ?", description = "Cron-job expression Ex: '0 0/15 * * * ?' for 15 Mins"),
                       @Property(name = "scheduler.concurrent", boolValue = false)

                    })

                    @Slf4j
                    public class TestScheduler implements Runnable {

                    ...

                    }

                    • 7. Re: Trigger scheduler once after deployment
                      Veena_07 Level 4

                      I am not sure if I understood it correctly, but will an expression like below help ?

                       

                      0 0 */4 ? * * - It will run every 4 hours starting next closest hour .. Unfortunately i could find one which start immediately

                      • 8. Re: Trigger scheduler once after deployment
                        dylanr46798176 Level 1

                        My bad

                         

                        This was code that I've written for a project of mine and I wanted to remove anything that didn't have anything to do with your question. Seems like I missed something!

                         

                        Anyway, that "tireDesignFactory" simply creates a new instance that implements Runnable, like your TestScheduler. (So it's custom code)

                         

                        Your TestScheduler is not a scheduler, but a job itself. If you would use my example and create a factory that returns a new Runnable instance, then your scheduler service will schedule the job at a specific time, and you can also ask it to schedule a job right after you instantiate your bundle with the @Activate annotated method.

                         

                        You would get something like this:

                         

                        import org.apache.sling.commons.scheduler.ScheduleOptions;
                        import org.apache.sling.commons.scheduler.Scheduler;
                        import org.osgi.service.component.annotations.Activate;
                        import org.osgi.service.component.annotations.Component;
                        import org.osgi.service.component.annotations.ConfigurationPolicy;
                        import org.osgi.service.component.annotations.Reference;
                        import org.osgi.service.metatype.annotations.Designate;

                         

                        @Component(service = CustomSchedulerService.class, configurationPolicy = ConfigurationPolicy.REQUIRE, immediate = true)

                        public class CustomSchedulerServiceImpl implements CustomSchedulerService {

                         

                           private String schedulerExpression;

                           @Reference
                           private Scheduler scheduler;

                         

                           @Reference
                           private CustomJobFactory factory;


                           @Activate
                           public void activate(final Map<String, Object> config) {

                                this.schedulerExpression = <YOUR CRON EXPRESSION HERE PREFERABLY FROM CONFIG>

                                  scheduleNow();

                                 scheduleLater();

                           }

                         

                           @Override
                           public void scheduleLater() {

                           final ScheduleOptions scheduleOptions = scheduler.EXPR(schedulerExpression);
                            scheduler.schedule(factory.createJob(), scheduleOptions);
                           }

                         

                          @Override
                          public void scheduleINow() {

                            final ScheduleOptions scheduleOptions = scheduler.NOW();
                            scheduler.schedule(factory.createJob(), scheduleOptions);
                          }

                        }

                         

                        ------------------

                         

                         

                        import org.apache.sling.commons.scheduler.ScheduleOptions;
                        import org.apache.sling.commons.scheduler.Scheduler;
                        import org.osgi.service.component.annotations.Activate;
                        import org.osgi.service.component.annotations.Component;
                        import org.osgi.service.component.annotations.ConfigurationPolicy;
                        import org.osgi.service.component.annotations.Reference;
                        import org.osgi.service.metatype.annotations.Designate;

                         

                        @Component(service = CustomJobFactory.class, immediate = true)

                        public class CustomJobFactoryImpl implements CustomJobFactory {

                        //you can use this class to get references from the OSGi container and pass those to your CustomJob instances

                           @Override
                           public void createJob() {

                                return new CustomJob();
                           }

                        }

                         

                        --------------------

                         

                         

                        import org.apache.sling.commons.scheduler.Job;
                        import org.apache.sling.commons.scheduler.JobContext;

                        public class CustomJob implements Job {

                           public CustomJob() {

                         
                           }

                         

                           @Override
                           public void execute(final JobContext jobContext) {

                           //do something
                           }

                        }

                        • 9. Re: Trigger scheduler once after deployment
                          Jörg Hoh Adobe Employee

                          What do you want to achieve? Can we rephrase your requirement to something like this: "By default the scheduling interval should be 4 hours. In case it is taking more time, the process should not run in parallel, but serialized"?

                           

                          In that case the section "preventing concurrent execution" of Apache Sling :: Scheduler Service (commons scheduler)  is covering that.

                           

                          Jörg

                          • 10. Re: Trigger scheduler once after deployment
                            tim-schwalbe Level 1

                            If want to achieve that the scheduler runs directly on statup/after deployment but it seems it just starting after 4 hours for the first time and after that every 4 hours.

                             

                            The problem is the scheduler pulls data into AEM and otherwise I have to wait 4 hours for the very first execution.

                            So the component shows nothing for the first 4 hours.

                            • 11. Re: Trigger scheduler once after deployment
                              smacdonald2008 Adobe Employee

                              This is an interesting use case - when you setup a scheduler to fire every 4 hours - the first time it will count 4 hours.  See if you can modify the code to fire once 1 when its activated.

                              • 12. Re: Trigger scheduler once after deployment
                                Jörg Hoh Adobe Employee

                                Hi,

                                 

                                I see. The only chance to get it working the way you want is to trigger the scheduled job manually on activation of a SCR component/service.

                                 

                                Jörg

                                • 13. Re: Trigger scheduler once after deployment
                                  tim-schwalbe Level 1

                                  Yes that what i thought, but then it will block all other components on startup because its maybe running for 30 minutes. So no chance to do it this way. I have to create a new Service and trigger it by a custom scheduler.

                                  Thanks for all replies.

                                  • 14. Re: Trigger scheduler once after deployment
                                    Jörg Hoh Adobe Employee

                                    I don't think that you need to do this. You can use the Scheduler API to immediately fire an event. But yes, you need to trigger that in an activate method.

                                     

                                    Jörg

                                    • 15. Re: Trigger scheduler once after deployment
                                      dylanr46798176 Level 1

                                      So would it come down to the example I provided? (More or less)

                                      • 16. Re: Trigger scheduler once after deployment
                                        Jörg Hoh Adobe Employee

                                        I guess so. But please validate, that the case of some activations/deactivations of the component in a short time is handled properly :-) Depending on your deployment processes this might happen.

                                         

                                        Jörg