Hi, this PR basically solves #25920, but there are still some issues to consider:

  • Boot finds classes annotated with @JsonMixin

Mix-in classes are mostly abstract classes or interfaces.

See https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations

I refer to the implementation of JsonComponentModule and use the ListableBeanFactory#getBeansWithAnnotation method to find the mix-in class, but the @Component annotation does not apply to an abstract class or interface unless it contains a method annotated with @Lookup.

See ClassPathScanningCandidateComponentProvider.java#L526

  • If the user customizes the MappingJackson2HttpMessageConverter, @JsonMixin may not work, for example:
@Bean
public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
    return new MappingJackson2HttpMessageConverter(new ObjectMapper());
}

Closes gh-25920

Comment From: mhalbritter

Hi, thanks for your contribution!

Mix-in classes are mostly abstract classes or interfaces.

When adding a @Scope("prototype") to the @JsonMixin, Spring will not eagerly instantiate the bean. If you then change the addJsonMixinBeans to this:

    private void addJsonMixinBeans(ListableBeanFactory beanFactory) {
        String[] names = beanFactory.getBeanNamesForAnnotation(JsonMixin.class);
        for (String name: names) {
            Class<?> type = beanFactory.getType(name);
            addJsonMixinBean(type);
        }
    }

then Spring will not try to instantiate the bean. You're only interested in the type of the bean, anyway. This way abstract beans and interfaces work.

But I'm not sure if that solution isn't too hacky. @wilkinsona what do you think?

If you want to play around with it, the changes are on this branch.

if the user customizes the MappingJackson2HttpMessageConverter, @JsonMixin may not work

That's the same as with @JsonComponent, right? Should be no problem, we just need to document it here.

Comment From: terminux

Thank you very much for your guidance @mhalbritter . Adding @Scope("prototype") to @JsonMixin is indeed a good option, at least better than having the user add the @Lookup . I've updated the PR.

Comment From: wilkinsona

I don't think @JsonMixin should be annotated with @Component at all. We don't want the mixins to be beans, prototypes or otherwise. Instead, I would use a custom sub-class of ClassPathScanningCandidateComponentProvider that overrides isCandidateComponent to find the @JsonMixin-annotated classes. They can then be registered with the JsonMixinModule by extracting information from the bean definitions that ClassPathScanningCandidateComponentProvider returns. The latter part of this is similar to what EntityScanner already does.

Comment From: terminux

Thank you so much for your reply @wilkinsona, very good suggestion. I will adjust the way to find mix-in classes based on your suggestion.

Comment From: terminux

Hi, I updated the PR and it is ready to be reviewed again.

Comment From: wilkinsona

This is looking really good now, @terminux. Thank you. The only thing I'm not completely sure about is the need for @JsonMixinScan. I'm in two minds about whether or not it needs to be separately configurable, of it we should just use the "main" packages for scanning for @JsonMixin-annotated types. I'll flag this for a forthcoming team meeting so that we can discuss it.

Comment From: philwebb

We discussed this today on our team call and we'd like to proceed but without the @JsonMixinScan annotation. We take that on as part of the merge. Thanks @terminux.

Comment From: wilkinsona

Thanks very much for the contribution, @terminux.