Skip to content

Commit da124a9

Browse files
committed
Make HttpMessageConverters classpath detection static
Prior to this commit, the classpath detection of various `HttpMessageConverter` types was using an instance `ClassLoader`. The main goal here was to provide the feature and being able to test it with filtered classloaders. It seems this approach fails with GraalVM and we need to ensure that classpath detection is performed at class loading time for our GraalVM feature (inlining such static booleans at build time). As a result, we need to remove the tests for classpath detection. See gh-33894
1 parent 7e919d2 commit da124a9

File tree

2 files changed

+80
-205
lines changed

2 files changed

+80
-205
lines changed

spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java

Lines changed: 80 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ static class DefaultBuilder implements HttpMessageConverters.Builder {
9292
this.clientMessageConverterConfigurer = new DefaultClientMessageConverterConfigurer(this.commonMessageConverters);
9393
this.serverMessageConverterConfigurer = new DefaultServerMessageConverterConfigurer(this.commonMessageConverters);
9494
if (registerDefaults) {
95-
this.commonMessageConverters.registerDefaults(classLoader);
96-
this.clientMessageConverterConfigurer.registerDefaults(classLoader);
97-
this.serverMessageConverterConfigurer.registerDefaults(classLoader);
95+
this.commonMessageConverters.registerDefaults();
96+
this.clientMessageConverterConfigurer.registerDefaults();
97+
this.serverMessageConverterConfigurer.registerDefaults();
9898
}
9999
}
100100

@@ -163,6 +163,41 @@ public DefaultHttpMessageConverters build() {
163163

164164
static class DefaultMessageConverterConfigurer {
165165

166+
private static final boolean isJacksonPresent;
167+
168+
private static final boolean isJackson2Present;
169+
170+
private static final boolean isGsonPresent;
171+
172+
private static final boolean isJsonbPresent;
173+
174+
private static final boolean isKotlinSerializationJsonPresent;
175+
176+
private static final boolean isJacksonXmlPresent;
177+
178+
private static final boolean isJackson2XmlPresent;
179+
180+
private static final boolean isJaxb2Present;
181+
182+
private static final boolean isJacksonSmilePresent;
183+
184+
private static final boolean isJackson2SmilePresent;
185+
186+
private static final boolean isJacksonCborPresent;
187+
188+
private static final boolean isJackson2CborPresent;
189+
190+
private static final boolean isKotlinSerializationCborPresent;
191+
192+
private static final boolean isJacksonYamlPresent;
193+
194+
private static final boolean isJackson2YamlPresent;
195+
196+
private static final boolean isKotlinSerializationProtobufPresent;
197+
198+
private static final boolean isRomePresent;
199+
200+
166201
private final @Nullable DefaultMessageConverterConfigurer inheritedMessageConverters;
167202

168203
private @Nullable ByteArrayHttpMessageConverter byteArrayMessageConverter;
@@ -183,6 +218,28 @@ static class DefaultMessageConverterConfigurer {
183218

184219
private final List<HttpMessageConverter<?>> additionalMessageConverters = new ArrayList<>();
185220

221+
static {
222+
ClassLoader classLoader = DefaultClientMessageConverterConfigurer.class.getClassLoader();
223+
isJacksonPresent = ClassUtils.isPresent("tools.jackson.databind.ObjectMapper", classLoader);
224+
isJackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
225+
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
226+
isGsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
227+
isJsonbPresent = ClassUtils.isPresent("jakarta.json.bind.Jsonb", classLoader);
228+
isKotlinSerializationJsonPresent = ClassUtils.isPresent("kotlinx.serialization.json.Json", classLoader);
229+
isJacksonSmilePresent = isJacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.smile.SmileMapper", classLoader);
230+
isJackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
231+
isJaxb2Present = ClassUtils.isPresent("jakarta.xml.bind.Binder", classLoader);
232+
isJacksonXmlPresent = isJacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.xml.XmlMapper", classLoader);
233+
isJackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
234+
isJacksonCborPresent = isJacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.cbor.CBORMapper", classLoader);
235+
isJackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
236+
isJacksonYamlPresent = isJacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.yaml.YAMLMapper", classLoader);
237+
isJackson2YamlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.yaml.YAMLFactory", classLoader);
238+
isKotlinSerializationCborPresent = ClassUtils.isPresent("kotlinx.serialization.cbor.Cbor", classLoader);
239+
isKotlinSerializationProtobufPresent = ClassUtils.isPresent("kotlinx.serialization.protobuf.ProtoBuf", classLoader);
240+
isRomePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
241+
}
242+
186243
DefaultMessageConverterConfigurer() {
187244
this(null);
188245
}
@@ -294,138 +351,69 @@ List<HttpMessageConverter<?>> getCustomConverters() {
294351
return result;
295352
}
296353

297-
void registerDefaults(ClassLoader classLoader) {
354+
void registerDefaults() {
298355
this.byteArrayMessageConverter = new ByteArrayHttpMessageConverter();
299356
this.stringMessageConverter = new StringHttpMessageConverter();
300357

301-
if (isJacksonPresent(classLoader)) {
358+
if (isJacksonPresent) {
302359
this.jsonMessageConverter = new JacksonJsonHttpMessageConverter();
303360
}
304-
else if (isJackson2Present(classLoader)) {
361+
else if (isJackson2Present) {
305362
this.jsonMessageConverter = new MappingJackson2HttpMessageConverter();
306363
}
307-
else if (isGsonPresent(classLoader)) {
364+
else if (isGsonPresent) {
308365
this.jsonMessageConverter = new GsonHttpMessageConverter();
309366
}
310-
else if (isJsonbPresent(classLoader)) {
367+
else if (isJsonbPresent) {
311368
this.jsonMessageConverter = new JsonbHttpMessageConverter();
312369
}
313-
else if (isKotlinSerializationJsonPresent(classLoader)) {
370+
else if (isKotlinSerializationJsonPresent) {
314371
this.jsonMessageConverter = new KotlinSerializationJsonHttpMessageConverter();
315372
}
316373

317-
if (isJacksonXmlPresent(classLoader)) {
374+
if (isJacksonXmlPresent) {
318375
this.xmlMessageConverter = new JacksonXmlHttpMessageConverter();
319376
}
320-
else if (isJackson2XmlPresent(classLoader)) {
377+
else if (isJackson2XmlPresent) {
321378
this.xmlMessageConverter = new MappingJackson2XmlHttpMessageConverter();
322379
}
323-
else if (isJaxb2Present(classLoader)) {
380+
else if (isJaxb2Present) {
324381
this.xmlMessageConverter = new Jaxb2RootElementHttpMessageConverter();
325382
}
326383

327-
if (isJacksonSmilePresent(classLoader)) {
384+
if (isJacksonSmilePresent) {
328385
this.smileMessageConverter = new JacksonSmileHttpMessageConverter();
329386
}
330-
else if (isJackson2SmilePresent(classLoader)) {
387+
else if (isJackson2SmilePresent) {
331388
this.smileMessageConverter = new MappingJackson2SmileHttpMessageConverter();
332389
}
333-
if (isJacksonCborPresent(classLoader)) {
390+
if (isJacksonCborPresent) {
334391
this.cborMessageConverter = new JacksonCborHttpMessageConverter();
335392
}
336-
else if (isJackson2CborPresent(classLoader)) {
393+
else if (isJackson2CborPresent) {
337394
this.cborMessageConverter = new MappingJackson2CborHttpMessageConverter();
338395
}
339-
else if (isKotlinSerializationCborPresent(classLoader)) {
396+
else if (isKotlinSerializationCborPresent) {
340397
this.cborMessageConverter = new KotlinSerializationCborHttpMessageConverter();
341398
}
342399

343-
if (isJacksonYamlPresent(classLoader)) {
400+
if (isJacksonYamlPresent) {
344401
this.yamlMessageConverter = new JacksonYamlHttpMessageConverter();
345402
}
346-
else if (isJackson2YamlPresent(classLoader)) {
403+
else if (isJackson2YamlPresent) {
347404
this.yamlMessageConverter = new MappingJackson2YamlHttpMessageConverter();
348405
}
349406

350-
if (isKotlinSerializationProtobufPresent(classLoader)) {
407+
if (isKotlinSerializationProtobufPresent) {
351408
this.additionalMessageConverters.add(new KotlinSerializationProtobufHttpMessageConverter());
352409
}
353410

354-
if (isRomePresent(classLoader)) {
411+
if (isRomePresent) {
355412
this.additionalMessageConverters.add(new AtomFeedHttpMessageConverter());
356413
this.additionalMessageConverters.add(new RssChannelHttpMessageConverter());
357414
}
358415
}
359416

360-
private static boolean isRomePresent(ClassLoader classLoader) {
361-
return ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
362-
}
363-
364-
private static boolean isJacksonPresent(ClassLoader classLoader) {
365-
return ClassUtils.isPresent("tools.jackson.databind.ObjectMapper", classLoader);
366-
}
367-
368-
private static boolean isJackson2Present(ClassLoader classLoader) {
369-
return ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
370-
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
371-
}
372-
373-
private static boolean isGsonPresent(ClassLoader classLoader) {
374-
return ClassUtils.isPresent("com.google.gson.Gson", classLoader);
375-
}
376-
377-
private static boolean isJsonbPresent(ClassLoader classLoader) {
378-
return ClassUtils.isPresent("jakarta.json.bind.Jsonb", classLoader);
379-
}
380-
381-
private static boolean isKotlinSerializationJsonPresent(ClassLoader classLoader) {
382-
return ClassUtils.isPresent("kotlinx.serialization.json.Json", classLoader);
383-
}
384-
385-
private static boolean isJacksonSmilePresent(ClassLoader classLoader) {
386-
return isJacksonPresent(classLoader) && ClassUtils.isPresent("tools.jackson.dataformat.smile.SmileMapper", classLoader);
387-
}
388-
389-
private static boolean isJackson2SmilePresent(ClassLoader classLoader) {
390-
return ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
391-
}
392-
393-
private static boolean isJaxb2Present(ClassLoader classLoader) {
394-
return ClassUtils.isPresent("jakarta.xml.bind.Binder", classLoader);
395-
}
396-
397-
private static boolean isJacksonXmlPresent(ClassLoader classLoader) {
398-
return isJacksonPresent(classLoader) && ClassUtils.isPresent("tools.jackson.dataformat.xml.XmlMapper", classLoader);
399-
}
400-
401-
private static boolean isJackson2XmlPresent(ClassLoader classLoader) {
402-
return ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
403-
}
404-
405-
private static boolean isJacksonCborPresent(ClassLoader classLoader) {
406-
return isJacksonPresent(classLoader) && ClassUtils.isPresent("tools.jackson.dataformat.cbor.CBORMapper", classLoader);
407-
}
408-
409-
private static boolean isJackson2CborPresent(ClassLoader classLoader) {
410-
return ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
411-
}
412-
413-
private static boolean isJacksonYamlPresent(ClassLoader classLoader) {
414-
return isJacksonPresent(classLoader) && ClassUtils.isPresent("tools.jackson.dataformat.yaml.YAMLMapper", classLoader);
415-
}
416-
417-
private static boolean isJackson2YamlPresent(ClassLoader classLoader) {
418-
return ClassUtils.isPresent("com.fasterxml.jackson.dataformat.yaml.YAMLFactory", classLoader);
419-
}
420-
421-
private static boolean isKotlinSerializationCborPresent(ClassLoader classLoader) {
422-
return ClassUtils.isPresent("kotlinx.serialization.cbor.Cbor", classLoader);
423-
}
424-
425-
private static boolean isKotlinSerializationProtobufPresent(ClassLoader classLoader) {
426-
return ClassUtils.isPresent("kotlinx.serialization.protobuf.ProtoBuf", classLoader);
427-
}
428-
429417
}
430418

431419
static class DefaultClientMessageConverterConfigurer extends DefaultMessageConverterConfigurer implements ClientMessageConverterConfigurer {
@@ -489,7 +477,7 @@ public ClientMessageConverterConfigurer configureClientMessageConverters(Consume
489477
}
490478

491479
@Override
492-
void registerDefaults(ClassLoader classLoader) {
480+
void registerDefaults() {
493481
this.resourceMessageConverters = Collections.singletonList(new ResourceHttpMessageConverter(false));
494482
}
495483

@@ -576,7 +564,7 @@ public ServerMessageConverterConfigurer configureServerMessageConverters(Consume
576564
}
577565

578566
@Override
579-
void registerDefaults(ClassLoader classLoader) {
567+
void registerDefaults() {
580568
this.resourceMessageConverters = Arrays.asList(new ResourceHttpMessageConverter(), new ResourceRegionHttpMessageConverter());
581569
}
582570

0 commit comments

Comments
 (0)