Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
creckord opened this issue Jan 31, 2023 · 7 comments
Closed

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

creckord opened this issue Jan 31, 2023 · 7 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@creckord
Copy link

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.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 31, 2023
@wilkinsona
Copy link
Member

wilkinsona commented Jan 31, 2023

Thanks for the report but Actuator requires Jackson and we do not support the use of Gson to serialize Actuator responses to json. There's some more information in #13766. In that issue, @philwebb wondered if we should fail hard when an attempt is made to use Gson:

I wonder if we should try to fail hard if GSON is used? We're getting a few bug reports because it appears to work even though we don't support it.

Perhaps we need to consider that again? It may be too late to make that change in 2.7.x and the benefit would be less in 3.0 as Actuator now has its own, isolated ObjectMapper.

@wilkinsona wilkinsona added the for: team-meeting An issue we'd like to discuss as a team to make progress label Feb 1, 2023
@creckord
Copy link
Author

creckord commented Feb 1, 2023

Okay, good to know - it's a bit surprising when an "innocent" supported config breaks support elsewhere, and the dependency on Jackson is not really clear from the outside, but glad that this is resolved in 3.x.

Any way that I can tell Actuator in 2.7.x to use Jackson in the meantime, while keeping Gson in my production endpoints? I'm using a separate port for management if that makes any difference.

@creckord
Copy link
Author

creckord commented Feb 1, 2023

Hm, from the bug you referenced:

We've just fixed #12951, so as of Spring Boot 2.3, an application can choose Gson as a preferred JSON mapper and not risk Actuator endpoint responses being broken.

#12951 also makes the JSON mapper actuator-specific and independent of application configuration.

That's not what I am observing right now. All we are doing is this in application.yaml

spring:
  mvc:
    converters:
      preferred-json-mapper: gson

and in code:

@Configuration
public class WebMvcConfig {
    @Bean
    public GsonBuilderCustomizer gsonCustomizer() {
        return gsonBuilder -> {
           //custom type mappers
        };
    }
}

Jackson is present in the build, but Actuator seems to use the main GsonHttpMessageConverter with this config.

@wilkinsona
Copy link
Member

wilkinsona commented Feb 1, 2023

#12951 is a little bit confusing, to me anyway, as the change was eventually reverted. @bclozel can you recall why the issue was left in the milestone after the revert?

@bclozel
Copy link
Member

bclozel commented Feb 1, 2023

@wilkinsona the revert happened after the M2 release, so we left the issue in place as M2 really contains that change.

@philwebb philwebb added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged for: team-meeting An issue we'd like to discuss as a team to make progress labels Feb 1, 2023
@philwebb philwebb added this to the 2.7.x milestone Feb 1, 2023
@philwebb
Copy link
Member

philwebb commented Feb 1, 2023

We're going to look to see if we can add a DTO so that Jackson and GSON will both work. We're not going to attempt to support all actuator endpoints with GSON, but we can at least try to make health work again.

@mhalbritter
Copy link
Contributor

I found a way to revert the changes in Health.

