0

Context

I know there are a lot of posts regarding the comparison between these two. All of them just focus on @Import works on single Config file while @ComponenentScan will scan all config, bean, service files.

I find something new, hope someone can give me a good explanation behind this:

Prerequisite Artifact:

  • org.springframework.boot.autoconfigure
  • org.springframework.boot.test
@SpringBootTest(classes = test1char.class)
@ComponentScan("org.springframework.boot.autoconfigure.jackson")
//@SpringBootTest(classes = test1char.class)
//@Import(org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.class)
public class ObjectMapperTest {

    //cannot autowired: no such bean when using ComponenentScan
    // Can autowired when either using @Import 
    // or @SpringBootTest(classes = org.springframework.boot.autoconfigure.jackson.class)

    @Autowired
    ObjectMapper objectMapper;

    @Test
    void main() {
        var date = LocalDateTime.now();//LocalDateTime
        String s;
        try {
            s = objectMapper.writeValueAsString(date);
            System.out.println(s);
        }catch (JsonProcessingException e){
            System.out.println(e);
        }

       
    }
}

ObjectMapper bean producer class: org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.class for reference


@AutoConfiguration
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {

    .... omit
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({Jackson2ObjectMapperBuilder.class})
    static class JacksonObjectMapperConfiguration {
        JacksonObjectMapperConfiguration() {
        }

        @Bean
        @Primary
        @ConditionalOnMissingBean
        ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
            return builder.createXmlMapper(false).build();
        }
    }

Issue

Basically the ObjectMapper cannot autowired: no such bean when using ComponenentScan. But it can be autowired when either using @Import or @SpringBootTest(classes = org.springframework.boot.autoconfigure.jackson.class)

Note: test1char.class is just a dummy class so that it has a context while not using the default SpringBootApplication which has everything in class path

I know it must have something to do with ConditionalOnClass which requires some class in jar org.springframework.boot.autoconfigure.jackson to be in classpath. So I boldly guess only @Import and @SprngBoot and @SpringBootTest can load class or package to be in classpath? That's why quite often ObjectMapper cannot be autoconfigured in @SpringBootTest annotated integration test as we often forgot to add the jar to it.

Update

Hate to say with @EnableAutoConfiguration it works all good like below: @ComponentScan("org.springframework.boot.autoconfigure.jackson") @EnableAutoConfiguration

Update

Actually @EnableAutoConfiguration alone also works without @ComponentScan.

-- One who is always confused by SpringBoot config xD

Attachment: Condition Report output in Intellij when using @ComponenetScan

============================ CONDITIONS EVALUATION REPORT

Positive matches:

None

Negative matches:

None

Exclusions:

None

Unconditional classes:

None
Stan
  • 602
  • 6
  • 23
  • Update title as well so please don't do the quick judge – Stan Aug 24 '22 at 08:52
  • autoconfigurations aren't detected by an componentscan because they aren't components. – M. Deinum Aug 24 '22 at 11:12
  • @M.Deinum Sorry can you give a bit more context? which issue are you trying to comment on? – Stan Aug 24 '22 at 11:14
  • Your question why they aren't detected by componentscan. – M. Deinum Aug 24 '22 at 11:20
  • @M.Deinum the job of `@ComponentScan` is to scan given packages and register beans annotated with Stereotype annotations (`@Component`, `@Configuration`, `@Service`, `@Repository`) – Stan Aug 24 '22 at 11:47
  • Trust me I know what the job of `@ComponentScan` is as well as `@Import`. You shouldn't use those on tests they work by accident not by design. It is an auto configuration whcih will work when that is enabled if not it won't work. – M. Deinum Aug 24 '22 at 11:54
  • Ok I got what you mean JacksonAutoConfiguration is not Bean annotated. It is annotated with `@EnableAutoConfiguration`. Then I don't see any reason why `@Import` works @M.Deinum – Stan Aug 24 '22 at 13:02
  • @M.Deinum And isn't it also meaning that `I@mport` can `@EnableAutoConfiguration` – Stan Aug 24 '22 at 13:06

0 Answers0