Search code examples
javaspring-bootservlet-filtersjakarta-migration

Using org.commonsources.correlation.filter.CorrelationHeaderFilter throws Caused by: java.io.IOException: Failed to load class [javax.servlet.Filter]


I have a Spring Boot app which is on 2.7.12 version (running on Java 8). I am upgrading it to Spring Boot 3.2.5 and installed Java 17. Now, I get below errors.

[12-09-2024 12:06:52.402] [] [main] [WARN ] [o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext.refresh] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: I/O failure while processing configuration class [org.commonsources.correlation.filter.CorrelationHeaderFilter]
[12-09-2024 12:06:52.405] [] [main] [INFO ] [o.s.b.a.l.ConditionEvaluationReportLogger.logMessage] - 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
[12-09-2024 12:06:52.414] [] [main] [ERROR] [o.s.boot.SpringApplication.reportFailure] - Application run failed
org.springframework.beans.factory.BeanDefinitionStoreException: I/O failure while processing configuration class [org.commonsources.correlation.filter.CorrelationHeaderFilter]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:251)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189)
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:314)
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:246)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:165)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:416)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:289)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:788)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:606)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:334)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
    at com.myproject.ecommerce.emc.EmcApplication.main(EmcApplication.java:19)
Caused by: java.io.IOException: Failed to load class [javax.servlet.Filter]
    at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:627)
    at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getInterfaces(ConfigurationClassParser.java:956)
    at org.springframework.context.annotation.ConfigurationClassParser.processInterfaces(ConfigurationClassParser.java:396)
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:342)
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:246)
    ... 18 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.servlet.Filter
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:467)
    at org.springframework.util.ClassUtils.forName(ClassUtils.java:304)
    at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:624)

I see that javax have been moved to Jakarta. My gradle file had below dependency

implementation group: 'javax.jms', name: 'javax.jms-api', version: '2.0.1'

which I removed and added corresponding Jakarta dependency

implementation group: 'jakarta.jms', name: 'jakarta.jms-api', version: '3.1.0'

Is there a solution to it?

Below is the build.gradle file

buildscript {
    ext {
        springBootVersion = '3.2.5'
    }

    repositories {
        maven {
            url "http://repourl.com:8081/repository/maven-proxy-group/"
            allowInsecureProtocol = true
        }
    }

    dependencies {
        classpath "gradle.plugin.com.sourcemuse.gradle.plugin:GradleMongoPlugin:1.0.7"
        classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.8"
        //classpath "net.ltgt.gradle:gradle-apt-plugin:0.20"
        classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'org.sonarqube'
apply plugin: "com.sourcemuse.mongo"
apply plugin: 'jacoco'

group = 'com.test.abc'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 17

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    maven {
        url "http://repourl.com:8081/repository/maven-proxy-group/"
        allowInsecureProtocol = true
    }
}

jacocoTestReport {
    reports {
        xml.enabled false
        csv.enabled false
        html.destination file("/jacoco/code-coverage")
    }
}

jar {
    enabled = false
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-aop'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
    implementation 'org.springframework.boot:spring-boot-starter-data-rest'
    implementation (group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa')
    //implementation group: 'org.springframework', name: 'spring-jms', version: '6.1.6'

    implementation 'org.springframework.kafka:spring-kafka'
    implementation(group: 'org.springframework', name: 'spring-jms')
    implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.7.0'
    implementation group: 'org.springdoc', name: 'springdoc-openapi-webmvc-core', version: '1.7.0'
    implementation 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    // External Dependencies
    implementation files('lib/ojdbc8.jar')
    implementation 'org.commonsources:correlation:1.0.7.RELEASE'

    annotationProcessor group: 'org.mapstruct', name: 'mapstruct-processor', version: '1.3.0.Final'
    implementation "org.mapstruct:mapstruct:1.3.0.Final"

    implementation group: 'org.yaml', name: 'snakeyaml', version: '2.0'

    implementation 'io.micrometer:micrometer-registry-prometheus'
    implementation 'io.micrometer:micrometer-core'
    implementation 'com.github.ozlerhakan:poiji:3.0.0'
    implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-csv', version: '2.14.1'

    //implementation group: 'javax.jms', name: 'javax.jms-api', version: '2.0.1'

    implementation group: 'jakarta.jms', name: 'jakarta.jms-api', version: '3.1.0'

    implementation group: 'xerces', name: 'xercesImpl', version: '2.12.2'
    implementation 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.4.0'
    implementation group: 'org.mongodb', name: 'mongodb-driver-sync', version: '4.7.2'
    implementation group: 'org.mongodb', name: 'mongodb-driver-core', version: '4.7.2'
    implementation group: 'org.mongodb', name: 'mongodb-driver-reactivestreams', version: '4.7.2'
    implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-csv', version: '2.14.1'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.14.1'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.14.1'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.14.1'
    implementation group: 'org.dom4j', name: 'dom4j', version: '2.1.3'
    implementation group: 'com.google.guava', name: 'guava', version: '31.1-jre'
    //  implementation "ch.qos.logback:logback-classic:1.4.5"
    //  implementation "ch.qos.logback:logback-core:1.4.5"
    implementation 'org.apache.kafka:kafka-clients:7.3.3-ce'
    implementation group: 'org.apache.commons', name: 'commons-compress', version: '1.23.0'
    implementation group: 'org.xerial.snappy', name: 'snappy-java', version: '1.1.10.2'

    //Test Dependencies
    //  testImplementation group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'io.projectreactor:reactor-test'
    //testImplementation group: 'com.h2database', name: 'h2', version: '2.1.214'
    testImplementation 'junit:junit:4.13.2'
}

task integrationTest(type: Test) {
    runWithMongoDb = true
}

Solution

  • The exception stacktrace indicates the problem is with the class org.commonsources.correlation.filter.CorrelationHeaderFilter, and suggests it implements javax.servlet.Filter instead of jakarta.servlet.Filter.

    You will need to find out if the library providing this class — org.commonsources:correlation — has a newer or alternative version that supports Jakarta EE 9+ (i.e. implements jakarta.servlet.Filter).

    However, it looks like the version you're using is the latest version, so you're probably out of luck. You either need to modify its sources and recompile yourself, or find and use some tool to rewrite the bytecode of the library to use the jakarta.* namespace instead of javax.*. Or maybe you can report an issue on that GitHub repository and hope the author wants to do this for you.

    Alternatively, you need to find a replacement library, or get rid of it and live without the functionality this provides you. You could look at Spring Cloud Sleuth as an alternative, I think.