Skip to content

Loading from spring.factories may fail with a ClassNotFoundException when the TCCL changes between calls #45984

Closed
@sephiroth-j

Description

@sephiroth-j

With the update from v3.4.4 to v3.4.5 we encountered two ClassNotFoundException in combination with Spring Webflux and HATEOAS.

I compared what has changed between these two versions and only the following had changed:

  • Spring Boot (of course)
  • Spring Framework 6.2.5 to 6.2.6
  • Reactor BOM 2024.0.4 to 2024.0.5

After using the previous versions of Spring Framework and Reactor, the error still persists and the only change is Spring Boot. The problem also exists with the current version 3.5.0.

There are two problems, the first relates to CollectionJsonAffordanceModelFactory and the second to HtmlInputTypeFactory.

stacktace-HtmlInputTypeFactory.txt
stacktace-CollectionJsonAffordanceModelFactory.txt

I have created a sample application to reproduce the error.

spring-hateoas-issue.zip

  1. mvn package
  2. java -jar .\target\cl-issue-demo-0.0.1-SNAPSHOT.jar
  3. in another console: curl -v http://localhost:8080/hello

No response is received and the stacktrace is logged.

Java version is 21.

openjdk version "21.0.4" 2024-07-16 LTS
OpenJDK Runtime Environment Temurin-21.0.4+7 (build 21.0.4+7-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.4+7 (build 21.0.4+7-LTS, mixed mode, sharing)

We were also able to create workarounds for both problems by triggering the static code on the main thread with an ApplicationListener (please see ApplicationConfiguration in the sample app).

@Bean
	public ApplicationListener<ApplicationStartedEvent> hateoasWorkaround() {
		// workaround classloader issues
		return event -> {
			// issue #1: org.springframework.hateoas.mediatype.collectionjson.CollectionJsonAffordanceModelFactory
			var link = org.springframework.hateoas.Link.of("test");
			org.springframework.hateoas.mediatype.Affordances.of(link).afford(HttpMethod.GET).build();
			// issue #2: org.springframework.hateoas.mediatype.html.HtmlInputTypeFactory
			var type = ResolvableType.forClassWithGenerics(Mono.class, ResolvableType.forClassWithGenerics(ResponseEntity.class, TestResponse.class));
			org.springframework.hateoas.mediatype.PropertyUtils.getExposedProperties(type);
		};
	}

Metadata

Metadata

Assignees

Labels

type: regressionA regression from a previous release

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions