Search code examples
javagradleannotation-processing

How to fix ClassNotFoundException: org.springframework.boot.configurationprocessor.json.JSONObject error?


I am getting following error when I deploy my application:

java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/json/JSONObject
    at com.rossmoor.jenarktomds.services.web.GrfPortalClientServiceImpl.getAccessToken(GrfPortalClientServiceImpl.java:53)
    at com.rossmoor.jenarktomds.services.web.GrfPortalClientServiceImpl.downloadAllGrfUsers(GrfPortalClientServiceImpl.java:325)
    at com.rossmoor.jenarktomds.services.DataProcessorImpl.testGrfApi(DataProcessorImpl.java:1939)
    at com.rossmoor.jenarktomds.services.DataProcessorImpl$$FastClassBySpringCGLIB$$716e474b.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
    at com.rossmoor.jenarktomds.services.DataProcessorImpl$$EnhancerBySpringCGLIB$$21e20f26.testGrfApi(<generated>)
    at com.rossmoor.jenarktomds.JenarkToMdsApplication.run(JenarkToMdsApplication.java:76)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:771)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:755)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
    at com.rossmoor.jenarktomds.JenarkToMdsApplication.main(JenarkToMdsApplication.java:59)
    ... 8 more
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.configurationprocessor.json.JSONObject
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    ... 30 more

The code that causes the error looks like this:

   // create request body
    JSONObject request = new JSONObject();
    request.put("username", configurationProperties.getGrfPortalUserName());
    request.put("password", configurationProperties.getGrfPortalUserPwd());

    // set headers
    HttpHeaders headers = new HttpHeaders();
    headers.add("API-Key", "{{apiKey}}");
    headers.add("Authorization", "Basic {{authorization}}");

    headers.setContentType(MediaType.APPLICATION_JSON);

    HttpEntity<String> entity = new HttpEntity<>(request.toString(), headers);

    if (Logger.isInfoEnabled()) Logger.info("Sending request to GRF Portal");
    // send request and parse result
    ResponseEntity<String> loginResponse = restTemplate
            .exchange(GRF_LOGIN_URL, HttpMethod.POST, entity, String.class);
    if (loginResponse.getStatusCode() == HttpStatus.OK)
    {
        JSONObject userJson = new JSONObject(loginResponse.getBody());

        if (Logger.isInfoEnabled()) Logger.info("Token Data = " + userJson);

        this.AccessToken = String.valueOf(userJson.get("token"));

        System.out.println("AccessToken = " + AccessToken);
    }
    else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED)
    {
        // nono... bad credentials
        if (Logger.isErrorEnabled()) Logger.error("nono... bad credentials");
    }

Please note the error occurs only in deployment on production server. I take following steps to deploy:

  1. Build the app using Gradle build command.
  2. Convert Jar file to exe using Jar2exe
  3. Deploy the exe file as a windows service (Using an installer program).

When I run the program on development or production server using IntelliJ idea the error does not occur. What could be problem here?

plugins {
    id 'org.springframework.boot' version '2.7.0'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.rossmoor'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-data-rest'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'com.microsoft.sqlserver:mssql-jdbc'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"

//    // https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-core
//    implementation group: 'org.hibernate.orm', name: 'hibernate-core', version: '6.0.2.Final'
//
//    // https://mvnrepository.com/artifact/jakarta.transaction/jakarta.transaction-api
//    implementation group: 'jakarta.transaction', name: 'jakarta.transaction-api', version: '2.0.1'
//
//    // https://mvnrepository.com/artifact/jakarta.persistence/jakarta.persistence-api
//    implementation group: 'jakarta.persistence', name: 'jakarta.persistence-api', version: '3.1.0'

    // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0'

    // https://mvnrepository.com/artifact/commons-validator/commons-validator
    implementation group: 'commons-validator', name: 'commons-validator', version: '1.7'

    // https://mvnrepository.com/artifact/org.mapstruct/mapstruct
    implementation group: 'org.mapstruct', name: 'mapstruct', version: '1.5.2.Final'

    // https://mvnrepository.com/artifact/com.google.code.gson/gson
    implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.1'

    implementation files('lib/connection-manager-2.0.0.1.jar')
    implementation files('lib/Utils-2.0.0.1.jar')
    implementation files('lib/TinyLog-2.0.0.1.jar')
}

tasks.named('test') {
    useJUnitPlatform()
}

Solution

  • This comes from your build.gradle:

    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    

    Since you have declared as compileOnly here:

    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    }
    

    but apparently the JSONException is used at run time, it makes your app fail when packaging with Jar2exe. The solution to this could be to include the whole dependency like so:

    implementation 'org.springframework.boot:spring-boot-configuration-processor'