Hi,

You have actually two issues. The first Is accessing an OSGi service from a 
route using Java DSL. Camel lookups are done in a Camel registry. The kind of 
registry depends on the way you start your camel context, if you are using 
blueprint to do that, you have a blueprint registry, if you are using Spring 
you have a spring registry and (AFAIK) if you are using Java DSL you are 
normally using a JNDI registry. The special thing about the blueprint registry 
is that it forwards lookups that cannot be resolved from the blueprint context 
to the OSGi service registry (so you can do lookups with the Camel registry 
that are doing OSGi service lookups). I don't think that is possible with Java 
DSL. However these OSGi lookups via the Camel registry are not very dynamic: 
The service object is retrieved via OSGi API and is pinned in memory (which is 
not exactly OSGi-like).

The other issue is when you are referencing services with blueprint. The user 
of this blueprint service reference will not get the service object itself, but 
a dynamic proxy object, that will remain the same even if you restart the 
service (it will even delay any calls to the service while it is gone to the 
time till it is back (or times out)). That way references injected during 
bundle startup will remain valid even if the underlying service is restarted. 

Therefore you can encounter three different behaviours when referencing an OSGi 
service (however this is registered) in a Camel route:
1. trying to reference it via the camel registry with a registry implementation 
different from the blueprint one doesn't work
2. referencing it via the camel registry with the blueprint implementation will 
work but only unless you restart the service
3. referencing the service via blueprint service reference and then referencing 
the service from the camel route will create a dynamic proxy object (that 
remains the same over the whole lifecycle but can cope with service restarts 
just all right).

Best regards
Stephan

-----Original Message-----
From: Quinn Stevenson [mailto:qu...@pronoia-solutions.com] 
Sent: Dienstag, 26. Januar 2016 23:11
To: users@camel.apache.org
Subject: Invoking Dynamic OSGi Blueprint services from a Java RouteBuilder

When I use an OSGi Service registered using Blueprint from a Java route (built 
using a Java RouteBuilder), the Camel route isn’t detecting the when the 
service is not available, and it isn’t updating when the service implementation 
changes.

The simple setup I’m using has a Java interface for the OSGi service in one 
bundle, and implementation of that interface which uses Blueprint to register 
the service in another bundle, and simple RouteBuilder that uses the service in 
a third bundle.  The implementation of the service is injected into the 
RouteBuilder using Blueprint, and the Camel context is configured in Blueprint 
in a fourth bundle.

After all these bundles are installed and started in Karaf, the run and the 
hashCode of service is logged every time the Camel timer fires and triggers an 
exchange.  If I stop the bundle that registers the service using Blueprint, the 
route continues to log the same hashCode when it calls the OSGi service.  I 
would expect a ServiceUnavailableException after a timeout.  

Additionally, when I restart the bundle that registers the service object, I 
continue to get the same hashCode.  I would expect to get a new hashCode value.

Am I doing something wrong?  Do I need to do something different do get the 
dynamic behavior I’m looking for?


The code looks like this:

Java Interface (service-interface bundle):
public interface Echo {
    String execute(String body);
}

Java Implementation:
public class EchoServiceOne implements Echo {
    Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public String execute(String body) {
        log.info( "{}:{} -> execute", this.getClass().getSimpleName(), 
this.hashCode() );
        return body;
    }
}


Blueprint Registering the service (service-one bundle):
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0";
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
           xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd";>

    <service interface="com.pronoia.test.osgi.service.Echo" >
        <service-properties>
            <entry key="instance" value="one" />
        </service-properties>
        <bean class="com.pronoia.test.osgi.service.impl.EchoServiceOne" />
    </service>

</blueprint>

Java RouteBuilder (route-builder bundle):
public class VerySimpleBuilder extends RouteBuilder {
    Echo blueprintServiceReference;

    @Override
    public void configure() throws Exception {
        from("timer://very-simple-builder?period=5000").routeId( 
"very-simple-route" )
                .setBody( simple( "${exchangeProperty[" + 
Exchange.TIMER_FIRED_TIME + "]}") )
                .log("Calling Service via Reference: ${body}" )
                .bean(blueprintServiceReference,false)
                .to( "mock://result")
                .log("Finished" );
    }

    public Echo getBlueprintServiceReference() {
        return blueprintServiceReference;
    }

    public void setBlueprintServiceReference(Echo blueprintServiceReference) {
        this.blueprintServiceReference = blueprintServiceReference;
    }
}

Blueprint constructing the Camel context (camel-context bundle):
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0";
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
           
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0";
           xsi:schemaLocation="
       http://www.osgi.org/xmlns/blueprint/v1.0.0 
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
       http://camel.apache.org/schema/blueprint 
http://camel.apache.org/schema/blueprint/camel-blueprint.xsd";
>

    <reference id="echo-service" interface="com.pronoia.test.osgi.service.Echo" 
filter="instance=one" timeout="2000" />

    <bean id="very-simple-route-builder" 
class="com.pronoia.test.camel.builder.VerySimpleBuilder">
        <property name="blueprintServiceReference" ref="echo-service" />
    </bean>

    <camelContext id="very-simple-context" 
xmlns="http://camel.apache.org/schema/blueprint";>
        <routeBuilder ref="very-simple-route-builder" />
    </camelContext>

</blueprint>


Reply via email to