How to run Spring-DM based applications on Fuse 7?

Solution Verified - Updated

Environment

  • Red Hat Fuse 7
    • Karaf runtime (OSGi)
  • Spring Dynamic Modules (Spring-DM) based application

Issue

  • Can Spring-DM based applications still be run on Fuse 7?
  • My Spring-DM based application does not start on Fuse 7. It works on Fuse 6.
  • Does Red Hat still support running Spring-DM based applications on Fuse 7?

Resolution

Spring-DM got deprecated in Fuse 6.2 already and is not supported in Fuse 7.

Customers are recommended to migrate their Spring-DM based applications to OSGi Blueprint.

Thus by default Spring-DM based applications will not start when deployed to Fuse 7.

However, if there's really a need to run applications that use Spring-DM, there is the Karaf feature from the Aries project called aries-blueprint-spring.
When having the aries-blueprint-spring Karaf feature installed, a bundle containing Spring-DM compliant XML may be processed and run as normal Blueprint bundle.
Please note again that Red Hat offers no support for the aries-blueprint-spring Karaf feature and for running Spring-DM based applications on Fuse 7.

Therefore the aries-blueprint-springKaraf feature should not be used as replacement for Blueprint, which is the officially supported Dependency Injection technology on Apache Karaf and Fuse 7 Karaf. This feature should be treated as temporary solution while migrating any old Spring-DM applications to Blueprint.

Diagnostic Steps

This aries-blueprint-spring Karaf feature contains two bundles:

    mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.spring/0.6.0
    mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.spring.extender/0.4.0

The responsibility of org.apache.aries.blueprint.spring bundle is to process all installed bundles in search for META-INF/spring.handlers resources - that's what Spring itself does. All registered (original) Spring namespace handlers are then wrapped in Blueprint specific org.apache.aries.blueprint.spring.BlueprintNamespaceHandler class that delegates to Spring specific org.springframework.beans.factory.xml.NamespaceHandler.

Thus, in generic manner, all Spring namespace handlers (and for example Camel/Spring specific namespace handler for http://camel.apache.org/schema/spring namespace) become available for Blueprint.

The responsibility of org.apache.aries.blueprint.spring.extender bundle is to process all bundles that may contain old Spring-DM XML declarations. In addition, this bundle registers own Blueprint-specific handlers for namespaces that were originally provided/handled by Spring-DM:

    http://www.springframework.org/schema/osgi
    http://www.springframework.org/schema/osgi-compendium

The process of determining whether given bundle is a Spring-DM bundle is:

  • check for META-INF/MANIFEST.MF header Spring-Context that specifies the paths for XML resources. This path may contain * wildcards.
  • If no such header exists, paths matching META-INF/spring/*.xml pattern are checked (just like it was done by Spring-DM itself)

Thus, having aries-blueprint-spring installed, a bundle containing Spring-DM compliant XML may be processed and run as normal Blueprint bundle. Such XML may contain well known constructs like:

<beans xmlns="http://www.springframework.org/schema/beans">
  ...
  <bean id="client" class="com.example.Client">
    <property name="txManager" ref="txManager" />
  </bean>
  ...
</beans>

It may also use Spring-DM-specific OSGi integration like:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:osgi="http://www.springframework.org/schema/osgi">
  ...
  <osgi:service interface="com.example.IClient" ref="client" />
  ...
  <osgi:reference id="mvn" interface="org.osgi.service.url.URLStreamHandlerService" filter="(url.handler.protocol=mvn)" />
  ...
</beans>

All the above constructs will be transformed into Blueprint specific OSGi integration (proxies, service references, ...).

Not everything works as expected. For example, using:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context">
  ...
  <context:component-scan base-package="com.example.services" />
  ...
</beans>

leads to this exception:

2019-06-10 14:48:50,978 WARN  {pool-18-thread-3} [org.springframework.core.io.support.PathMatchingResourcePatternResolver.doFindPathMatchingFileResources()] (PathMatchingResourcePatternResolver.java:721) : Cannot search for matching files underneath URL [bundle://238.1:1/com/example/services/] because it does not correspond to a directory in the file system
java.io.FileNotFoundException: URL [bundle://238.1:1/com/example/services/] cannot be resolved to absolute file path because it does not reside in the file system: bundle://238.1:1/com/example/services/
	at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:215) ~[175:org.apache.servicemix.bundles.spring-core:4.3.20.RELEASE_1]
	at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52) ~[175:org.apache.servicemix.bundles.spring-core:4.3.20.RELEASE_1]
	at org.springframework.core.io.UrlResource.getFile(UrlResource.java:213) ~[175:org.apache.servicemix.bundles.spring-core:4.3.20.RELEASE_1]
...

because <context:component-scan> doesn't work well with OSGi dynamism (and the fact that bundle may be completely virtual, without the ability to scan for classes.

Product(s)
Components
Category
Tags

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.