6

relevant zulip chat

I am trying to figure how you are supposed to gracefully fail during application startup in quarkus.

  1. i tried adding this to the application startup code. This is right now not being called if i run one of the unit tests. It is only called if i start the application directly. I was hoping to return a non zero value as oppose to throwing an exception. This might be the recomended approach. I am not sure.
    public class MyApp implements QuarkusApplication {

        @Override
        public int run(String... args) throws Exception {
            System.out.println("Do startup logic here");
            Quarkus.waitForExit();
            return 0;
        }
  1. i also tried raising an exception from the onStart lifecycle event. But it seems quarkus kept continuing its execution
   void onStart(@Observes StartupEvent ev) {               
        LOGGER.info("The application is starting...");
    }

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

I am not sure if this is a feature request a bug or i am missing something and this is normal behaviour.

Edit1: Just to be clear:

@Startup
@ApplicationScoped
public class StarterBean {
    private static final Logger LOGGER = Logger.getLogger("");

    public StarterBean() {
        throw new RuntimeException("failed misrably");
    }
}

when i run with "./gradlew quarkusDev` i see the exception in the console but the application never exists. I was thinking it should. It does exit during unit tests and properly fails. I tried moving the exception in the onStart and that did not help as well. I also tried combinations of having each of Startup,ApplicationScoped or both

Edit2:

I tested it by building the uber jar and running that. Raising the exception does quit the application. Also as one can imagine the application also exits when running in the docker container. I am puzzled why the gradle task never exist. So to that end i think i will accept the answer . Thank you so much for your help !

Ymo
  • 103
  • 6

1 Answers1

4

I'm not sure there's a nice answer here that fulfils all requirements (happy to be corrected if I'm wrong.) Not sure exactly what you're trying to achieve, but a few options which may be worth exploring:

  • Quarkus.asyncExit(code) in your run() method will allow you to exit gracefully, but this won't be called by unit tests.
  • You can initialise a bean at startup (annotate it with @Startup) that throws an exception in its constructor, but that isn't particularly elegant and won't give you control of the status code. It does however seem to return -1, so it does fulfil your criteria of a non-zero exit code at least. (Sadly Quarkus.asyncExit(code) doesn't seem to work for unit tests, even though it's executed in the bean initialisation before the test stars.)
  • As above, but you can call System.exit() in the bean constructor. This gives you control over the exit code, but is the least clean approach, it simply yanks the VM away without any graceful opportunity for cleanup.

EDIT: Just seen this from the zulipchat thread which adds some necessary context:

I need to be able to bail out during startup if i see certain conditions (for example missing env variables or whatever) how am i supposed to do it ?

In this case, I would probably declare a @Startup bean (or beans) to initialise based on these environment variables, and make sure the constructors of those beans throw meaningful exceptions if the conditions aren't right (missing env variables, corrupt env variables, etc.) That has a few advantages:

  • You can separate your appropriate startup checks into distinct beans, enforcing separation of responsibilities;
  • You have meaningful information to analyse & action in logs;
  • You meaningfully halt with a non-zero exit code if things are wrong as a result of throwing that exception, allowing a container healthcheck system to report that a node has died badly.
Michael Berry
  • 70,193
  • 21
  • 157
  • 216
  • Well ```Quarkus.asyncExit(0)``` works very fine, resembling springboot shutdown hook. You can use it for shutdown endpoint in a microservice rest – Stefano Scarpanti Feb 23 '22 at 08:34