'Missing ErrorController interface in Spring Boot

I am trying to implement a custom replacement for the Whitelabel error page in a Spring Boot application using Spring 5.3.15 and Java 17.

According to the many tutorials I found it should be trivial:

  • Implement a custom controller that implements the ErrorController interface
  • A method with a request mapping for /error
  • Design an attractive error.jsp page.

I have spring-boot-starter-web in my POM and I see all other Spring MVC classes, but there is no ErrorController interface in my classpath.

What am I missing? Has Spring changed and there is a new way to implement a generic custom error page?

NOTE: Code not yet included to avoid noise. EDIT: Added some relevant code per OAPiet's request.

EDIT: I located the current spring-boot-autoconfigure.jar and navigated to org.springframework.boot.autoconfigure.web, the package that is supposed to contain ErrorController.class and it is not there. I think this indicates that the approach for creating a custom error page has indeed changed.

Code pieces:

  • SpringConfig (all of the relevant configuration is here, application.properties does not yet contain anything related to the error page:
@Configuration
@EnableAutoConfiguration(exclude= {DataSourceAutoConfiguration.class})
@ComponentScan(basePackages= {"my.app.pkg", "my.error.controller.pkg"})
@PropertySources({
  @PropertySource(value="classpath:application_PROD.properties", ignoreResourceNotFound=true),
  @PropertySource(value="classpath:application_DEV.properties", ignoreResourceNotFound=true),
})
public class SpringConfig {
  @Bean
  public InternalResourceViewResolver resolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setViewClass(JstlView.class);
    resolver.setPrefix("/WEB-INF/jsp/");
    resolver.setSuffix(".jsp");
    return resolver;
  }
}
  • MyErrorController (Just a skeleton for now. I want a controller so that I can supply additional values to display in the error.jsp page. Problem is that the ErrorController interface has either been moved or removed.):
@Controller
public class MyErrorController implements WebUtils, JsonUtils {
  @RequestMapping(value={"/error"}, method=RequestMethod.GET)
  public String unexpectedErrors(Model model, HttpServletRequest request) {
    Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
    Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
    
    model.addAttribute("statusCode",              statusCode);
    model.addAttribute("exception",               exception);
    return "err";
  }
}

As requested, adding a screenshot of spring-boot-autoconfigure-2.6.3.jar showing the org.springframework.boot.web.servlet.error package where ErrorController should be but isn't.

screenshot

Also, here is my POM:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>net.cndc</groupId>
    <artifactId>myWebApp</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>myWebApp</name>
    <packaging>war</packaging>
    
    <properties>
        <java.version>17</java.version>
        <azure.version>3.13.0</azure.version>
    </properties>
    
    <dependencies>
    <!-- starters -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.azure.spring</groupId>
            <artifactId>azure-spring-boot-starter-active-directory</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
    <!-- JSP -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.1</version>
      <scope>provided</scope>
    </dependency>
    <!-- JSTL -->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>${jstl.version}</version>
    </dependency>
    
    <!-- CNDC library(ies) -->
    <dependency>
      <groupId>my.group</groupId>
      <artifactId>my-lib</artifactId>
      <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>my.group</groupId>
      <artifactId>my-db-xyz-api</artifactId>
      <version>0.0.1-SNAPSHOT</version>
    </dependency>
        
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.azure.spring</groupId>
                <artifactId>azure-spring-boot-bom</artifactId>
                <version>${azure.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
      <dependency>
        <groupId>my.group</groupId>
        <artifactId>bom-pom-master</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <filtering>false</filtering>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>false</filtering>
      </resource>
    </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

And my bom-pom-master:

<?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>my.group</groupId>
  <artifactId>bom-pom-master</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>

  <name>bom-pom-master</name>
  <url>http://www.chickasaw.net</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.release>17</maven.compiler.release>
    <commons.io.version>2.11.0</commons.io.version>
    <commons.lang.version>3.12.0</commons.lang.version>
    <commons.text.version>1.9</commons.text.version>
    <httpclient.version>4.5.13</httpclient.version>
    <jackson.version>2.12.5</jackson.version>
    <jaxb.version>2.3.1</jaxb.version>
    <jjwt.version>0.9.1</jjwt.version>
    <junit.version>4.11</junit.version>
    <log4j2.version>2.17.1</log4j2.version>
    <servlet.version>4.0.1</servlet.version>
    <spring.version>5.3.15</spring.version>
    <spring-security.version>5.6.1</spring-security.version>
  </properties>

  <dependencies>
    <!-- apache commons -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>${commons.io.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>${commons.lang.version}</version>
    </dependency>          
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-text</artifactId>
      <version>${commons.text.version}</version>
    </dependency>    
    
    <!-- Log4j -->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    
    <!-- JJWT, library to add JWT bearer token support -->
    <dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt</artifactId>
      <version>0.9.1</version>
    </dependency>    
    <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.3.1</version>
    </dependency>
    
    <!-- Jackson JSON -->
    <dependency>  <!-- Jackson -->
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.12.5</version>
    </dependency>
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.5.13</version>
    </dependency>
    
    <!-- server -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>
    
    <!-- spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>${spring-security.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <version>${spring-security.version}</version>
    </dependency>

    <!-- junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <filtering>false</filtering>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>false</filtering>
      </resource>
    </resources>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.1</version>
          <configuration>
            <release>${maven.compiler.release}</release>
            <debug>true</debug>
          </configuration>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>



Solution 1:[1]

Add this configuration in: application.properties

# Disable the white label error page
server.error.whitelabel.enabled=false


# If you need to mapping in a result of a rest services
server.error.path=/error

The HTML error page have to be in resources/templates/error.html

or

For JSP page: webapp/WEB-INF/views/error.jsp

In application.properties:

spring.mvc.view.prefix= /WEB-INF/views/
spring.mvc.view.suffix= .jsp

It would be very helpful if you show some code for helping you.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 oaPiet