Skip to content

Declaring an ApplicationRunner causes Spring Shell application to close immediately #1330

@3ric-T

Description

@3ric-T

Description

A Spring Boot application using Spring Shell version 4.0.1 with interactive mode configured exits immediately after start if classes implementing ApplicationRunner are present and declared as @Component


Versions affected

  • Spring Shell 4.0.1
  • Spring Boot 4.0.5

Operating System

  • Linux (Ubuntu 24.04.4)
  • Java 25.0.2 (OpenJDK)

Steps to Reproduce

  1. Generate a minimal project from start.spring.io with Spring Shell as the only dependency
  2. Add a Component that implement ApplicationRunner :
package com.example.demo.runner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class DemoRunner implements ApplicationRunner {
    private static final Logger LOGGER = LoggerFactory.getLogger(DemoRunner.class);

    @Override
    public void run(ApplicationArguments args) throws Exception {
        LOGGER.info("This is my runner!");
    }
}
  1. Build the application:
./gradlew build
  1. Launch the application:
java -jar demo-0.0.1-SNAPSHOT.jar

Expected Behavior

The application should:

  1. Complete startup
  2. Display the Spring Shell prompt
  3. Wait for user input in interactive mode
  4. Remain running until the user exits

Actual Behavior

The application:

  1. Completes startup successfully
  2. Immediately triggers the shutdown hook
  3. Exits with code 0 without entering interactive mode

Additional Context

  • The problem did not occur with Spring Shell 3.4.x
  • Enabling spring.shell.context.close=true did not solve anything

Minimal Reproducer

A minimal project demonstrating the problem is available here:
👉 https://github.com/3ric-T/spring-shell-reproducer

Possible Workaround

When possible, the ApplicationRunner implementations can be replaced by classes with methods annotated with @EventListener

Logs


Negative matches:
-----------------
(...)
   ShellRunnerAutoConfiguration#nonInteractiveShellRunner:
      Did not match:
         - @ConditionalOnProperty (spring.shell.interactive.enabled=false) found different value in property 'enabled' (OnPropertyCondition)

   ShellRunnerAutoConfiguration#springShellApplicationRunner:
      Did not match:
         - @ConditionalOnMissingBean (types: org.springframework.boot.ApplicationRunner; SearchStrategy: all) found beans of type 'org.springframework.boot.ApplicationRunner' demoRunner (OnBeanCondition)
(...)

Unconditional classes:
----------------------
(...)
    org.springframework.shell.core.autoconfigure.ShellRunnerAutoConfiguration
(...)

2026-04-02 11:38:25.084  INFO 2882 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 1.063 seconds (process running for 1.413)
2026-04-02 11:38:25.086 DEBUG 2882 --- [           main] o.s.b.a.ApplicationAvailabilityBean      : Application availability state LivenessState changed to CORRECT
2026-04-02 11:38:25.089  INFO 2882 --- [           main] com.example.demo.runner.DemoRunner       : This is my runner!
2026-04-02 11:38:25.090 DEBUG 2882 --- [           main] o.s.b.a.ApplicationAvailabilityBean      : Application availability state ReadinessState changed to ACCEPTING_TRAFFIC
2026-04-02 11:38:25.095 DEBUG 2882 --- [ionShutdownHook] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5b1f29fa, started on Thu Apr 02 11:38:24 CEST 2026
2026-04-02 11:38:25.097 DEBUG 2882 --- [ionShutdownHook] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 1073741823
2026-04-02 11:38:25.098 DEBUG 2882 --- [ionShutdownHook] o.s.c.support.DefaultLifecycleProcessor  : Bean 'applicationTaskExecutor' completed its stop procedure
2026-04-02 11:38:25.098 DEBUG 2882 --- [ionShutdownHook] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase -2147483647
2026-04-02 11:38:25.098 DEBUG 2882 --- [ionShutdownHook] o.s.c.support.DefaultLifecycleProcessor  : Bean 'springBootLoggingLifecycle' completed its stop procedure
2026-04-02 11:38:25.098 DEBUG 2882 --- [ionShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor' 

Would you like to contribute a fix?

  • Yes
  • No

I'm unfortunately not very familiar with how Spring Boot internally works but I'm keen to learn


Metadata

Metadata

Assignees

No one assigned

    Labels

    status/need-triageTeam needs to triage and take a first look

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions