spring-boot-admin icon indicating copy to clipboard operation
spring-boot-admin copied to clipboard

Unable to upgrade to Spring Boot 3.5.0

Open bigluds opened this issue 8 months ago • 8 comments

Spring Boot Admin Server information

  • Version: 3.4.6

  • Spring Boot version: 3.5.0

  • Configured Security: Basic Auth

  • Webflux or Servlet application: WebFlux

Client information

  • Spring Boot versions: 3.4.6

  • Used discovery mechanism: Self registration

  • Webflux or Servlet application: WebFlux

Description

When upgrading from Spring Boot 3.4.6 ou Spring Boot 3.5.0 my application is unable to start due to the following error:


APPLICATION FAILED TO START


Description:

Parameter 2 of method registrationClient in de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration$RestClientRegistrationClientConfig required a bean of type 'org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder' that could not be found.

Thank you for helping in solving this issue.

bigluds avatar May 23 '25 18:05 bigluds

Hi @bigluds,

SBA is not yet Spring Boot 3.5 ready as Spring Cloud is not yet released for Spring Boot 3.5.

Anyways. When not using Spring Cloud dependencies, SBA should work ootb. We have upgraded to Spring Boot 3.5 in a branch and for Servlet and WebFlux based implementations, SBA starts up as usual. Can you post the spring dependencies you are using in your project and check if your local setup is correct since all dependant ClientHttpRequestFactoryBuilder classes are part of org.springframework.boot:spring-boot:3.5.0.

SteKoe avatar May 24 '25 07:05 SteKoe

Dear @SteKoe,

Thanks for reminding that SBA is not yet Spring Boot 3.5 ready. But I require Spring Boot 3.5 because it fixes an issue we have.

You can find below the full dependency tree we have :

net.ddns.lbert.website:website-be:jar:1.0.2-develop-SNAPSHOT
+- org.springframework.boot:spring-boot-starter-webflux:jar:3.5.0:compile
|  +- org.springframework.boot:spring-boot-starter:jar:3.5.0:compile
|  |  +- org.springframework.boot:spring-boot:jar:3.5.0:compile
|  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:3.5.0:compile
|  |  +- org.springframework.boot:spring-boot-starter-logging:jar:3.5.0:compile
|  |  \- jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile
|  +- org.springframework.boot:spring-boot-starter-json:jar:3.5.0:compile
|  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.19.0:compile
|  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.19.0:compile
|  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.19.0:compile
|  +- org.springframework.boot:spring-boot-starter-reactor-netty:jar:3.5.0:compile
|  |  \- io.projectreactor.netty:reactor-netty-http:jar:1.2.6:compile
|  |     +- io.netty:netty-codec-http:jar:4.1.121.Final:compile
|  |     \- io.netty:netty-codec-http2:jar:4.1.121.Final:compile
|  +- org.springframework:spring-web:jar:6.2.7:compile
|  \- org.springframework:spring-webflux:jar:6.2.7:compile
+- org.springframework.boot:spring-boot-starter-data-r2dbc:jar:3.5.0:compile
|  +- org.springframework.data:spring-data-r2dbc:jar:3.5.0:compile
|  |  +- org.springframework.data:spring-data-relational:jar:3.5.0:compile
|  |  +- org.springframework.data:spring-data-commons:jar:3.5.0:compile
|  |  +- org.springframework:spring-context:jar:6.2.7:compile
|  |  +- org.springframework:spring-r2dbc:jar:6.2.7:compile
|  |  \- org.slf4j:slf4j-api:jar:2.0.17:compile
|  +- io.r2dbc:r2dbc-spi:jar:1.0.0.RELEASE:compile
|  |  \- org.reactivestreams:reactive-streams:jar:1.0.4:compile
|  \- io.r2dbc:r2dbc-pool:jar:1.0.2.RELEASE:compile
|     \- io.projectreactor.addons:reactor-pool:jar:1.1.2:compile
+- org.springframework:spring-jdbc:jar:6.2.7:compile
|  +- org.springframework:spring-beans:jar:6.2.7:compile
|  +- org.springframework:spring-core:jar:6.2.7:compile
|  |  \- org.springframework:spring-jcl:jar:6.2.7:compile
|  \- org.springframework:spring-tx:jar:6.2.7:compile
+- org.springframework.boot:spring-boot-starter-actuator:jar:3.5.0:compile
|  +- org.springframework.boot:spring-boot-actuator-autoconfigure:jar:3.5.0:compile
|  |  \- org.springframework.boot:spring-boot-actuator:jar:3.5.0:compile
|  +- io.micrometer:micrometer-observation:jar:1.15.0:compile
|  |  \- io.micrometer:micrometer-commons:jar:1.15.0:compile
|  \- io.micrometer:micrometer-jakarta9:jar:1.15.0:compile
+- org.springframework.boot:spring-boot-starter-security:jar:3.5.0:compile
|  +- org.springframework:spring-aop:jar:6.2.7:compile
|  +- org.springframework.security:spring-security-config:jar:6.5.0:compile
|  |  \- org.springframework.security:spring-security-core:jar:6.5.0:compile
|  |     \- org.springframework.security:spring-security-crypto:jar:6.5.0:compile
|  \- org.springframework.security:spring-security-web:jar:6.5.0:compile
|     \- org.springframework:spring-expression:jar:6.2.7:compile
+- org.mapstruct:mapstruct:jar:1.5.5.Final:compile
+- io.micrometer:micrometer-registry-prometheus:jar:1.15.0:compile
|  +- io.micrometer:micrometer-core:jar:1.15.0:compile
|  |  +- org.hdrhistogram:HdrHistogram:jar:2.2.2:runtime
|  |  \- org.latencyutils:LatencyUtils:jar:2.0.3:runtime
|  +- io.prometheus:prometheus-metrics-core:jar:1.3.6:compile
|  |  +- io.prometheus:prometheus-metrics-model:jar:1.3.6:compile
|  |  \- io.prometheus:prometheus-metrics-config:jar:1.3.6:compile
|  +- io.prometheus:prometheus-metrics-tracer-common:jar:1.3.6:compile
|  \- io.prometheus:prometheus-metrics-exposition-formats:jar:1.3.6:runtime
|     \- io.prometheus:prometheus-metrics-exposition-textformats:jar:1.3.6:runtime
+- de.codecentric:spring-boot-admin-starter-client:jar:3.4.6:compile
|  \- de.codecentric:spring-boot-admin-client:jar:3.4.6:compile
+- io.swagger.core.v3:swagger-annotations:jar:2.2.27:compile
+- jakarta.validation:jakarta.validation-api:jar:3.0.2:compile
+- org.openapitools:jackson-databind-nullable:jar:0.2.6:compile
|  \- com.fasterxml.jackson.core:jackson-databind:jar:2.19.0:compile
|     +- com.fasterxml.jackson.core:jackson-annotations:jar:2.19.0:compile
|     \- com.fasterxml.jackson.core:jackson-core:jar:2.19.0:compile
+- org.postgresql:postgresql:jar:42.7.5:runtime
|  \- org.checkerframework:checker-qual:jar:3.48.3:runtime
+- org.postgresql:r2dbc-postgresql:jar:1.0.7.RELEASE:runtime
|  +- com.ongres.scram:client:jar:2.1:runtime
|  |  \- com.ongres.scram:common:jar:2.1:runtime
|  |     \- com.ongres.stringprep:saslprep:jar:1.1:runtime
|  |        \- com.ongres.stringprep:stringprep:jar:1.1:runtime
|  +- io.projectreactor:reactor-core:jar:3.7.6:compile
|  \- io.projectreactor.netty:reactor-netty-core:jar:1.2.6:compile
|     +- io.netty:netty-handler:jar:4.1.121.Final:compile
|     |  +- io.netty:netty-common:jar:4.1.121.Final:compile
|     |  +- io.netty:netty-resolver:jar:4.1.121.Final:compile
|     |  +- io.netty:netty-buffer:jar:4.1.121.Final:compile
|     |  +- io.netty:netty-transport:jar:4.1.121.Final:compile
|     |  +- io.netty:netty-transport-native-unix-common:jar:4.1.121.Final:compile
|     |  \- io.netty:netty-codec:jar:4.1.121.Final:compile
|     +- io.netty:netty-handler-proxy:jar:4.1.121.Final:compile
|     |  \- io.netty:netty-codec-socks:jar:4.1.121.Final:compile
|     +- io.netty:netty-resolver-dns:jar:4.1.121.Final:compile
|     |  \- io.netty:netty-codec-dns:jar:4.1.121.Final:compile
|     +- io.netty:netty-resolver-dns-native-macos:jar:osx-x86_64:4.1.121.Final:compile
|     |  \- io.netty:netty-resolver-dns-classes-macos:jar:4.1.121.Final:compile
|     \- io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.121.Final:compile
|        \- io.netty:netty-transport-classes-epoll:jar:4.1.121.Final:compile
+- org.liquibase:liquibase-core:jar:4.31.1:compile
|  +- com.opencsv:opencsv:jar:5.9:compile
|  +- org.yaml:snakeyaml:jar:2.4:compile
|  +- javax.xml.bind:jaxb-api:jar:2.3.1:compile
|  +- org.apache.commons:commons-collections4:jar:4.4:compile
|  +- org.apache.commons:commons-text:jar:1.13.0:compile
|  +- org.apache.commons:commons-lang3:jar:3.17.0:compile
|  \- commons-io:commons-io:jar:2.18.0:compile
+- org.springframework.boot:spring-boot-starter-test:jar:3.5.0:test
|  +- org.springframework.boot:spring-boot-test:jar:3.5.0:test
|  +- org.springframework.boot:spring-boot-test-autoconfigure:jar:3.5.0:test
|  +- com.jayway.jsonpath:json-path:jar:2.9.0:test
|  +- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.2:test
|  |  \- jakarta.activation:jakarta.activation-api:jar:2.1.3:test
|  +- net.minidev:json-smart:jar:2.5.2:test
|  |  \- net.minidev:accessors-smart:jar:2.5.2:test
|  |     \- org.ow2.asm:asm:jar:9.7.1:test
|  +- org.assertj:assertj-core:jar:3.27.3:test
|  |  \- net.bytebuddy:byte-buddy:jar:1.17.5:test
|  +- org.awaitility:awaitility:jar:4.3.0:test
|  +- org.hamcrest:hamcrest:jar:3.0:test
|  +- org.junit.jupiter:junit-jupiter:jar:5.12.2:test
|  |  +- org.junit.jupiter:junit-jupiter-api:jar:5.12.2:test
|  |  |  +- org.opentest4j:opentest4j:jar:1.3.0:test
|  |  |  +- org.junit.platform:junit-platform-commons:jar:1.12.2:test
|  |  |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
|  |  +- org.junit.jupiter:junit-jupiter-params:jar:5.12.2:test
|  |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.12.2:test
|  |     \- org.junit.platform:junit-platform-engine:jar:1.12.2:test
|  +- org.mockito:mockito-core:jar:5.17.0:test
|  |  +- net.bytebuddy:byte-buddy-agent:jar:1.17.5:test
|  |  \- org.objenesis:objenesis:jar:3.3:test
|  +- org.mockito:mockito-junit-jupiter:jar:5.17.0:test
|  +- org.skyscreamer:jsonassert:jar:1.5.3:test
|  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
|  +- org.springframework:spring-test:jar:6.2.7:test
|  \- org.xmlunit:xmlunit-core:jar:2.10.1:test
+- io.projectreactor:reactor-test:jar:3.7.6:test
\- io.github.hakky54:logcaptor:jar:2.10.0:test
   +- ch.qos.logback:logback-classic:jar:1.5.18:compile
   |  \- ch.qos.logback:logback-core:jar:1.5.18:compile
   +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.24.3:compile
   |  \- org.apache.logging.log4j:log4j-api:jar:2.24.3:compile
   \- org.slf4j:jul-to-slf4j:jar:2.0.17:compile

bigluds avatar May 24 '25 09:05 bigluds

Got a similar error. Dependencies are minimal <spring-boot-admin.version>3.4.7</spring-boot-admin.version>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
        <version>${spring-boot-admin.version}</version>
    </dependency>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-client</artifactId>
        <version>${spring-boot-admin.version}</version>
    </dependency>
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>applicationinsights-runtime-attach</artifactId>
        <version>${applicationinsights.runtime.attach.version}</version>
    </dependency>
</dependencies>

dkorotych avatar May 26 '25 13:05 dkorotych

Hi @dkorotych, hi @bigluds,

can you share a minimal project that reproduces the issue? I have just added your dependencies and Spring Boot 3.5.0 to this runtime sample (https://github.com/codecentric/spring-boot-admin-runtime-playground/tree/main/eureka/apps/spring-boot-admin) and it just starts.

 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.5.0)

2025-05-26T19:06:01.913Z  INFO 1 --- [spring-boot-admin-eureka] [           main] d.c.s.SpringBootAdminApplication         : Starting SpringBootAdminApplication v1.0.0-SNAPSHOT using Java 17.0.15 with PID 1 (/opt/app/app.jar started by root in /)
2025-05-26T19:06:01.942Z  INFO 1 --- [spring-boot-admin-eureka] [           main] d.c.s.SpringBootAdminApplication         : No active profile set, falling back to 1 default profile: "default"
2025-05-26T19:06:09.733Z  WARN 1 --- [spring-boot-admin-eureka] [           main] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates, check your Thymeleaf configuration, or set spring.thymeleaf.check-template-location=false)
2025-05-26T19:06:10.551Z  INFO 1 --- [spring-boot-admin-eureka] [           main] ctiveUserDetailsServiceAutoConfiguration : 

