Life cycle management of the event scheduler (and other axon non core components)

Hi Allard,

I’ve played a bit with event schedulers. I was wondering what the best way to configure event schedulers through the configuration API and handle their life cycle is?

I’ve setup a standalone application via DefaultConfigurer, created a SimpleEventScheduler and registered it as component in the configuration. So far no problems just using it, e.g. in a Saga.

The problem comes when the application ends and wants to shutdown. The executor service used in the simple event scheduler doesn’t terminate because its shutdown method is never called.

That leads to the question, how axon is looking at managed objects if using java configuration? I can think of several solutions:

1.) Give axon components a life cycle so that they can be stopped with the configuration just as module configurations are.
2.) Allow a module configuration to create and register components in order to control their life cycle
3.) Make the event scheduler an important concept in the configuration just as event bus or command bus are and manage the life cycle there.

Sure, this problem goes away if using e.g. a DI container which can manage the life cycle of application specific services. And maybe this is also indicates that you have decided that axon should stay out of the way in managing life cycles other than axon core components.

What do you think?

Kind regards,

Frank.

Hi Frank,

how did you configure the SimpleEventScheduler? There is already lifecycle management in the Configuration API, albeit simple. When registering the scheduler like this:
configurer.registerComponent(EventScheduler.class, c-> new SimpleEventScheduler(Executors.newSingleThreadScheduledExecutor()));

You should also register a close handler on the configuration to shutdown the executor service:
configurer.registerComponent(EventScheduler.class, c-> {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
SimpleEventScheduler scheduler = new SimpleEventScheduler(…);
c.onShutdown(executor::shutdown);
return scheduler;
});

Cheers,

Allard

Hi Frank,

how did you configure the SimpleEventScheduler? There is already lifecycle management in the Configuration API, albeit simple. When registering the scheduler like this:
configurer.registerComponent(EventScheduler.class, c-> new SimpleEventScheduler(Executors.newSingleThreadScheduledExecutor()));

In the end exactly like this.

You should also register a close handler on the configuration to shutdown the executor service:

configurer.registerComponent(EventScheduler.class, c-> {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
SimpleEventScheduler scheduler = new SimpleEventScheduler(…);
c.onShutdown(executor::shutdown);
return scheduler;
});

Ah, thanks. Missed that part. I didn’t know that you can register a close handler just like this.

What I’ve tried before was something like this:

public class EventSchedulerConfiguration implements ModuleConfiguration {
    private Configuration configuration;
    private ScheduledExecutorService executorService;
    private Component<EventScheduler> eventSchedulerComponent;

    public EventSchedulerConfiguration() {
        eventSchedulerComponent = new Component<EventScheduler>(() -> configuration, "Event Scheduler", c -> defaultEventScheduler(c));
    }

    public void initialize(Configuration configuration) {
        this.configuration = configuration;
    }

    public void start() {
        // is not part of the configuration interface
        configuration.registerComponent(EventScheduler.class, eventSchedulerComponent)

    }

    public void shutdown() {
        if (executorService != null) {
            executorService.shutdown();
        }
    }

    private EventScheduler defaultEventScheduler(Configuration configuration) {
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        return new SimpleEventScheduler(executorService, configuration.eventBus());
    }
}

But this was a dead end because there is no way to register the event scheduler component with the configuration. The idea behind it was to have the module configuration for supplying a default event scheduler as well as giving the possibility to configure another event scheduler.

Kind regards,

Frank.