piątek, 17 października 2014

Spring component-scan classpath pitfall

There is one non-intuitive behavior with Spring's component-scan - it works on _current_ classpath. For example:

Project A

context-a.xml:

    <component-scan package="x">


Project B

context-a.xml:

    <import resource="classpath:/a.xml" /> 

    <component-scan package="x.y">


This will load all components from  package "x.y" already at <import> tag.  It can lead to very strange errors in bigger projects (sudden appearance of "NoSuchBeanDefinitionException: No qualifying bean of type" errors) and  trying to cherry-pick used imports/components might be hard or even impossible.
There is similar issue with integration tests - Spring will scan all classes in package, including test files, for components. If you are using inner static classes to override context configuration spring will pick up all of them. And that problem might propagate if you are reusing test support code (<classifier>tests</classifier>). Lucky this one is easy to deal with: it is possible to filter it out:
<context:component-scan base-package="my.package" >
        <context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration" />
        <context:exclude-filter type="regex" expression=".*IT" />
        <context:exclude-filter type="regex" expression=".*Test" />
</context:component-scan>