spring-bootannotationsspring-integrationspring-annotationscomponent-scan

IntegrationComponentScan with an explicit basePackages required in Spring Boot?


I have a Spring Boot application (using Spring Boot 2.4.11) where I'm using Spring Integration. I added the org.springframework.boot:spring-boot-starter-integration and hence I expected @IntegrationComponentScan to be active by default. Indeed, I find Issue 2037 that seems to suggest this. Also, I see that annotation on org.springframework.boot.autoconfigure.integration.IntegrationAutoConfigurationScanRegistrar.IntegrationComponentScanConfiguration.

However, my @MessagingGateway annotated interfaces were not taken up by Spring. I tried to add an explicit @IntegrationComponentScan on one of my @Configuration classes, but it didn't work either.

It started to work once I also specified an explicit basePackages value for that annotation, so:

@Configuration
@IntegrationComponentScan(basePackages = "com.example.app.integration")
public class MyConfigurationClass {
}

and of course my annotated interfaces are in a package below com.example.app.integration.

Am I missing something? I couldn't find any reference to @IntegrationComponentScan in Spring Boot documentation. Other similar annotations (like @EnableJpaRepositories for Spring Data or @EntityScan) are not strictly necessary, unless you need to customize the scanning scope.

I also found Issue 3375, that seems to suggest that I should look at @AutoConfigurationPackage, but:


Solution

  • I think you need to show your project structure. It works as expected:

    1. I have an interface like com.example.integration.gateway.MyGateway

    2. My main class is in the com.example.integration.IntegrationApplication with a content like:

      @SpringBootApplication
      public class IntegrationApplication {
      

    It still works even if I have that MyGateway in the com.example.integration package.

    To conclude. The @SpringBootApplication is marked with the @ComponentScan where Spring starts scanning components from the package where this @SpringBootApplication is declared and all the way down to its sub-packages.

    If your components are in a different from @SpringBootApplication class, then consider to have it customized via its scanBasePackages property:

    /**
     * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
     * for a type-safe alternative to String-based package names.
     * <p>
     * <strong>Note:</strong> this setting is an alias for
     * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
     * scanning or Spring Data {@link Repository} scanning. For those you should add
     * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
     * {@code @Enable...Repositories} annotations.
     * @return base packages to scan
     * @since 1.3.0
     */
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};
    

    Everything else needs an investigation already inside your project. If you can share that with us, we can take a look and find something.

    UPDATE

    Turned out when an XML configuration for <int:gateway> is in use, Spring Boot auto-configuration for @IntegrationComponentScan backs-off and requires to be provided explicitly to make @MessagingGateway interfaces to be visible. This problem was fixed in Spring Boot 3.0 as a side-effect of some other fix.