0

In my app we are force to use a tomcat 8.5 because we have to support servlet api 3.1 but we upgradred to spring boot 2.2.6. and now the problem is happening while starting using the embedded tomcat. If I comment out the tomcat version in my pom (getting Tomcat 9) the same code works like a charm.

This my EmbededTomcat code:

@Value("${spring.datasource.url}")
private String jdbcUrl;

@Value("${spring.datasource.username}")
private String jdbcUsername;

@Value("${spring.datasource.password}")
private String jdbcPassword;

@Value("${spring.datasource.driver-class-name}")
private String driverClassName;

@Bean
public TomcatServletWebServerFactory tomcatFactory() {
    log.info("initializing tomcat factory... ");        
    return new TomcatServletWebServerFactory() {

        @Override
        protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
            tomcat.enableNaming();
            return super.getTomcatWebServer(tomcat);
        }

        @Override
        protected void postProcessContext(Context context) {    
            log.info("initializing tomcat factory JDNI ... ");
            // Adding connection details
            ContextResource resource = new ContextResource();
            resource.setName("jdbc/DB");
            resource.setType(DataSource.class.getName());
            resource.setProperty("driverClassName", driverClassName);
            resource.setProperty("url", jdbcUrl);
            resource.setProperty("username", jdbcUsername);
            resource.setProperty("password", jdbcPassword);

            context.getNamingResources().addResource(resource);
        }
    };
}

On my pom.xml the only change I made are:

<servlet-api.version>3.1.0</servlet-api.version> 
<!-- Forced for embeded tomcats since tomcat 9 force servlet 4.0 -->
<tomcat.version>8.5.54</tomcat.version>

And this is the full stack error:

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

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:175)

The following method did not exist:

    org.apache.tomcat.util.modeler.Registry.disableRegistry()V

The method's class, org.apache.tomcat.util.modeler.Registry, is available from the following locations:

    jar:file:/C:/Users/localAdministrator/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.54/tomcat-embed-core-8.5.54.jar!/org/apache/tomcat/util/modeler/Registry.class

It was loaded from the following location:

    file:/C:/Users/localAdministrator/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.54/tomcat-embed-core-8.5.54.jar


Action:

Correct the classpath of your application so that it contains a single, compatible version of org.apache.tomcat.util.modeler.Registry

Possible related question:

am trying a Spring boot example but it is showing following error.. what should i do?

creamteam
  • 26
  • 1
  • 3

3 Answers3

0

It's pretty ugly solution and probably it won't work, but you can give it a chance.

  1. Create in your app package structure like in apache's lib /java/src/main/org/apache/tomcat/util/modeler/
  2. Put Registry class from Tomcat 8 in this package.
  3. Add stub method disableRegistry, something like

    public static synchronized void disableRegistry() {
        return new NoDescriptorRegistry();
    }
    
Danila Zharenkov
  • 1,720
  • 1
  • 15
  • 27
  • 2
    that's is not a valid solution since there are many other classes related that are also changed from tomcat 8 to 9. :( – creamteam Apr 14 '20 at 17:20
0

Spring boot 2.2.6 expects tomcat 9.0.x minimum. ref - https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies/2.2.6.RELEASE

To stay with spring 2.2.6 and alongside bringing tomcat 8.5.x, perhaps you could override 'spring-boot-starter-tomcat' artifact (hailing from spring-boot-parent:2.2.6) for compatible & desired tomcat version.

i.e. spring-boot-starter-tomcat:2.0.7.RELEASE would work nicely with tomcat 8.5.x

Declare the following dependency in the pom file

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <version>2.0.7.RELEASE</version>
</dependency>
Sats
  • 1,061
  • 9
  • 12
0

This is the pom.xml file that worked for me:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.9.RELEASE</version>
    <relativePath/>
</parent>

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



<dependencies>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <!--<exclusions>
            <exclusion>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-jdbc</artifactId>
            </exclusion>
        </exclusions>-->
    </dependency>
    
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <version>2.0.7.RELEASE</version>
    </dependency>
    

    <!-- Include Servlet API -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>

    
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>-->
    </dependencies>
</dependencyManagement>


...
Taras Gleb
  • 158
  • 2
  • 5