vidocq-runtime-core is the Vidocq Runtime runtime engine. It discovers the extensions through ServiceLoader, builds the configuration, boots the Vauban CDI container and drives the extension lifecycle.

Coordinates

Artefact

io.vidocq.runtime:vidocq-runtime-core:0.3.0

Java module

io.vidocq.runtime.core

Source

vidocq-runtime-core/src/main/java/io/vidocq/runtime/core/

Responsibilities

  • Discover every VidocqExtension on the module path via java.util.ServiceLoader (ExtensionLoader), sorted by ascending priority().

  • Build the configuration (VidocqConfigImpl over the built-in ConfigSource chain, wrapped by the legacy VidocqConfigurationImpl).

  • Run the lifecycle in order (VidocqBootstrap):

    1. configure — each extension reads its keys: ext.configure(configuration).

    2. beforeStart — create the VaubanContainerBuilder (bean index from META-INF/vauban-beans.list, no classpath scanning) and let each extension enrich it: ext.beforeStart(builder).

    3. CDI start — builder.build() boots Vauban.

    4. onStart — each extension receives the ExtensionContext (container, bean manager, config): the Chappe extension opens the HTTP listeners, Cassini mounts the REST routes, Mansart opens the JDBC pool.

  • Warn about configured vidocq.* keys no extension consumes (ConfigKeyAudit, based on VidocqExtension.configKeys()).

  • Manage the shutdown cycle — onStop() runs in reverse priority order, virtual threads drain cleanly.

  • Install the Vauban application layer when the launch vehicle requires it (VidocqAppLayer, Vidocq.run), including the vidocq:dev hot-reload loop (VidocqDevReloadLoop).

Entry point

package io.example;

public class App {
    public static void main(String[] args) {
        io.vidocq.runtime.core.Vidocq.main(args);
    }
}

Vidocq.main is a simple facade over VidocqBootstrap. User code does not need a @SpringBootApplication nor an application class — extensions and beans are discovered from the module path (ServiceLoader + the compile-time bean index). For a zero-config IDE launch, annotate a trampoline main with @VidocqMain and call Vidocq.run(App.class, args) — the application is then re-loaded inside the Vauban application layer.

Lifecycle hooks

An extension subscribes to phases by overriding the VidocqExtension methods:

public class MyExtension implements VidocqExtension {

    @Override
    public String name() { return "my-extension"; }

    @Override
    public void onStart(ExtensionContext ctx) {
        // the container is up — resolve beans, mount handlers
    }

    @Override
    public void onStop() {
        // reverse-order shutdown — release resources
    }
}

All hooks have empty default implementations; priority() (default 1000, lower runs first) orders the extensions within every phase.

Threading

Boot itself is intentionally sequential on a single thread (easier diagnosis, readable stack traces). The virtual threads appear after onStart:

  • the Chappe HTTP I/O — one virtual thread per inbound connection;

  • the Mansart JDBC housekeeping;

  • request-time work of extensions such as vidocq-runtime-knock-health-extension, whose health checks execute on the incoming request’s virtual thread.

Next steps

  • Internals — detailed sequence with diagram

  • SPI — interfaces consumed by core