Spring component-scan in OSGi finds nothing
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <!-- Scans the classpath of this application for @Components to deploy as beans --> <context:component-scan base-package="com.some.other.module.one,com.another.module.two" /> <context:annotation-config /> .... </beans>
In the MANIFEST, I import the packages containing the classes with Spring annotations. However, when I inspect the ApplicationContext, it doesn't have any of the annotated beans in it.
I believe this is happening because the classpaths we're scanning are in different bundles. Those bundles don't directly importing the packages with the classes that have Spring annotations in them. What's confusing is why Spring doesn't pick up the classpath of the main bundle that the component-scan is started from? It seems as if it is using the classpath of each bundle when it's doing a classpath scan. Is there a way to get the classpath scan to use the classpath of the bundle the scan starts in?
As Danail Nachev said below, when Spring does a classpath scan, it happens only within the module that the classpath is happening in. The work around is to use:
- Put your configurations per module in a Spring 3 @Configuration bean.
- Use an XML file in your top level bundle that initializes the @Configuration bean.
- In the top level @Configuration bean use the @Import to import the other configuration files.
- Make sure to Require-Bundle in your MANIFEST to ensure the configuration you're importing is available.
OSGi is all about being modular, so it makes great deal to have clear separation between the bundles. If Spring can go and unite them under single ApplicationContext, will not be different than usual Spring application, where everything is available in single classpath. Something like this.
What's happening is that each bundle receives its own ApplicationContext. These ApplicationContexts can exchange beans using OSGi Service Registry. You need to mark beans as exported and import them in others ApplicationContexts, otherwise they are not visible to one another.
This should explain why you cannot configure everything with single Spring context and expect that starting from one bundle it would go and find all beans. Spring context scans only single bundle and optionally can import/export beans as OSGi services.
Interpreted from here: