Not familiar with OSGi Declarative Services, so there will be some
guesswork on my part...

Yes, I use OsgiCamelTracker to control the Camel-using bundles.  But
it also tracks whether the CamelContext-singleton-providing service
(ContextUtil) is up.  That service in turn depends on an instance of
org.apache.camel.spi.TypeConverterLoader service.

camel-core has a BundleActivator.  That activator starts a
BundleTracker that checks every bundle that launches (including
itself) to see if it contains components that need to be loaded.  It
registers the components as services first, then it registers
TypeConverterLoader.

>From the example you gave, it looks like you need to create another
class that binds to TypeConverterLoader, generates and starts a
CamelContext, and then registers itself as a service; then your
CamelStarter class would bind to that service along with the
ComponentResolver(s), and fetch the CamelContext from that service.

Can you bind to multiple services via your XML, such that your class
won't activate until all the other services are found?

Don

On Tue, Jun 21, 2011 at 3:21 PM, Michael Furtak <[email protected]> wrote:
> Hi Don,
>
> I reviewed your sample code. Thanks very much for sharing that with me. If I 
> understand the intent and explanation correctly, you are using your 
> OsgiCamelTracker to delay the start-up of your Camel-using code until you can 
> be sure that the requisite ComponentResolver services have become available.
>
> In my current project we use OSGi Declarative Services, so I have set up an 
> OSGi component (yay, overloaded terms!) that requests a service reference for 
> a ComponentResolver that can provide the Camel 'file' component. This should 
> have the same effect of delaying the activation of my CamelStarter class 
> until that service can be bound. Here's the DS xml:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"; 
> name="com.cra.camelsandbox.CamelStarter">
>   <implementation class="com.cra.camelsandbox.CamelStarter"/>
>   <reference bind="bindComponentResolver" cardinality="1..1" 
> interface="org.apache.camel.spi.ComponentResolver" name="ComponentResolver" 
> policy="dynamic" target="(component=file)" unbind="unbindComponentResolver"/>
> </scr:component>
>
>
> And the Java class itself:
>
> public class CamelStarter
> {
>  private static final transient Logger LOG = 
> LoggerFactory.getLogger(CamelStarter.class);
>
>  protected void activate(ComponentContext context) throws Exception
>  {
>    LOG.trace("activating");
>    CamelContext camelContext = new 
> OsgiDefaultCamelContext(context.getBundleContext());
>    // camelContext.start();
>  }
>
>  protected void deactivate(ComponentContext context)
>  {
>    LOG.trace("deactivating");
>  }
>
>  protected void bindComponentResolver(ComponentResolver cr)
>  {
>    LOG.trace("Binding ComponentResolver");
>    // Ignored, since the ComponentResolver is not directly used
>  }
>
>  protected void unbindComponentResolver(ComponentResolver cr)
>  {
>    LOG.trace("Unbinding ComponentResolver");
>    // Ignored, since the ComponentResolver is not directly used
>  }
> }
>
> With the third line of the activate method commented out, everything seems to 
> go as planned:
>
> [21 Jun 2011 15:08:19]  TRACE [Component Resolve Thread (Bundle 12)] 
> CamelStarter - Binding ComponentResolver
> [21 Jun 2011 15:08:19]  TRACE [Component Resolve Thread (Bundle 12)] 
> CamelStarter - activating
>
>
> But if I uncomment it, I get this:
>
> java.lang.reflect.InvocationTargetException
>        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>        at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>        at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>        at java.lang.reflect.Method.invoke(Method.java:597)
>        at 
> org.eclipse.equinox.internal.ds.model.ServiceComponent.activate(ServiceComponent.java:210)
>        at 
> org.eclipse.equinox.internal.ds.model.ServiceComponentProp.activate(ServiceComponentProp.java:139)
>        at 
> org.eclipse.equinox.internal.ds.model.ServiceComponentProp.build(ServiceComponentProp.java:339)
>        at 
> org.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess.java:588)
>        at 
> org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:196)
>        at 
> org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:441)
>        at 
> org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:213)
>        at 
> org.eclipse.equinox.internal.ds.SCRManager.performWork(SCRManager.java:800)
>        at 
> org.eclipse.equinox.internal.ds.SCRManager$QueuedJob.dispatch(SCRManager.java:767)
>        at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:89)
>        at 
> org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run(Executor.java:70)
> Caused by: org.apache.camel.RuntimeCamelException: Error staring 
> OSGiTypeConverter due: Failed to load type converters because of: Cannot find 
> any type converter classes from the following packages: 
> [org.apache.camel.component.file, org.apache.camel.component.bean, 
> org.apache.camel.converter]
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.createRegistry(OsgiTypeConverter.java:206)
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.getDelegate(OsgiTypeConverter.java:164)
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.addingService(OsgiTypeConverter.java:69)
>        at 
> org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:896)
>        at 
> org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:261)
>        at 
> org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:184)
>        at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:339)
>        at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:273)
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.doStart(OsgiTypeConverter.java:102)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:67)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:54)
>        at 
> org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:60)
>        at 
> org.apache.camel.impl.DefaultCamelContext.startServices(DefaultCamelContext.java:1613)
>        at 
> org.apache.camel.impl.DefaultCamelContext.addService(DefaultCamelContext.java:899)
>        at 
> org.apache.camel.impl.DefaultCamelContext.getTypeConverter(DefaultCamelContext.java:984)
>        at 
> org.apache.camel.impl.DefaultCamelContext.getTypeConverterRegistry(DefaultCamelContext.java:1001)
>        at 
> org.apache.camel.impl.DefaultCamelContext.forceLazyInitialization(DefaultCamelContext.java:1940)
>        at 
> org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:1423)
>        at 
> org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:1336)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:67)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:54)
>        at 
> org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:1314)
>        at com.cra.camelsandbox.CamelStarter.activate(CamelStarter.java:18)
>        ... 15 more
> Caused by: org.apache.camel.TypeConverterLoaderException: Failed to load type 
> converters because of: Cannot find any type converter classes from the 
> following packages: [org.apache.camel.component.file, 
> org.apache.camel.component.bean, org.apache.camel.converter]
>        at 
> org.apache.camel.impl.converter.AnnotationTypeConverterLoader.load(AnnotationTypeConverterLoader.java:79)
>        at 
> org.apache.camel.impl.converter.BaseTypeConverterRegistry.loadTypeConverters(BaseTypeConverterRegistry.java:395)
>        at 
> org.apache.camel.impl.converter.DefaultTypeConverter.doStart(DefaultTypeConverter.java:41)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:67)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:54)
>        at 
> org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:60)
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.createRegistry(OsgiTypeConverter.java:202)
>        ... 37 more
> Root exception:
> org.apache.camel.RuntimeCamelException: Error staring OSGiTypeConverter due: 
> Failed to load type converters because of: Cannot find any type converter 
> classes from the following packages: [org.apache.camel.component.file, 
> org.apache.camel.component.bean, org.apache.camel.converter]
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.createRegistry(OsgiTypeConverter.java:206)
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.getDelegate(OsgiTypeConverter.java:164)
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.addingService(OsgiTypeConverter.java:69)
>        at 
> org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:896)
>        at 
> org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:261)
>        at 
> org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:184)
>        at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:339)
>        at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:273)
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.doStart(OsgiTypeConverter.java:102)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:67)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:54)
>        at 
> org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:60)
>        at 
> org.apache.camel.impl.DefaultCamelContext.startServices(DefaultCamelContext.java:1613)
>        at 
> org.apache.camel.impl.DefaultCamelContext.addService(DefaultCamelContext.java:899)
>        at 
> org.apache.camel.impl.DefaultCamelContext.getTypeConverter(DefaultCamelContext.java:984)
>        at 
> org.apache.camel.impl.DefaultCamelContext.getTypeConverterRegistry(DefaultCamelContext.java:1001)
>        at 
> org.apache.camel.impl.DefaultCamelContext.forceLazyInitialization(DefaultCamelContext.java:1940)
>        at 
> org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:1423)
>        at 
> org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:1336)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:67)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:54)
>        at 
> org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:1314)
>        at com.cra.camelsandbox.CamelStarter.activate(CamelStarter.java:18)
>        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>        at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>        at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>        at java.lang.reflect.Method.invoke(Method.java:597)
>        at 
> org.eclipse.equinox.internal.ds.model.ServiceComponent.activate(ServiceComponent.java:210)
>        at 
> org.eclipse.equinox.internal.ds.model.ServiceComponentProp.activate(ServiceComponentProp.java:139)
>        at 
> org.eclipse.equinox.internal.ds.model.ServiceComponentProp.build(ServiceComponentProp.java:339)
>        at 
> org.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess.java:588)
>        at 
> org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:196)
>        at 
> org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:441)
>        at 
> org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:213)
>        at 
> org.eclipse.equinox.internal.ds.SCRManager.performWork(SCRManager.java:800)
>        at 
> org.eclipse.equinox.internal.ds.SCRManager$QueuedJob.dispatch(SCRManager.java:767)
>        at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:89)
>        at 
> org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run(Executor.java:70)
> Caused by: org.apache.camel.TypeConverterLoaderException: Failed to load type 
> converters because of: Cannot find any type converter classes from the 
> following packages: [org.apache.camel.component.file, 
> org.apache.camel.component.bean, org.apache.camel.converter]
>        at 
> org.apache.camel.impl.converter.AnnotationTypeConverterLoader.load(AnnotationTypeConverterLoader.java:79)
>        at 
> org.apache.camel.impl.converter.BaseTypeConverterRegistry.loadTypeConverters(BaseTypeConverterRegistry.java:395)
>        at 
> org.apache.camel.impl.converter.DefaultTypeConverter.doStart(DefaultTypeConverter.java:41)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:67)
>        at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:54)
>        at 
> org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:60)
>        at 
> org.apache.camel.core.osgi.OsgiTypeConverter.createRegistry(OsgiTypeConverter.java:202)
>        ... 37 more
>
> Slightly off topic, your advice about needing to share the CamelContext 
> object as a singleton (wrt. SEDA, etc.) was received loud and clear. What you 
> see here is me just trying to keep my test cases simple for now.
>
>
> So that's where I am stuck at the moment. I'm sorry not to be working more 
> directly from your sample code, but please correct me if its service 
> management strategy/intent is different from my understanding. Does my 
> current problem make sense? What am I missing?
>
>
> Thanks,
> -Mike
>
>
>
>
>
>
>
>
> THIS MESSAGE IS INTENDED FOR THE USE OF THE PERSON TO WHOM IT IS ADDRESSED. 
> IT MAY CONTAIN INFORMATION THAT IS PRIVILEGED, CONFIDENTIAL AND EXEMPT FROM 
> DISCLOSURE UNDER APPLICABLE LAW. If you are not the intended recipient, your 
> use of this message for any purpose is strictly prohibited. If you have 
> received this communication in error, please delete the message and notify 
> the sender so that we may correct our records.
>
> -----Original Message-----
>
>
>
> From: Donald Whytock [mailto:[email protected]]
> Sent: Monday, June 20, 2011 4:45 PM
> To: [email protected]
> Subject: Re: Camel under OSGi without Spring et al.
>
> OsgiCamelTracker.java (attached) is a work in progress.  There's a
> reference to ContextUtil; that's the service class that supplies the
> CamelContext singleton.
>
> Use it by subclassing it and implementing methods start() and stop().
> Call setBundleContext(bundleContext) first, then startTracking().
>
> OsgiCamelTracker.startTracking() accepts no parameters, a single
> String, or a Collection<String>.  The strings are the names of
> components that you need.  It'll track instances of ComponentResolver,
> maintaining a list of what components are available and what
> components are still needed.  When all the components you need are
> available, it'll call start(); when any of the components cease to be
> available, it'll call stop().
>
> If you don't supply component names, it'll react to camel-core itself
> becoming active, which is all you need for core components like mock,
> bean and file.
>
> Use routeId(<name>) in your route definitions.  Use
> camelcontext.startRoute(<name>) from the OsgiCamelTracker.start(); use
> camelcontext.stopRoute(<name>) from the OsgiCamelTracker.stop().
>
> Be advised, you'll need to use a singleton CamelContext if you're
> using SEDA queues, because SEDA queues are local to a CamelContext
> instance.  A route that consumes from a SEDA queue from one
> CamelContext instance won't see anything produced to a SEDA queue from
> a different CamelContext instance.
>
> For OsgiDefaultCamelContext...
>
>> On Mon, Jun 20, 2011 at 3:31 PM, Michael Furtak <[email protected]> wrote:
>>> I did come across mention of this in my troubleshooting exploration. It 
>>> seems to be part of a bundle called camel-core-osgi, is that right? I don't 
>>> think I have it in my 2.7.2 distribution. Is it something I need to bundle 
>>> myself? I also saw mention of it being private to the Spring bundle, which 
>>> is what prompted my discussion about not wanting to bring in Spring.
>
> org.apache.camel.core.osgi is in camel-blueprint.jar.  I split it out
> into its own .jar so as to not worry about the Blueprint dependencies.
>  You'll need to modify the manifest, or make your own.
>
> Don
>
>

Reply via email to