We have upgraded from Spring boot 2.7.12/Java 11 to 3.1.7/Java 17. Some of our endpoints were working as expected while some are failing. One of the failing endpoint has GetMapping(value="/resource/test/") as given below. And the error is

Handler dispatch failed: java.lang.NoSuchMethodError: 'org.springframework.http.HttpStatus org.springframework.http.client.ClientHttpResponse.getStatusCode()'.

Controller:

  @javax.annotation.Resource
  private RestTemplate externalRestTemplate;
  
  
  @GetMapping(value = "/resource/test", produces = MediaType.APPLICATION_PDF_VALUE)
  public ResponseEntity<org.springframework.core.io.Resource> getValue(
          @RequestParam @Size(max = 5)
          @Pattern(regexp = "^[A-Za-z0-9]+$") String code,
          @RequestParam @Size(max = 10)
          @Pattern(regexp = "^[0-9]+$") String key) {
    try {
      org.springframework.core.io.Resource resource = externalValue(code, key);
      if (resource == null) {
        return new ResponseEntity("Not available", HttpStatus.NO_CONTENT);
      }
      return new ResponseEntity<>(resource, HttpStatus.OK);
    } catch (Exception e) {
      return new ResponseEntity("error", HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

    public org.springframework.core.io.Resource externalValue(String code, String key){
        final ResponseEntity<Resource> responseEntity;
        try{
            RequestEntity<String> requestEntity = new RequestEntity<>(getRequestHeaders(), HttpMethod.GET,        buildURIforValue(code, key));
            responseEntity = externalRestTemplate.exchange(requestEntity, org.springframework.core.io.Resource.class);
            return responseEntity.getBody();
        } catch (final RestClientException e) {
            return null;
        }
        catch (final Exception e) {
            return null;
        }
    }

    public HttpHeaders getRequestHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_PDF, MediaType.APPLICATION_OCTET_STREAM));
        return headers;
    }

    private URI buildURIforValue(String code, String key){
        return UriComponentsBuilder.fromUriString("https://wwwsb.testxyz.com/test/value.json"+"?"+
                "key"+"="+key
                +"&"+"vin"+"="+vin).build().toUri();
    }

build.gradle:

plugins {
    id 'java'
    id 'maven-publish'
    id 'org.springframework.boot' version '3.1.7'
    id 'gradle-boost' version '5.0.1'
    id 'org.sonarqube' version "4.2.1.3168"
    id 'com.google.cloud.tools.jib' version '3.4.0'
    id 'com.jfrog.artifactory' version '5.+'
    id 'jacoco'
}

group = 'com.test.one'
version = gradleBoost.fn.gitVersion()
println "Build Version = ${version ?: '[none]'}"

sourceCompatibility = JavaVersion.VERSION_17

dependencies {
    // Bill Of Materials Imports
    bomImport platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
    bomImport platform('com.google.cloud:spring-cloud-gcp-dependencies:4.8.4')

    //Core libraries
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'com.testone.cloudnative:spring-boot-starter-testone:5.0.0'

    // Spring Integration
    implementation 'org.springframework.integration:spring-integration-core'

    //gcp logging
    implementation 'com.google.cloud:spring-cloud-gcp-starter'
    implementation 'com.google.cloud:spring-cloud-gcp-starter-trace'
    implementation 'com.google.cloud:spring-cloud-gcp-starter-logging'
    //implementation 'org.springframework.cloud:spring-cloud-sleuth-api:3.1.10'

    //security
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'com.testone.cloudnative:spring-base-security:2.0.0'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.security.oauth:spring-security-oauth2:2.5.0.RELEASE'

    //secrets manager
    implementation 'com.google.cloud:spring-cloud-gcp-starter-secretmanager'

    implementation 'com.testone.spring.filters:forwarded-auth-header-rewrite:1.0.0'

    //database
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.flywaydb:flyway-core'
    localOnly 'com.h2database:h2'
    implementation 'org.postgresql:postgresql'
    implementation 'com.google.cloud.sql:postgres-socket-factory:1.13.1'

    implementation 'com.google.cloud:spring-cloud-gcp-starter'

    //SRE Metrics
    implementation 'com.testone.mpp.pe.sre:metrics:3.0.5'

    //Feign
    implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.0.4'

    // https://mvnrepository.com/artifact/com.netflix.feign/feign-jackson
    implementation 'com.netflix.feign:feign-jackson:8.18.0'

    //BigTable
    implementation ('com.google.cloud:google-cloud-bigtable:2.27.0')

    implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
    implementation 'org.springframework:spring-core:6.0.16'

    //others
    implementation 'org.springdoc:springdoc-openapi-ui:1.7.0'
    implementation 'org.modelmapper:modelmapper:2.4.5'
    implementation fileTree(dir: "$rootDir/src/main/resources/lib", include: '*.jar')

    implementation 'javax.ws.rs:javax.ws.rs-api:2.1.1'
    implementation 'org.apache.commons:commons-collections4:4.4'

    implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-jakarta-xmlbind-annotations', version: '2.16.1'

    //other
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    implementation 'com.mikesamuel:json-sanitizer:1.2.2'

    implementation group: 'org.json', name: 'json', version: '20230227'

    implementation 'org.skyscreamer:jsonassert:1.5.0'

    implementation 'org.apache.httpcomponents.client5:httpclient5'

    ///BEGIN - Temporary Workarounds

    ///END - Temporary Workarounds

    /*********** TEST libs ***********/
    testImplementation 'com.testone.cloudnative:spring-base-test:5.0.0'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testAnnotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.mockito:mockito-inline:2.13.0'
    testImplementation 'org.junit.jupiter:junit-jupiter-api'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
    testImplementation 'net.javacrumbs.json-unit:json-unit-assertj:2.36.0'
    testImplementation 'org.glassfish.jersey.core:jersey-common:2.22.2'
    testImplementation 'org.junit.jupiter:junit-jupiter-migrationsupport:5.9.0'
    testImplementation 'com.google.cloud:google-cloud-bigtable-emulator:0.150.0'

}

tasks.withType(Test) {
    useJUnitPlatform()
}

test {
    finalizedBy jacocoTestReport // report is always generated after tests run
}

repositories {
    maven {
        url 'https://jfrog.testone.com/artifactory/test-sbox-local'
        credentials {
            username System.getenv('JFROG_USERNAME')
            password System.getenv('JFROG_PASSWORD')
        }
    }
}

Tried changing the javax dependency in build.gradle to jakarta dependency. Still getting same error. Also tried few options from online blogs, but nothing worked. Failing in externalRestTemplate.exchange(requestEntity, org.springframework.core.io.Resource.class);

Does RestTemplate work with Spring boot 3?

If so, how to handle this error?

Currently, we have 'javax.ws.rs-api dependency', tried updating it to 'jakarta.ws.rs-api', still no luck.

The same code and endpoint with Spring boot 2 is working without any issues.

How to get rid of this error? Anything else to be checked while upgrading from spring boot 2 to 3 which may be causing this issue?

1

There are 1 best solutions below

0
Ricardo Gellman On

RestTemplate does work with Spring Boot 3. Spring Boot 3 continues to support RestTemplate, although it's marked as deprecated in favor of WebClient (introduced in Spring WebFlux).

Consider apply Spring Boot BOM (Bill of Materials) in your project explained here: How to find out which dependency version I should use?

Also, validade your SB external dependencies in: https://docs.spring.io/spring-boot/docs/current/reference/html/dependency-versions.html