Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring component-scan in OSGi finds nothing

Using the Spring-Context MANIFEST definitions, I'm trying to do a component-scan to search packages for Spring annotated beans. My Spring XML configuration looks something like this:

<?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?

Edit

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:

  1. Put your configurations per module in a Spring 3 @Configuration bean.
  2. Use an XML file in your top level bundle that initializes the @Configuration bean.
  3. In the top level @Configuration bean use the @Import to import the other configuration files.
  4. Make sure to Require-Bundle in your MANIFEST to ensure the configuration you're importing is available.
like image 476
Arthur Maltson Avatar asked Nov 30 '11 19:11

Arthur Maltson


1 Answers

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: Chapter 8. Packaging and Deploying Spring-based OSGi applications

like image 93
Danail Nachev Avatar answered Sep 19 '22 06:09

Danail Nachev