Skip to content

Actuator Health web endpoint broken with Gson and Java 17 #34030

@creckord

Description

@creckord

In Spring Boot Actuator 2.7.8, the Health class got a new field exception. This was includes in commit d7852cb as part of #32527.

Unfortunately, Gson is not able to serialize exceptions out of the box in Java 17 due to the closed down module system. This leads to the following exception when calling the health actuator REST endpoint:

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Failed making field 'java.lang.Throwable#detailMessage' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.; nested exception is com.google.gson.JsonIOException: Failed making field 'java.lang.Throwable#detailMessage' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.
	at org.springframework.http.converter.json.AbstractJsonHttpMessageConverter.writeInternal(AbstractJsonHttpMessageConverter.java:128) ~[spring-web-5.3.25.jar:5.3.25]
	at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104) ~[spring-web-5.3.25.jar:5.3.25]
	at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:290) ~[spring-webmvc-5.3.25.jar:5.3.25]
	at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:219) ~[spring-webmvc-5.3.25.jar:5.3.25]
	at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78) ~[spring-web-5.3.25.jar:5.3.25]
	at ...
Caused by: com.google.gson.JsonIOException: Failed making field 'java.lang.Throwable#detailMessage' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.
	at com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:38) ~[gson-2.10.1.jar:?]
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:286) ~[gson-2.10.1.jar:?]
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130) ~[gson-2.10.1.jar:?]
	at ...
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.String java.lang.Throwable.detailMessage accessible: module java.base does not "opens java.lang" to unnamed module @2a742aa2
	at java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) ~[?:?]
	at ...

Actuator should include the appropriate TypeAdapters to serialize Health objects with Gson out of the box by providing an appropriate GsonBuilderCustomizer for Health that deals with the exception property.

Alternatively, instead of just fixing this specifically for Health, an adapter for Throwable would be great in StandardGsonBuilderCustomizer, since that can probably be useful in other places as well (e.g. in @ExceptionHandler methods).

Side note: As a workaround, I also tried to set spring.gson.exclude-fields-without-expose-annotation=true, but while that avoided the exception, it resulted in an empty object being returned, since the Health object is not annotated for Gson.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions