Skip to content

Application won't stop in case of error at startup time if management.server.port != server.port #14490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
snussbaumer opened this issue Sep 17, 2018 · 4 comments
Labels
for: external-project For an external project and not something we can fix status: invalid An issue that we don't feel is valid

Comments

@snussbaumer
Copy link

If an exception occurs during the startup of a spring boot application AND if management.server.port != server.port, the application won't stop as it should and stays in a "limbo state" : it's not started, but does not stop.

This is a problem when for example run in a Kubernetes cluster, as Kubernetes won't detect that the application didn't start and won't try to restart it.

Repro here : https://github.com/snussbaumer/app-wont-stop-repro, just run mvn spring-boot:run and see that the app is neither started nor stopped.

If you try to curl localhost:8080/info you see an exception :
java.lang.IllegalStateException: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@49ed99ad has not been refreshed yet

I repro the problem by throwing an exception in the start method of a SmartLifeCycle object, which is really to make it simple to reproduce, but I see the same problem in a more involved case in a spring cloud application (with eureka and an a config server), when it has problems contacting the configuration server at startup (java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:136))

Below the files from the repro :

@SpringBootApplication
public class ReproApplication {

    public static void main(String[] args) {
        SpringApplication.run(ReproApplication.class, args);
    }

    @Bean
    public TestLifeCycle testLifeCycle() {
        return new TestLifeCycle();
    }

    public static class TestLifeCycle implements SmartLifecycle {

        private boolean isRunning = false;

        @Override
        public boolean isAutoStartup() {
            return true;
        }

        @Override
        public void stop(Runnable callback) {
            callback.run();
        }

        @Override
        public void start() {
            if (isRunning) {
                return;
            }
            isRunning = true;
            throw new RuntimeException("Something went wrong");
        }

        @Override
        public void stop() {
            isRunning = false;
        }

        @Override
        public boolean isRunning() {
            return isRunning;
        }

        @Override
        public int getPhase() {
            return Integer.MIN_VALUE;
        }
    }

}

application.properties

server.port=80
management.server.port=8080

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>repro</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>repro</name>
  <description>Demo project for Spring Boot</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 17, 2018
@philwebb philwebb added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Sep 17, 2018
@philwebb philwebb added this to the 2.0.x milestone Sep 17, 2018
@wilkinsona
Copy link
Member

wilkinsona commented Oct 2, 2018

We already register an ApplicationListener that should close the child management context:

CloseManagementContextListener.addIfPossible(this.applicationContext,
managementContext);
managementContext.refresh();

The problem is that this listener isn't called when the ApplicationFailedEvent is published. It isn't called because the listener was registered after the application context's multicaster had been initialised and, as a result, it isn't in the collection returned by AbstractApplicationContext.getApplicationListeners(). I'm not sure that there's a good way for us to register the initialiser early while avoiding registering it unnecessarily.

I think we may need a Framework change to fix this. Specifically, it would be helpful if getApplicationListeners() returns all added listeners, irrespective of whether they were registered before the multicaster is created or after it was created.

@wilkinsona
Copy link
Member

I've opened SPR-17324.

@wilkinsona wilkinsona added the status: blocked An issue that's blocked on an external project change label Oct 6, 2018
@wilkinsona
Copy link
Member

Thanks to the changes made for SPR-17324 which are in Framework 5.0.10 snapshots, the provided sample now passes when using Spring Boot 2.0.6 snapshots.

@wilkinsona wilkinsona added status: invalid An issue that we don't feel is valid for: external-project For an external project and not something we can fix and removed status: blocked An issue that's blocked on an external project change type: bug A general bug labels Oct 10, 2018
@wilkinsona wilkinsona removed this from the 2.0.x milestone Oct 10, 2018
@snussbaumer
Copy link
Author

Great, many thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

4 participants