Access to OSGi services through a bus
It is often useful to proxy calls to services exported by a Blueprint context through a service bus.
The bus could be used to log incoming calls, adapt/filter the call arguments and the result, transparently forward requests to a remote OSGi container, broadcast to several remote containers or forward to the more powerful Fuse Fabric endpoints.
Exporting a regular interface to a Camel endpoint is key to this functionality.
Figure 1: Direct service binding |
![]() |
Figure 2: Binding to a Camel proxy |
![]() |
Camel Bean Invocation
Camel allows to wrap calls to interfaces in BeanInvocation objects within Exchanges and then send them through endpoints such as JMS, HTTP, etc.
Camel supports 3 approaches to bean invocation:
- The bean component which invokes a bean in the bean registry (e.g. Blueprint)
- POJO producing where proxies that automate the bean invocation are injected through annotations.
- Spring remoting where the proxies used in POJO producing are created explicitly.
Spring Remoting
We’ll employ Spring remoting to explicitly create service proxies linked to Camel endpoints and export these proxies as OSGi services in the Blueprint container.
Given the following interface:
interface TaskManager { Task save(Task task); void delete(String id); Task find(String id); }
The Blueprint container implementing the TaskManager service makes it available through Camel endpoint activemq:queue:io.modio.blog.osgi.camel.proxy:
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <bean id="taskManager" class="io.modio.blog.osgi.camel.proxy.impl.TaskManagerImpl"/> <camelContext id="camelContext" xmlns="http://camel.apache.org/schema/blueprint"> <route> <from uri="activemq:queue:io.modio.blog.osgi.camel.proxy"/> <to uri="bean:taskManager"/> </route> </camelContext> </blueprint>
The proxy to the TaskManager service can be in the same or a different Blueprint container:
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <camelContext id="camelContext" xmlns="http://camel.apache.org/schema/blueprint"> <proxy id="taskManagerProxy" serviceUrl="activemq:queue:io.modio.blog.osgi.camel.proxy" serviceInterface="io.modio.blog.osgi.camel.proxy.TaskManager"/> </camelContext> <service interface="io.modio.blog.osgi.camel.proxy.TaskManager" ref="taskManagerProxy"/> </blueprint>
Alternatively if the proxy is defined outside the camel context then the blueprint container and camel context ID need to be set explicitly and afterPropertiesSet() needs to be called:
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <camelContext id="camelContext" xmlns="http://camel.apache.org/schema/blueprint"> </camelContext> <bean id="taskManagerProxyFactory" init-method="afterPropertiesSet" class="org.apache.camel.blueprint.CamelProxyFactoryBean"> <property name="serviceUrl" value="activemq:queue:io.modio.blog.osgi.camel.proxy"/> <property name="serviceInterface" value="io.modio.blog.osgi.camel.proxy.TaskManager"/> <property name="camelContextId" value="camelContext"/> <property name="blueprintContainer" ref="blueprintContainer"/> </bean> <service interface="io.modio.blog.osgi.camel.proxy.TaskManager"> <bean factory-ref="taskManagerProxyFactory" factory-method="getObject"/> </service> </blueprint>
This will affect both the bootstrapping of the service consumer Blueprint container and the semantics of the calls to the service when the underlying service is not available:
Direct Service Binding | Binding to a Camel Proxy |
Blueprint container initialization will block until service becomes available | Blueprint container will complete initialization and bind to the proxy. |
Call to the service reference will block until the service becomes available again or a timeout occurs in which case a ServiceUnavailableException exception is thrown. | Blueprint container will call the proxy. The behavior of the call will depend on the Camel routing setup. E.g.
|
The Blueprint container on the consuming side is:
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <reference id="taskManager" interface="io.modio.blog.osgi.camel.proxy.TaskManager"/> <bean id="driver" class="io.modio.blog.osgi.camel.proxy.Driver"> <property name="taskManager" ref="taskManager"/> </bean> </blueprint>