concurrency
concurrency copied to clipboard
[Use Case]: Autostart for Scheduled Asynchronous methods
As a ...
- [ ] Application user/user of the configuration itself
- [X] API user (application developer)
- [ ] SPI user (container or runtime developer)
- [ ] Specification implementer
I need to be able to ...
arrange for an Asynchronous method to be automatically submitted/scheduled after a configurable delay upon application startup
Which enables me to ...
more conveniently code applications that have business logic that should run on a schedule
Additional information
This requirement was discussed in a topic titled "Defining Jakarta EE 12 Scope in Program Plan" on the jakarta.ee-community mailing list.
It is already possible to have an Asynchronous method immediately start running on a schedule with code like this:
@Asynchronous(runAt = @Schedule(daysOfWeek = DayOfWeek.TUESDAY, hours = 1))
public void weeklyTask(@Observes Startup event) {
...
}
There has also been some interest in being able to impose a delay before the Asynchronous method will automatically start running. One way that this can already by achieved is with 2 separate methods,
@Inject
ManagedScheduledExecutorService executor;
public void autoStart(@Observes Startup event) {
executor.schedule(this::every10Minutes, 1, TimeUnit.HOURS);
}
@Asynchronous(runAt = @Schedule(cron = "*/10 * * * *"))
public void every10Minutes() {
...
}
If the above usage is good enough, we could document similar examples in the spec and add some TCK tests.
If the above is not considered concise enough, another idea would be to add add a long value, being a delay (in milliseconds? seconds? which unit is best?) to automatically start after. The default of -1 would mean don't automatically schedule on application startup, keeping existing applications compatible.
@Asynchronous(runAt = @Schedule(cron = "*/10 * * * *"),
submitAfter = 1000)
public void every10Minutes() {
...
}
Some concerns if we did this would be if someone tries to use both ways on the same method, which would be contradictory.
As EJB and Spring do, make sure all @Scheduled based scheduled tasks are scanned at deployment time and started automatically as the application is deployed.
Developers can control more details of the scheduled task by programmatic APIs, auto or not, conditionally generate the schedule settings, etc.
The @Schedule nested in the current @Asychronous is confused, and can not replace the EJB one.
I vote for the opinion of @OndroMih
Yes. I would even remove this in the next version of Concurrency and create a completely new >Scheduled annotation, not reuse Asynchronous. It’s a completely broken API construct.
Maybe it’s even time to release a new version of Concurrency to fix it and make it into EE 11, since we’re still waiting for the TCK.
https://eclipsefoundationhq.slack.com/archives/C04EWTSC16Y/p1735047311024939
I have now had a chance to closely examine the current design, and I must say I entirely agree with @arjantijms, @OndroMih, and @hantsy. The original EJB @Schedule and subsequent Spring @Scheduled annotations have had a popular, proven, and intuitive design for many years now. In order for the Jakarta Concurrency equivalent to have a practical possibility of being competitive, it really needs to support something like this:
@ApplicationScoped
public class UploadDirectoryScanner {
@Schedule(cron = "*/15 * * * * *")
public void processFiles() {
...
}
}
I think the current design might have a place too, but it may be best to rethink it with more community input. Perhaps it is best to not release it at all for now.
Perhaps it is best to not release it at all for now.
It was already released back in June 2024 under Concurrency 3.1. Unfortunately all of this discussion is happening much too late to decide not to release it. At this point, it would take a breaking change and consequently a new major release (4.0) to remove the @Schedule annotation that was already released in 3.1.
But maybe we don't need to do anything that drastic. @m-reza-rahman states above,
it really needs to support something like this:
@ApplicationScoped public class UploadDirectoryScanner { @Schedule(cron = "*/15 * * * * *") public void processFiles() { ... } }
The @Schedule(cron = "*/15 * * * * *") part is already valid under Concurrency 3.1. The part that isn't allowed is placing the Schedule annotation directly on a method.
In 3.1, @Schedule is only permitted in the runAt of the @Asynchronous annotation, and it defaults to requiring manual invocation unless you include @Observes Startup event on the method to make it automatic.
One option that we have would be to expand the valid target for @Schedule to also include ElementType.METHOD, for which we would define the behavior to be automatic start. I think that would give you the more concise way of using it that you are asking for without requiring a breaking change. It would still be a breaking change if you also want to get rid of the ability to define runAt = @Schedule(...) on @Asynchronous.
I think the main thing is providing a real alternative to EJB and Spring. The current design could remain at least for some time. It is not entirely invalid certainly.
I agree. We can keep the current design and allow using the same @Schedule annotation on a method. That's a great suggestion, @njr-11, thank you!
I hope there is a new annotation that refer to the definition from Spring @Scheduled.
public @interface Scheduled { // a modified versoin of spring @Scheduled
String cron() default ""; //also should support EL
ZoneId zone() default UTC;
long fixedRate() default -1;
String fixedRateExpression() default ""; // accept EL
long fixedDelay() default -1;
String fixedDelayExpression() default ""; // accept EL
long initialDelay() default -1;
String initialDelayExpression() default ""; // accept EL
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
String scheduler() default ""; //scheduledExecutorService name or change it to Qualifier to match the executor to run this scheudule
}
Currently, the in the @Schedule, the attributes hour/minute/second etc., are just another form of the cron, it does not cover the simple fixedRate/interval case.
We can probably just add the missing rate, delay, and timeUnit arguments to the existing Schedule? That should work both with an annotated method and inside the @Asynchronous annotation.
We can probably just add the missing rate, delay, and timeUnit arguments to the existing Schedule? That should work both with an annotated method and inside the @asynchronous annotation.
It is possible.
But there is an issue if allowing it annotated with methods directly, you have to add an extra attribute similar to @Asynchronus.executor to choose the executor service.
Currently, it is nested in the @Asynchronous, it could reuse the executor attribute in @Asynchronous.
I absolutely support the idea of automated start of the @Asynchronous method!
Is there any reason to use one interface for 3 different settings? We use the @Scheduled for cron, for definition by fields and now we talk about about rate/interval. Can we simply define 3 different annotations, which defines clearly the fields with no complex rules.
public @interface Schedule {
Month[] months() default {};
int[] daysOfMonth() default {};
DayOfWeek[] daysOfWeek() default {};
...
String zone() default "";
}
public @interface ScheduleCron {
String cron();
String zone() default "";
}
public @interface ScheduleRate {
long fixedRate() default -1;
String fixedRateExpression() default ""; // accept EL
long fixedDelay() default -1;
String fixedDelayExpression() default ""; // accept EL
long initialDelay() default -1;
String initialDelayExpression() default ""; // accept EL
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
Because of the backward compatibility -- what about just to add the other two annotations? This would allow to simplify new code.
Because of the backward compatibility -- what about just to add the other two annotations? This would allow to simplify new code.
@Schedule already has cron, so the first two are already combined. Your point about using a separate annotation if we add an annotative way of specifying fixed rate/fixed delay is a very good one because there is no overlap at all between the attributes involved and it would be confusing to users to be able to intermix what is configured for fixed rate/fixed delay TimeUnit-based attributes with what is configured for the Cron/year-month-day... TimeZone based attributes.
I don't see why fixed rate/fixed delay are even being discussed under this issue at all. This issue is supposed to be about automatic start. A separate issue ought to be used for requesting an annotation that provides fixed rate/fixed delay configuration.
@njr-11 Created new issue https://github.com/jakartaee/concurrency/issues/684
Because of the backward compatibility -- what about just to add the other two annotations? This would allow to simplify new code.
I do not think we have compatibility issue now, because Jakarta EE 11 is not released, and this @Schedule annotation is not used widely.
Thanks for splitting it out. I tagged #684 with the 3.2 milestone to ensure it is considered.
Because of the backward compatibility -- what about just to add the other two annotations? This would allow to simplify new code.
I do not think we have compatibility issue now, because Jakarta EE 11 is not released, and this
@Scheduleannotation is not used widely.
It doesn't matter that Jakarta EE 11 web profile/platform are not released yet. Jakarta Concurrency 3.1 @Schedule was already released and so it would be an incompatible change to the Concurrency specification to make an incompatible change to the @Schedule annotation that was in the 3.1 spec level.
Because of the backward compatibility -- what about just to add the other two annotations? This would allow to simplify new code.
Separating them into different annotations is a good idea.
- Make the current
@Scheduleto build cron via attributes likemonths/daysOfMonth/daysOfWeek, etc. (mainly replace the EJB@Schedule) - When using the
cronexpression and fixed rate try to move to the new@Scheduledannotation as I suggested in #684
Then it covers the users who are familiar with second/minute/hour/months/daysOfMonth/daysOfWeek attributes in EJB @Schedule, and also attracts new users that are familiar with corn expression or Spring @Scheduled.