From a20cd2de02b3167bd47e886cc0970a3874fb0f3c Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 13 Jan 2016 13:14:40 +0000 Subject: [PATCH] Publish ExitCodeEvent when possible Update SpringApplication to publish an ExitCodeEvent when a valid exit code is known. Fixes gh-4804 --- .../springframework/boot/ExitCodeEvent.java | 50 +++++++++++++++++++ .../boot/SpringApplication.java | 23 ++++++--- .../boot/SpringApplicationTests.java | 20 ++++++++ 3 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 spring-boot/src/main/java/org/springframework/boot/ExitCodeEvent.java diff --git a/spring-boot/src/main/java/org/springframework/boot/ExitCodeEvent.java b/spring-boot/src/main/java/org/springframework/boot/ExitCodeEvent.java new file mode 100644 index 0000000000..e4464d8669 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/ExitCodeEvent.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot; + +import org.springframework.context.ApplicationEvent; + +/** + * Event fired when an application exit code has been determined from an + * {@link ExitCodeGenerator}. + * + * @author Phillip Webb + * @since 1.3.2 + */ +public class ExitCodeEvent extends ApplicationEvent { + + private final int exitCode; + + /** + * Create a new {@link ExitCodeEvent} instance. + * @param source the source of the event + * @param exitCode the exit code + */ + public ExitCodeEvent(Object source, int exitCode) { + super(source); + this.exitCode = exitCode; + } + + /** + * Return the exit code that will be used to exit the JVM. + * @return the the exit code + */ + public int getExitCode() { + return this.exitCode; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index c8dd46277d..25a1450115 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -302,7 +302,11 @@ public class SpringApplication { SpringApplicationRunListeners listeners = getRunListeners(args); listeners.started(); try { - context = doRun(listeners, args); + ApplicationArguments applicationArguments = new DefaultApplicationArguments( + args); + context = createAndRefreshContext(listeners, applicationArguments); + afterRefresh(context, applicationArguments); + listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) @@ -316,12 +320,13 @@ public class SpringApplication { } } - private ConfigurableApplicationContext doRun(SpringApplicationRunListeners listeners, - String... args) { + private ConfigurableApplicationContext createAndRefreshContext( + SpringApplicationRunListeners listeners, + ApplicationArguments applicationArguments) { ConfigurableApplicationContext context; // Create and configure the environment ConfigurableEnvironment environment = getOrCreateEnvironment(); - configureEnvironment(environment, args); + configureEnvironment(environment, applicationArguments.getSourceArgs()); listeners.environmentPrepared(environment); if (isWebEnvironment(environment) && !this.webEnvironment) { environment = convertToStandardEnvironment(environment); @@ -343,7 +348,6 @@ public class SpringApplication { } // Add boot specific singleton beans - ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments); @@ -363,8 +367,6 @@ public class SpringApplication { // Not allowed in some environments. } } - afterRefresh(context, applicationArguments); - listeners.finished(context, null); return context; } @@ -858,6 +860,9 @@ public class SpringApplication { Throwable exception) { int exitCode = getExitCodeFromException(exception); if (exitCode != 0) { + if (context != null) { + context.publishEvent(new ExitCodeEvent(context, exitCode)); + } SpringBootExceptionHandler handler = getSpringBootExceptionHandler(); if (handler != null) { handler.registerExitCode(exitCode); @@ -1186,6 +1191,7 @@ public class SpringApplication { */ public static int exit(ApplicationContext context, ExitCodeGenerator... exitCodeGenerators) { + Assert.notNull(context, "Context must not be null"); int exitCode = 0; try { try { @@ -1195,6 +1201,9 @@ public class SpringApplication { generators.addAll(exitCodeGenerators); generators.addAll(beans); exitCode = generators.getExitCode(); + if (exitCode != 0) { + context.publishEvent(new ExitCodeEvent(context, exitCode)); + } } finally { close(context); diff --git a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 92f0afd538..34734e3d26 100644 --- a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -549,6 +549,8 @@ public class SpringApplicationTests { @Test public void exitWithExplicitCode() throws Exception { SpringApplication application = new SpringApplication(ExampleConfig.class); + ExitCodeListener listener = new ExitCodeListener(); + application.addListeners(listener); application.setWebEnvironment(false); this.context = application.run(); assertNotNull(this.context); @@ -560,6 +562,7 @@ public class SpringApplicationTests { } })); + assertThat(listener.getExitCode(), equalTo(2)); } @Test @@ -574,6 +577,8 @@ public class SpringApplicationTests { } }; + ExitCodeListener listener = new ExitCodeListener(); + application.addListeners(listener); application.setWebEnvironment(false); try { application.run(); @@ -582,6 +587,7 @@ public class SpringApplicationTests { catch (IllegalStateException ex) { } verify(handler).registerExitCode(11); + assertThat(listener.getExitCode(), equalTo(11)); } @Test @@ -982,4 +988,18 @@ public class SpringApplicationTests { } + private static class ExitCodeListener implements ApplicationListener { + + private int exitCode; + + @Override + public void onApplicationEvent(ExitCodeEvent event) { + this.exitCode = event.getExitCode(); + } + + public int getExitCode() { + return this.exitCode; + } + + } }