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
Solved! Go to Solution.
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
Maybe you can schedule it again when activating the component?
@Activate or @Modified
Views
Replies
Total Likes
Can you point me to an example?
Views
Replies
Total Likes
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);
}
}
Views
Replies
Total Likes
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()
Views
Replies
Total Likes
WHen setting up a schedule - are you using the org.apache.sling.commons.scheduler.Scheduler API?
Views
Replies
Total Likes
@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 {
...
}
Views
Replies
Total Likes
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
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
}
}
Views
Replies
Total Likes
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
Views
Replies
Total Likes
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.
Views
Replies
Total Likes
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.
Views
Replies
Total Likes
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
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.
Views
Replies
Total Likes
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
Views
Replies
Total Likes
So would it come down to the example I provided? (More or less)
Views
Replies
Total Likes
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
Views
Like
Replies
Views
Like
Replies