Solution to Spring Boot Project Startup Failure

  • 2021-09-05 00:09:16
  • OfStack

Does the Spring Boot project fail frequently and display a lot of error messages, such as the following exception when the port is repeatedly bound:


***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

This should be familiar to everyone!

The error message can be understood by everyone, but it is very unfriendly. So, how did Spring Boot realize such an abnormal error message output? Today, the stack leader shared an easy-to-understand way to play Spring Boot startup failure, so that the new intern can see the problem in 1 second.

If you are not familiar with Spring Boot, or just use it simply, it is recommended that you study it in depth. It is recommended that this Spring Boot learning warehouse be welcomed. Star attention is welcome:

https://github.com/javastacks/spring-boot-best-practice

Introduction of Failure Analyzers

Many "Failure Analyzers", or "Failure Analyzers", are registered in Spring Boot, and the startup failure scenarios in Spring Boot are intercepted and processed by these failure analyzers.

Spring Boot provides FailureAnalyzers Interface:


package org.springframework.boot.diagnostics;

/**
 * A {@code FailureAnalyzer} is used to analyze a failure and provide diagnostic
 * information that can be displayed to the user.
 *
 * @author Andy Wilkinson
 * @since 1.4.0
 */
@FunctionalInterface
public interface FailureAnalyzer {

 /**
 * Returns an analysis of the given {@code failure}, or {@code null} if no analysis
 * was possible.
 * @param failure the failure
 * @return the analysis or {@code null}
 */
 FailureAnalysis analyze(Throwable failure);

}

The purpose of this interface is to analyze startup failure exceptions and display useful diagnostic information to the user.

Spring Boot Built-in Registered All Failure Analyzers are in this file:

/org/springframework/boot/spring-boot/2.3.5.RELEASE/spring-boot-2.3.5.RELEASE-sources.jar!/META-INF/spring.factories

List of all registered failure analyzers:


# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer

Go back to the above port and repeat the binding startup failure exception, which is registered PortInUseFailureAnalyzer This failure analyzer can see that PortInUseFailureAnalyzer The failure analyzer is in the registration list.

Let's take a look at it again PortInUseFailureAnalyzer Source code of:


/**
 * A {@code FailureAnalyzer} that performs analysis of failures caused by a
 * {@code PortInUseException}.
 *
 * @author Andy Wilkinson
 */
class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> {

 @Override
 protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) {
  return new FailureAnalysis("Web server failed to start. Port " + cause.getPort() + " was already in use.",
   "Identify and stop the process that's listening on port " + cause.getPort() + " or configure this "
     + "application to listen on another port.",
   cause);
 }

}

As long as the application startup process throws PortInUseException The exception is intercepted by the failure analyzer and outputs a readable error message, and now you know how the binding duplicate binding error is output.

Custom Failure Analyzers

From the built-in failure analyzer, we can find that all analyzers inherit this abstract base class: AbstractFailureAnalyzer, which implements FailureAnalyzer interface. Generally, based on this abstract base class, we can realize the extension of custom failure analyzer.

The following stack length shows you how to extend or customize an FailureAnalyzer through two examples.

1. Rewrite the Port Failure Analyzer

For example, the one above PortInUseFailureAnalyzer Output content is English, not very intuitive to see, we can achieve a Chinese port failure analyzer.

Quite simply, create a failure analyzer that inherits the AbstractFailureAnalyzer abstract class:


package cn.javastack.springboot.features.analyzer;

import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.web.server.PortInUseException;

public class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> {

 @Override
 protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) {
  return new FailureAnalysis(" The port you started  " + cause.getPort() + "  Be occupied .",
   " Quickly check the lower port  " + cause.getPort() + "  Is occupied by which program, or forcibly kills the process .",
   cause);
 }

}

Rewrite analyze Method and returns 1 FailureAnalysis Object, FailureAnalysis The three main messages of the class are:


public FailureAnalysis(String description, String action, Throwable cause) {
 this.description = description;
 this.action = action;
 this.cause = cause;
}

That is to show: readable error description, suggested check and fix actions, and original exception.

Then create the META-INF/spring. factories file in your own resource directory and add:


org.springframework.boot.diagnostics.FailureAnalyzer=\
cn.javastack.springboot.features.analyzer.PortInUseFailureAnalyzer

Startup output:


***************************
APPLICATION FAILED TO START
***************************

Description:

 The port you started  8080  Be occupied .

Action:

 Quickly check the lower port  8080  Is occupied by which program, or forcibly kills the process .

Is it much clearer to re-realize 1 in this way? Interns can understand it!

2. Custom Failure Analyzer

Below to customize a new failure analyzer, so that everyone can know the failure analyzer more clearly.

We manually threw a custom exception during the process of creating Bean:


@Bean
public CommandLineRunner commandLineRunner(){
 throw new JavastackException("Java Technical stack exception ");
}

Add 1 Failure Analyzer to intercept this exception:


package cn.javastack.springboot.features.analyzer;

import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;

public class JavastackFailureAnalyzer extends AbstractFailureAnalyzer<JavastackException> {

 @Override
 protected FailureAnalysis analyze(Throwable rootFailure, JavastackException cause) {
  return new FailureAnalysis("Java There is an exception in the technology stack... ",
   " Go and check it quickly 1 Get off! ",
   cause);
 }

}

Add registration:


package org.springframework.boot.diagnostics;

/**
 * A {@code FailureAnalyzer} is used to analyze a failure and provide diagnostic
 * information that can be displayed to the user.
 *
 * @author Andy Wilkinson
 * @since 1.4.0
 */
@FunctionalInterface
public interface FailureAnalyzer {

 /**
 * Returns an analysis of the given {@code failure}, or {@code null} if no analysis
 * was possible.
 * @param failure the failure
 * @return the analysis or {@code null}
 */
 FailureAnalysis analyze(Throwable failure);

}
0

Startup output:


package org.springframework.boot.diagnostics;

/**
 * A {@code FailureAnalyzer} is used to analyze a failure and provide diagnostic
 * information that can be displayed to the user.
 *
 * @author Andy Wilkinson
 * @since 1.4.0
 */
@FunctionalInterface
public interface FailureAnalyzer {

 /**
 * Returns an analysis of the given {@code failure}, or {@code null} if no analysis
 * was possible.
 * @param failure the failure
 * @return the analysis or {@code null}
 */
 FailureAnalysis analyze(Throwable failure);

}
1

If the failure analyzer is not registered, this custom exception will not be intercepted by the built-in failure analyzer, and will output a lot of exception information. Using the failure analyzer, you can intuitively see what the error is and how to fix it.

Summarize

The failure analyzer provided by Spring Boot replaces a lot of error exception information with friendly error information and repair suggestions, which can help us locate application startup failures more intuitively. Have you learned?

All the sample source code for this article has been uploaded to Github:

https://github.com/javastacks/spring-boot-best-practice

Welcome everyone to pay attention to Star, which will be updated continuously.

The above is the Spring Boot project startup failure solution details, more about Spring Boot project startup failure information please pay attention to other related articles on this site!


Related articles: