Spring boot provides various ways to return a custom exit code on application exit. In this tutorials, we will go through each of them.
Implementing ExitCodeGenerator
Spring beans can implement org. springframework. boot. Exit Code Generator interface and return exit code from its getExitCode method. We must also explicitly call SpringApplication.exit(..) method as shown in the following example;
@SpringBootConfiguration
public class ExampleExitCodeGenerator {
@Bean
MyBean myBean() {
return new MyBean();
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ExampleExitCodeGenerator.class, args);
MyBean myBean = context.getBean(MyBean.class);
myBean.doSomething();
int exitValue = SpringApplication.exit(context);
System.exit(exitValue);
}
private static class MyBean implements ExitCodeGenerator {
public void doSomething() {
System.out.println("in doSomething()");
}
@Override
public int getExitCode() {
return 500;
}
}
}Output . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.3.RELEASE)
2025-10-29 13:55:17.691 INFO 3716 --- [enerator.main()] c.l.example.ExampleExitCodeGenerator : Starting ExampleExitCodeGenerator on JoeMsi with PID 3716 (D:\LogicBig\example-projects\spring-boot\boot-application-exit-code\target\classes started by joe2 in D:\LogicBig\example-projects\spring-boot\boot-application-exit-code) 2025-10-29 13:55:17.698 INFO 3716 --- [enerator.main()] c.l.example.ExampleExitCodeGenerator : No active profile set, falling back to default profiles: default 2025-10-29 13:55:18.318 INFO 3716 --- [enerator.main()] c.l.example.ExampleExitCodeGenerator : Started ExampleExitCodeGenerator in 1.111 seconds (JVM running for 10.474) in doSomething()
Process finished with exit code 500
Listening to ExitCodeEvent
Spring boot fires ExitCodeEvent on finding application specific exit codes. We can listen to that event as shown in this example. Also check out our Spring core events handling tutorial.
@SpringBootConfiguration
public class ExampleExitCodeEvent {
@Bean
MyBean myBean() {
return new MyBean();
}
@Bean
MyBean2 myBean2() {
return new MyBean2();
}
public static void main(String[] args) {
ApplicationContext context =
SpringApplication.run(ExampleExitCodeEvent.class, args);
MyBean myBean = context.getBean(MyBean.class);
myBean.doSomething();
int exit = SpringApplication.exit(context);
System.exit(exit);
}
private static class MyBean implements ExitCodeGenerator {
public void doSomething() {
System.out.println("in doSomething()");
}
@Override
public int getExitCode() {
return 100;
}
}
private static class MyBean2 {
@EventListener
public void exitEvent(ExitCodeEvent event) {
System.out.println("-- ExitCodeEvent --");
System.out.println("exit code: " + event.getExitCode());
}
}
}Output . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.3.RELEASE)
2025-10-29 13:55:32.171 INFO 19124 --- [odeEvent.main()] c.logicbig.example.ExampleExitCodeEvent : Starting ExampleExitCodeEvent on JoeMsi with PID 19124 (D:\LogicBig\example-projects\spring-boot\boot-application-exit-code\target\classes started by joe2 in D:\LogicBig\example-projects\spring-boot\boot-application-exit-code) 2025-10-29 13:55:32.175 INFO 19124 --- [odeEvent.main()] c.logicbig.example.ExampleExitCodeEvent : No active profile set, falling back to default profiles: default 2025-10-29 13:55:32.958 INFO 19124 --- [odeEvent.main()] c.logicbig.example.ExampleExitCodeEvent : Started ExampleExitCodeEvent in 1.25 seconds (JVM running for 14.336) in doSomething() -- ExitCodeEvent -- exit code: 100
Process finished with exit code 100
Throwing a custom exception from run method of ApplicationRunner/CommandLineRunner
The custom exception class must implement ExitCodeGenerator interface. This only works if this exception is thrown in ApplicationRunner/CommandLineRunner run method.
Here, we don't have to explicitly call SpringApplication.exit(..)
@SpringBootConfiguration
public class ExampleExitCodeGeneratorException {
@Bean
ApplicationRunner appRunner() {
return new MyAppRunner();
}
@Bean
MyBean myBean() {
return new MyBean();
}
public static void main(String[] args) {
SpringApplication.run(ExampleExitCodeGeneratorException.class, args);
}
private static class MyAppRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("in ApplicationRunner#run method");
throw new MyExitCodeException("test exception");
}
}
private static class MyExitCodeException extends RuntimeException
implements ExitCodeGenerator {
public MyExitCodeException(String message) {
super(message);
}
@Override
public int getExitCode() {
return 5;
}
}
private static class MyBean {
@EventListener
public void exitEvent(ExitCodeEvent event) {
System.out.println("-- ExitCodeEvent --");
System.out.println("exit code: " + event.getExitCode());
}
}
}Output . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.3.RELEASE)
2025-10-29 13:55:43.402 INFO 21004 --- [xception.main()] c.l.e.ExampleExitCodeGeneratorException : Starting ExampleExitCodeGeneratorException on JoeMsi with PID 21004 (D:\LogicBig\example-projects\spring-boot\boot-application-exit-code\target\classes started by joe2 in D:\LogicBig\example-projects\spring-boot\boot-application-exit-code) 2025-10-29 13:55:43.407 INFO 21004 --- [xception.main()] c.l.e.ExampleExitCodeGeneratorException : No active profile set, falling back to default profiles: default in ApplicationRunner#run method -- ExitCodeEvent -- exit code: 5 2025-10-29 13:55:44.205 ERROR 21004 --- [xception.main()] o.s.boot.SpringApplication : Application startup failed
java.lang.IllegalStateException: Failed to execute ApplicationRunner at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:770) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:757) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at com.logicbig.example.ExampleExitCodeGeneratorException.main(ExampleExitCodeGeneratorException.java:20) [classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:na] at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:294) [exec-maven-plugin-1.5.0.jar:na] at java.lang.Thread.run(Thread.java:748) [na:na] Caused by: com.logicbig.example.ExampleExitCodeGeneratorException$MyExitCodeException: test exception at com.logicbig.example.ExampleExitCodeGeneratorException$MyAppRunner.run(ExampleExitCodeGeneratorException.java:28) ~[classes/:na] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:767) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] ... 12 common frames omitted
[WARNING] java.lang.reflect.InvocationTargetException Caused by: java.lang.IllegalStateException: Failed to execute ApplicationRunner at org.springframework.boot.SpringApplication.callRunner (SpringApplication.java:770) at org.springframework.boot.SpringApplication.callRunners (SpringApplication.java:757) at org.springframework.boot.SpringApplication.afterRefresh (SpringApplication.java:747) at org.springframework.boot.SpringApplication.run (SpringApplication.java:315) at org.springframework.boot.SpringApplication.run (SpringApplication.java:1162) at org.springframework.boot.SpringApplication.run (SpringApplication.java:1151) at com.logicbig.example.ExampleExitCodeGeneratorException.main (ExampleExitCodeGeneratorException.java:20) Caused by: com.logicbig.example.ExampleExitCodeGeneratorException$MyExitCodeException: test exception at com.logicbig.example.ExampleExitCodeGeneratorException$MyAppRunner.run (ExampleExitCodeGeneratorException.java:28) at org.springframework.boot.SpringApplication.callRunner (SpringApplication.java:767) at org.springframework.boot.SpringApplication.callRunners (SpringApplication.java:757) at org.springframework.boot.SpringApplication.afterRefresh (SpringApplication.java:747) at org.springframework.boot.SpringApplication.run (SpringApplication.java:315) at org.springframework.boot.SpringApplication.run (SpringApplication.java:1162) at org.springframework.boot.SpringApplication.run (SpringApplication.java:1151) at com.logicbig.example.ExampleExitCodeGeneratorException.main (ExampleExitCodeGeneratorException.java:20)
Process finished with exit code 5
Note that, we are still able to receive ExitCodeEvent in above example.
Using ExitCodeExceptionMapper
ExitCodeExceptionMapper is a strategy interface that can be used to provide a mapping between exceptions and exit codes as shown in the following example.
@SpringBootConfiguration
public class ExampleExitCodeExceptionMapper {
@Bean
MyBean myBean() {
return new MyBean();
}
@Bean
ApplicationRunner appRunner() {
return new MyAppRunner();
}
@Bean
ExitCodeExceptionMapper exitCodeExceptionMapper() {
return exception -> {
if (exception.getCause() instanceof MyException) {
return 10;
}
return 1;
};
}
public static void main(String[] args) {
SpringApplication.run(ExampleExitCodeExceptionMapper.class, args);
}
private static class MyAppRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("in command line");
if (true) throw new MyException("test");
}
}
private static class MyBean {
@EventListener
public void exitEvent(ExitCodeEvent event) {
System.out.println("-- ExitCodeEvent --");
System.out.println("exit code: " + event.getExitCode());
}
}
private static class MyException extends RuntimeException {
public MyException(String message) {
super(message);
}
}
}Output . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.3.RELEASE)
2025-10-29 13:55:48.875 INFO 12148 --- [onMapper.main()] c.l.e.ExampleExitCodeExceptionMapper : Starting ExampleExitCodeExceptionMapper on JoeMsi with PID 12148 (D:\LogicBig\example-projects\spring-boot\boot-application-exit-code\target\classes started by joe2 in D:\LogicBig\example-projects\spring-boot\boot-application-exit-code) 2025-10-29 13:55:48.878 INFO 12148 --- [onMapper.main()] c.l.e.ExampleExitCodeExceptionMapper : No active profile set, falling back to default profiles: default in command line -- ExitCodeEvent -- exit code: 10 2025-10-29 13:55:49.570 ERROR 12148 --- [onMapper.main()] o.s.boot.SpringApplication : Application startup failed
java.lang.IllegalStateException: Failed to execute ApplicationRunner at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:770) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:757) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] at com.logicbig.example.ExampleExitCodeExceptionMapper.main(ExampleExitCodeExceptionMapper.java:32) [classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:na] at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:294) [exec-maven-plugin-1.5.0.jar:na] at java.lang.Thread.run(Thread.java:748) [na:na] Caused by: com.logicbig.example.ExampleExitCodeExceptionMapper$MyException: test at com.logicbig.example.ExampleExitCodeExceptionMapper$MyAppRunner.run(ExampleExitCodeExceptionMapper.java:40) ~[classes/:na] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:767) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE] ... 12 common frames omitted
[WARNING] java.lang.reflect.InvocationTargetException Caused by: java.lang.IllegalStateException: Failed to execute ApplicationRunner at org.springframework.boot.SpringApplication.callRunner (SpringApplication.java:770) at org.springframework.boot.SpringApplication.callRunners (SpringApplication.java:757) at org.springframework.boot.SpringApplication.afterRefresh (SpringApplication.java:747) at org.springframework.boot.SpringApplication.run (SpringApplication.java:315) at org.springframework.boot.SpringApplication.run (SpringApplication.java:1162) at org.springframework.boot.SpringApplication.run (SpringApplication.java:1151) at com.logicbig.example.ExampleExitCodeExceptionMapper.main (ExampleExitCodeExceptionMapper.java:32) Caused by: com.logicbig.example.ExampleExitCodeExceptionMapper$MyException: test at com.logicbig.example.ExampleExitCodeExceptionMapper$MyAppRunner.run (ExampleExitCodeExceptionMapper.java:40) at org.springframework.boot.SpringApplication.callRunner (SpringApplication.java:767) at org.springframework.boot.SpringApplication.callRunners (SpringApplication.java:757) at org.springframework.boot.SpringApplication.afterRefresh (SpringApplication.java:747) at org.springframework.boot.SpringApplication.run (SpringApplication.java:315) at org.springframework.boot.SpringApplication.run (SpringApplication.java:1162) at org.springframework.boot.SpringApplication.run (SpringApplication.java:1151) at com.logicbig.example.ExampleExitCodeExceptionMapper.main (ExampleExitCodeExceptionMapper.java:32)
Process finished with exit code 10
Example ProjectDependencies and Technologies Used: - Spring Boot 1.5.3.RELEASE
Corresponding Spring Version 4.3.8.RELEASE - spring-boot-starter : Core starter, including auto-configuration support, logging and YAML.
- JDK 1.8
- Maven 3.3.9
|