Trigger scheduler once after deployment | Community
Skip to main content
February 9, 2018
Solved

Trigger scheduler once after deployment

  • February 9, 2018
  • 16 replies
  • 8246 views

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

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by joerghoh

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

16 replies

February 9, 2018

Maybe you can schedule it again when activating the component?

@Activate or @Modified

February 9, 2018

Can you point me to an example?

February 9, 2018

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);
  }

}

February 9, 2018

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()

smacdonald2008
February 9, 2018

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

February 9, 2018

@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 {

...

}

VeenaVikraman
Community Advisor
Community Advisor
February 9, 2018

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

February 9, 2018

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
   }

}

joerghoh
Adobe Employee
Adobe Employee
February 9, 2018

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

February 10, 2018

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.