Using generated security password: 234e4ecb-b16f-41f3-ad4f-d7f22cde584d

2025-05-26T19:06:11.834Z  INFO 1 --- [spring-boot-admin-eureka] [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8080 (http)
2025-05-26T19:06:12.028Z  INFO 1 --- [spring-boot-admin-eureka] [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 15 endpoints beneath base path '/actuator'
2025-05-26T19:06:12.104Z  INFO 1 --- [spring-boot-admin-eureka] [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8081 (http)
2025-05-26T19:06:12.180Z  INFO 1 --- [spring-boot-admin-eureka] [           main] d.c.s.SpringBootAdminApplication         : Started SpringBootAdminApplication in 15.166 seconds (process running for 19.45)

SteKoe avatar May 26 '25 19:05 SteKoe

Hi @SteKoe

You are right, it is not only about libraries, but also about settings. If you turn off virtual threads or client URL, then the application starts normally

sba.zip

dkorotych avatar May 27 '25 10:05 dkorotych

Hello @SteKoe

I confirm the feedback given by @dkorotych when I have the spring property spring.threads.virtual.enabled: true the error occurs otherwise it seems to work correctly.

bigluds avatar May 27 '25 18:05 bigluds

Hello @dkorotych,

thanks for providing the minimal sample. I was able to see the very same effect and the team will dig deeper into it. Accoding to Spring Boot 3.5.0 release notes there might be a breaking change.

@bigluds thanks for confirming the issue with virtual threads, too!

SteKoe avatar May 28 '25 05:05 SteKoe

The root cause is this change in Spring Boot 3.5.0:

RestClientAutoConfiguration now applies for reactive web applications that are using virtual threads and have a applicationTaskExecutor bean.

(see Spring Boot 3.5 Release Notes)

We currently assume, that if a RestClient.Builder bean is available that a ClientHttpRequestFactoryBuilder bean is available, too. With the change in Spring Boot, the former will be available in reactive web applications using virtual threads, but the latter won't. Note that a prerequisit for virtual threads in Spring is a Java version >= 21.

As a workaround, you can define your own ReactiveRegistrationClient:

@Bean
public RegistrationClient registrationClient(ClientProperties client, WebClient.Builder webClient) {
	if (client.getUsername() != null && client.getPassword() != null) {
		webClient = webClient.filter(basicAuthentication(client.getUsername(), client.getPassword()));
	}
	return new ReactiveRegistrationClient(webClient.build(), client.getReadTimeout());
}

We are still looking for a proper fix in Spring Boot Admin.

hzpz avatar Jun 06 '25 10:06 hzpz