Skip to content

Add actuator specific ObjectMapper #12951

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
vilhelm-persson-viper opened this issue Apr 23, 2018 · 21 comments
Closed

Add actuator specific ObjectMapper #12951

vilhelm-persson-viper opened this issue Apr 23, 2018 · 21 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@vilhelm-persson-viper
Copy link

vilhelm-persson-viper commented Apr 23, 2018

When using a custom object mapper with MapperFeature.AUTO_DETECT_GETTERS disabled the detailed information for Health endpoint is not returned.

The status is returned as expected but not the detailed information.

From the code the getStatus method has Jackson annotation but the getDetails is lacking annotation.

Problem found using SpringBoot spring-boot-starter-parent version 2.0.1.RELEASE.

As a workaround and for verification of the problem is related to Jackson an MixIn class where created annotation for getStatus and getDetails and after that the information where displayed as expected.

mapper.addMixIn(Health.class, HealthMixIn.class);
public abstract class HealthMixIn {
  @JsonValue public abstract Object getStatus();
  @JsonValue public abstract Object getDetails();
}

How to repeat:

@Bean
@Primary
public ObjectMapper create() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(MapperFeature.AUTO_DETECT_GETTERS)
    return mapper;
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 23, 2018
@philwebb
Copy link
Member

I wonder if we should create our own ObjectMapper for the actuator.

@philwebb philwebb added the for: team-attention An issue we'd like other members of the team to review label Apr 23, 2018
@snicoll
Copy link
Member

snicoll commented Apr 24, 2018

If we do, I am expecting some stuff to be configurable. For instance, you may want that Instant are formatted consistently and having our own means you'd need to configure things in two places. Doing this will certainly break other use cases.

@wilkinsona
Copy link
Member

For instance, you may want that Instant are formatted consistently

We document the actuator's format for Instant so I think this is actually an argument in favour of using our own ObjectMapper. Doing so would mean that the precise format of the responses will always match what we've documented.

Doing this will certainly break other use cases

On the other hand, I agree with this. While it may be a bad thing that configuring the global ObjectMapper affects the Actuator's response format, the reality is that it does. I would be surprised if at least some users aren't currently relying on that.

@snicoll
Copy link
Member

snicoll commented Apr 24, 2018

We document the actuator's format for Instant

I am not surprised but for some reason I completely eluded that. I think it's going to be quite hard to do this right. Users may care about a single ObjectMapper so we should give them the ability to do that. And the auto-configured ObjectMapper is already @Primary so we'd probably need some way to qualify the actuator specific one, if any.

@philwebb philwebb added type: task A general task and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged labels Apr 25, 2018
@philwebb philwebb changed the title Health detail information need ObjectMapper auto detect getter Add actuator specific ObjectMapper Apr 25, 2018
@philwebb philwebb added this to the Backlog milestone Apr 25, 2018
@wilkinsona
Copy link
Member

If we add an Actuator-specific ObjectMapper, we'll perhaps be adding to the problem that's described in #1789.

@wilkinsona wilkinsona added type: enhancement A general enhancement and removed type: task A general task labels Apr 25, 2018
@vilhelm-persson-viper
Copy link
Author

Referring to initial title where the problem where detected.

For the Health actuator I think that adding Jackson annotation also for the getDetails method would solve the problem with most custom configuration on the ObjectMapper.

@joshiste
Copy link
Contributor

joshiste commented Jun 14, 2018

Currently the easiest way to reconfigure the global ObjectMapper without having the actuator endpoints affected is this:

    @Bean
    public MappingJackson2HttpMessageConverter actuatorHttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(Jackson2ObjectMapperBuilder.json().featuresToDisable(WRITE_DATES_AS_TIMESTAMPS).build());
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.parseMediaType(ActuatorMediaType.V2_JSON)));
        return converter;
    }

I'd really like to submit a PR for spring boot that takes this approach, as it would make the actuators' format "stable" (useful for spring boot admin users).
The downside (as mentioned before): you can't customize this mapper... (unless the user overrides the actuatorHttpMessageConverter)

WDYT @wilkinsona @snicoll, is such a PR worth it?

@wilkinsona
Copy link
Member

Interesting approach, @joshiste. Unfortunately, there's a bit more to it I think as the Actuator also uses an ObjectMapper in various other places (the env and config props endpoints, JMX endpoints, etc) and we don't want to contribute to the problem that #1789 is tracking without exhausting other possibilities first.

In short, I don't think such a PR is worth it right now. We may end up taking an approach like the one you have proposed, but I think some investigation and experimentation is needed first.

@philwebb philwebb modified the milestones: Backlog, Icebox Aug 31, 2018
@philwebb philwebb added the status: blocked An issue that's blocked on an external project change label Aug 31, 2018
@philwebb philwebb modified the milestones: Icebox, 2.2.x Aug 31, 2018
@joshiste
Copy link
Contributor

joshiste commented Sep 1, 2018

@philwebb you added the status: blocked label. I'd be interested in some background info on that and the progress on this topic.

@philwebb
Copy link
Member

philwebb commented Sep 4, 2018

I added blocked because it feels like we really need to solve #1789 [edit: I meant #13766] before this one. There's not really been much progress on that one unfortunately.

@snicoll

This comment has been minimized.

@philwebb

This comment has been minimized.

@wilkinsona
Copy link
Member

Let's start exploring this for 2.3.0.M2.

@bclozel
Copy link
Member

bclozel commented Feb 12, 2020

I've just closed this issue, opting for an Actuator-specific ObjectMapper instance. This instance is used for Spring MVC, Spring WebFlux, JMX and Jersey - Actuator endpoints.

The JSON mapper becomes now an implementation detail of Actuator. Jackson was already a hard dependency, but this time the mapper is totally independent from the rest of the application.

This has the following advantages:

  • changing the application JSON serialization configuration won't have any effect on Actuator JSON responses (= they'll be consistent across applications)
  • in the future, Spring Boot might choose another JSON mapper or different defaults for that without any effect on the application itself (see Provide support for actuators and /error rendering with Gson #13766)
  • we don't need to annotate classes to ensure that the response format will be consistent
  • using the Gson mapper in the application (i.e. adding the library as a dependency and using "spring.mvc.converters.preferred-json-mapper:gson") now works. It was previously failing on the /actuator/beans endpoint

There are some downsides to that approach.

First, we're making #1789 worse because we now have 3 ObjectMapper instances in a typical web application with Actuator: one for the application, one for Actuator endpoints, and another one specifically for the config properties endpoint (as we have very specific constraints for serializing those).

Also, this ObjectMapper instance only comes into play when the Actuator-specific media types are used (such as "application/vnd.spring-boot.actuator.v3+json"). If the client explicitly asks for "application/json", the application's ObjectMapper might be used in this case and the proper serialization is not guaranteed anymore.

@bclozel
Copy link
Member

bclozel commented Feb 21, 2020

We need to revert that change because of #20211.

With the current Actuator setup, a custom annotation-based HandlerMapping instance for Actuator endpoints will still share the RequestMappingHandlerAdapter infrastructure with the main application. In the case of #20211, we can't really have actuator-specific HTTP message converters, as we would need to only involve them for some endpoints.

Instead, we should consider whether we can implement the MVC web adapter layer for Actuator using Servlet Functional Endpoints, see #20290. In that mode, the message converters would be limited to that specific HandlerMapping implementation. Right now, adding another message converter to the list has side-effects on the main application and this is not acceptable.

@bclozel
Copy link
Member

bclozel commented Feb 21, 2020

Actually, closing in favor of #20291 as we need to keep this issue tied to the released 2.3.0.M2 version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

9 participants