∫created

Integration created

How to scan Spring components in OSGi

TL;DR

Spring cannot scan components in OSGi environment. This problem come from the fact that Spring uses classpath scanning to find components. In OSGi environment, classes are loaded from bundles. So, Spring cannot find them.

Workaround

To solve this problem we cannot use @ComponentScan annotation. Instead, we need to use @Import annotation to import all the components we need.

    @Configuration
    @Import({
        AwesomeService1.class,
        AwesomeService2.class,
        AwesomeService3.class
        ...
    })
    

It’s not a good solution, but it works. However, it is not a good practice to import all the components manually. So, we need to find a better solution.

We need to:

  • find a way to scan components in OSGi environment
  • add found components to the Spring context

Solution

Value of @Import annotation can be injected with helper method changeAnnotationValue:

    public static void changeAnnotationValue(Annotation annotation, String attributeName, Object newValue) {
      try {
          Field f = annotation.getClass().getDeclaredField("memberValues");
          f.setAccessible(true);
          Map<String, Object> memberValues = (Map<String, Object>) f.get(annotation);
          memberValues.put(attributeName, newValue);
      } catch (Exception e) {
          throw new RuntimeException(e);
      }
  }

Not forget to add @Import annotation to the configuration class with empty value:

    @Configuration
    @Import({})
    public class PortalConfig {
    ...
    }

Conclusion

Hope that this solution will help you to solve the same problem when integrating Spring Framework with OSGi environment!