Skip to content

Custom triggers

Simon Taddiken edited this page Aug 21, 2016 · 6 revisions

Custom triggers allow to implement individual scheduling strategies which will then be handled by the framework. All existing triggers are implemented this way. Writing a custom trigger involves two steps: Creating a trigger-annotation and creating a TriggerStrategy implementation to handle the annotation.

Trigger annotations

Trigger annotations provide meta information of how a method which is annotated with @Scheduled is actually scheduled. The first step is to create such a custom trigger annotation:

@Trigger
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CustomTrigger {
    // ... custom fields
}

The meta-annotation @Trigger marks this annotation as a valid trigger. @Retention tells the Java compiler that this annotation is handled during runtime (and not during compile time). @Target tells the Java compiler that this annotation is valid on methods only.

Trigger strategies

For every trigger annotation there exists an implementation of TriggerStrategy which is able to handle scheduling of methods annotated with that trigger.

public class CustomTriggerStrategy implements TriggerStrategy {

    @Override
    public Class<CustomTrigger> getTriggerType() {
        return CustomTrigger.class;
    }

    @Override
    public ScheduledContext schedule(Method method, Object self,
            ScheduledExecutorService executor,
            ExceptionHandler handler) {

        final CustomTrigger trigger = method.getAnnotation(getTriggerType());

        // schedule with given executor
    }

In order for the framework to find this implementation it must be registered as a Java Service Provider. This is done by placing a file named de.skuzzle.inject.async.TriggerStrategy into the META-INF/services directory. This file lists your trigger strategy implementations, one full qualified class name per line.

You can use field- or method-injection to inject any dependencies into your strategy implementation (Constructor injection is not possible as the strategy is instantiated by the Java ServiceLoader.

Implementation helpers

Your strategy must return an instance of ScheduledContext. You can obtain one by injecting the ContextFactory into your strategy implementation.

In order to support injection of method parameters, you may use the class InjectedMethodInvocation. You can create a Runnable instance which takes care of managing the context, calling the actual method and handling exceptions using RunnableBuilder.createRunnableStack. If your context should support cancellation you should have a look at RunnableBuilder.createLockedRunnableStack.