CDI Events allow beans to communicate so that one bean can define an event, another bean can fire the event, and yet another bean can handle the event.Let's see how we can take advantage of this to manage the lifecycle of a Quarkus application.

Start from a basic Quarkus project:

mvn io.quarkus:quarkus-maven-plugin:1.3.2.Final:create \
    -DprojectGroupId=com.sample \
    -DprojectArtifactId=lifecycle-demo \
    -DclassName="com.sample.ExampleResource" \

Then, add the following CDI Bean to it:

import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
import io.quarkus.runtime.configuration.ProfileManager;
import org.jboss.logging.Logger;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;

class ApplicationLifeCycle {

    private static final Logger LOGGER = Logger.getLogger(ApplicationLifeCycle.class);

    void onStart(@Observes StartupEvent ev) {"The application has started");

    void onStop(@Observes ShutdownEvent ev) {"The application is stopping...");

This is an example of how to take advantage of the CDI concept of events, in which you produce and subscribe to events occuring in your application in a way that enables you to maintain decoupled code between producers and observers. Quarkus runtime uses the javax.enterprise.event.Event class to create events, and you use the CDI’s @Observes annotation to subscribe to events.

In our case, the CDI @Observes the io.quarkus.runtime.StartupEvent and the io.quarkus.runtime.ShutdownEvent. Therefore:

  • On start with the StartupEvent you can execute code when the application is starting
  • On shutdown with the ShutdownEvent you can execute code when the application is shutting down.

Run the application with:

mvn quarkus:dev

You will see on the Console printed:

[com.sam.ApplicationLifeCycle] (main) The application has started

If you stop it, the following message will be displayed:

[com.sam.ApplicationLifeCycle] (Quarkus Shutdown Thread) The application is stopping...

Interestingly enough, you can perform a different set of actions in your LifeCycle class based on the Profile which has been used to start your application.

By default Quarkus has three profiles, although it is possible to use as many as you like. The default profiles are:

  • dev - Activated when in development mode (i.e. quarkus:dev)
  • test - Activated when running tests
  • prod - The default profile when not running in development or test mode

Let's change our code as follows:

void onStart(@Observes StartupEvent ev) {"The application is starting with profile `%s`", ProfileManager.getActiveProfile());

Now, if you start the application in development mode, the following output will be displayed:

[com.sam.ApplicationLifeCycle] (main) The application is starting with profile `dev`