0

The question is simple, but I can't find answer - Can I state that all declarative services in bundle A become available after bundle A start? For example,

bundle=context.installBundle("file:bundleA-1.0.0.jar");
bundle.start();
//In this point are declarative services of bundle A 100% available?

P.S. I use apache felix, but I think it must be defined in Specs but not in implementation.

EDIT:
I assume that DS runtime is running, config is present and all mandatory references are present.

Pavel_K
  • 10,748
  • 13
  • 73
  • 186

2 Answers2

2

The answer to your question is a very simple: NO. There are NO guarantees about availability in OSGi ever based on neither timing nor ordering. The only guarantees are specified in the service events.

It is one of the greatest causes of complexity to make timing/ordering assumptions in your code because they are always violated in the most obscure way.

DS makes it trivial to write code that correctly reacts to the service dependencies as they come and go. Making sure that you get those guarantees associated with services is incredibly complex and you destroy all that value if you start to make assumptions that something should be available after you call a method.

In your example, just rely on a service that you need. If that service is available, then you are sure all initialization is done.

If you stick to service dependencies life in OSGi is fairly easy and very robust.

UPDATED with example after questions

One the non-OSGi side:

 systemBundleContext = ... create framework
 systemBundleContext.registerService( 
    BundleActivator.class, 
    new BundleActivator() {
        public void start(BundleContext c) {
           // start non-OSGi code
        }
        public void stop(BundleContext c) {
           // stop non-OSGi code
        }
     },
     null );

DS Component:

 @Component
 public class Initiator {
    @Reference
    BundleActivator ba;

    @Referenc
    MyService myService;

    @Activate void activate(BundleContext context) throws Exception {
      ba.start(context);
    }

    @Deactivate void deactivate(BundleContext context) throws Exception {
      ba.stop(context);
    }
 }      
Peter Kriens
  • 15,196
  • 1
  • 37
  • 55
  • Let's suppose I have only one declarative service - service A. And I need to use this service in usual code, not in another osgi services. So do I understand you right - that the only way is to use service tracker in such situation? – Pavel_K Aug 08 '16 at 10:14
  • ServiceTracker could work but there is a much easier solution. The issue is one of **control** (which I regard as one of the most interesting least discussed aspects of writing code). What I would probably do is register a BundleActivator service on the non-OSGi side and then create an immediate DS component in the OSGi side with the proper dependencies. This component calls out to the framework side service on activate/deactivate. This way you have the control on the DS side and the non-OSGi side follows it. – Peter Kriens Aug 08 '16 at 10:27
  • I read you comment several times.. but.. could you give example in code what you mean? – Pavel_K Aug 08 '16 at 11:24
  • Thank you very much, Now I need to understand your code. Sorry for my questions...After your code I think I don't know osgi at all. What is framework? What class is it? – Pavel_K Aug 08 '16 at 12:08
  • I might have misunderstood your question then. I understood you run code as bundles and code that runs outside the framework. If all your code is running as a bundle, then why not just use DS? – Peter Kriens Aug 08 '16 at 13:01
  • Ok. I will give details. I have a non osgi code. This non osgi code starts osgi framework (felix) and after that installs and starts one bundle - bundle A. There are DS in bundle A. How can I outside osgi framework (in my non osgi code) be sure that DS from bunle A are available ? – Pavel_K Aug 08 '16 at 13:09
  • So my example code does exactly that. The framework object is the Bundle Context you get for the system bundle when you create the Felix OSGi framework. – Peter Kriens Aug 08 '16 at 13:16
  • Thank you very much. This is what I need (but I haven't tested yet). I suggest you to edit you answer and istead of `framework` write `BundleContext systemBundleContext` – Pavel_K Aug 08 '16 at 13:26
0

You can not assume that all DS Components are available as services after bundle start. The first thing is that the DS runtime must also be running. Then DS components by default are lazily activated. This means they are active only when some other bundle requires such a service and last but not least components only are activated once all their mandatory references are present. Well ... and before I forget it it you can also define that a component is only activated if a config is present for it.

Christian Schneider
  • 19,420
  • 2
  • 39
  • 64
  • In this case only the lazy loading remains as a cause. Do you use immediate=true? – Christian Schneider Aug 08 '16 at 07:48
  • I think there is difference between available service and service with created instance. When I say available I mean that if this service is necessary then OSGI framework will create its instances. – Pavel_K Aug 08 '16 at 08:04
  • Honestly I am a bit confused what you are really asking. Is this just a theoretical question or do you have a concrete service that does not seem to start. – Christian Schneider Aug 08 '16 at 08:06