krenson pushed a commit to krenson/test-push that referenced this issue Mar 15, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
…ot-starter-parent from 2.7.8 to 2.7.9 (patch)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [org.springframework.boot:spring-boot-starter-parent](https://spring.io/projects/spring-boot) ([source](https://github.com/spring-projects/spring-boot)) | parent | patch | `2.7.8` -> `2.7.9` |

---

### Release Notes

<details>
<summary>spring-projects/spring-boot</summary>

### [`v2.7.9`](https://github.com/spring-projects/spring-boot/releases/tag/v2.7.9)

[Compare Source](spring-projects/spring-boot@v2.7.8...v2.7.9)

#### 🐞 Bug Fixes

-   Maven Plugin's PropertiesMergingResourceTransformer closes InputStream when it should not do so [#&#8203;34063](spring-projects/spring-boot#34063)
-   Actuator Health web endpoint broken with Gson and Java 17 [#&#8203;34030](spring-projects/spring-boot#34030)
-   Dependency management for Mongo's Java Driver is incomplete [#&#8203;33941](spring-projects/spring-boot#33941)
-   Using devtools with Reactive application results in slower restarts [#&#8203;33855](spring-projects/spring-boot#33855)
-   Spies are not reset after test execution when using `@SpyBean` [#&#8203;33830](spring-projects/spring-boot#33830)
-   Properties Migrator does not detect properties of Map type that are marked as deprecated [#&#8203;27854](spring-projects/spring-boot#27854)

#### 📔 Documentation

-   Updated documentation for `@ConfigurationProperties` bean naming rules [#&#8203;34029](spring-projects/spring-boot#34029)
-   Restore "Use Jedis Instead of Lettuce" how-to documentation [#&#8203;33994](spring-projects/spring-boot#33994)
-   Add Redis application properties example [#&#8203;33965](spring-projects/spring-boot#33965)
-   Use Maven Central for release downloads in CLI installation documentation [#&#8203;33962](spring-projects/spring-boot#33962)
-   Actuator section is missing from documentation overview [#&#8203;33932](spring-projects/spring-boot#33932)
-   Add Javadoc since to OperationParameter.getAnnotation() [#&#8203;33914](spring-projects/spring-boot#33914)
-   Document additional configuration that is required for spring.mvc.throw-exception-if-no-handler-found=true to be effective [#&#8203;31660](spring-projects/spring-boot#31660)

#### 🔨 Dependency Upgrades

-   Upgrade to ActiveMQ 5.16.6 [#&#8203;34238](spring-projects/spring-boot#34238)
-   Upgrade to Byte Buddy 1.12.23 [#&#8203;34239](spring-projects/spring-boot#34239)
-   Upgrade to Dropwizard Metrics 4.2.16 [#&#8203;34240](spring-projects/spring-boot#34240)
-   Upgrade to Elasticsearch 7.17.9 [#&#8...
krenson pushed a commit to krenson/test-push that referenced this issue Mar 15, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
…ot-starter-parent from 2.7.8 to 2.7.9 (patch)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [org.springframework.boot:spring-boot-starter-parent](https://spring.io/projects/spring-boot) ([source](https://github.com/spring-projects/spring-boot)) | parent | patch | `2.7.8` -> `2.7.9` |

---

### Release Notes

<details>
<summary>spring-projects/spring-boot</summary>

### [`v2.7.9`](https://github.com/spring-projects/spring-boot/releases/tag/v2.7.9)

[Compare Source](spring-projects/spring-boot@v2.7.8...v2.7.9)

#### 🐞 Bug Fixes

-   Maven Plugin's PropertiesMergingResourceTransformer closes InputStream when it should not do so [#&#8203;34063](spring-projects/spring-boot#34063)
-   Actuator Health web endpoint broken with Gson and Java 17 [#&#8203;34030](spring-projects/spring-boot#34030)
-   Dependency management for Mongo's Java Driver is incomplete [#&#8203;33941](spring-projects/spring-boot#33941)
-   Using devtools with Reactive application results in slower restarts [#&#8203;33855](spring-projects/spring-boot#33855)
-   Spies are not reset after test execution when using `@SpyBean` [#&#8203;33830](spring-projects/spring-boot#33830)
-   Properties Migrator does not detect properties of Map type that are marked as deprecated [#&#8203;27854](spring-projects/spring-boot#27854)

#### 📔 Documentation

-   Updated documentation for `@ConfigurationProperties` bean naming rules [#&#8203;34029](spring-projects/spring-boot#34029)
-   Restore "Use Jedis Instead of Lettuce" how-to documentation [#&#8203;33994](spring-projects/spring-boot#33994)
-   Add Redis application properties example [#&#8203;33965](spring-projects/spring-boot#33965)
-   Use Maven Central for release downloads in CLI installation documentation [#&#8203;33962](spring-projects/spring-boot#33962)
-   Actuator section is missing from documentation overview [#&#8203;33932](spring-projects/spring-boot#33932)
-   Add Javadoc since to OperationParameter.getAnnotation() [#&#8203;33914](spring-projects/spring-boot#33914)
-   Document additional configuration that is required for spring.mvc.throw-exception-if-no-handler-found=true to be effective [#&#8203;31660](spring-projects/spring-boot#31660)

#### 🔨 Dependency Upgrades

-   Upgrade to ActiveMQ 5.16.6 [#&#8203;34238](spring-projects/spring-boot#34238)
-   Upgrade to Byte Buddy 1.12.23 [#&#8203;34239](spring-projects/spring-boot#34239)
-   Upgrade to Dropwizard Metrics 4.2.16 [#&#8203;34240](spring-projects/spring-boot#34240)
-   Upgrade to Elasticsearch 7.17.9 [#&#8...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

6 participants