7 Replies Latest reply on Mar 5, 2009 1:53 AM by thomas.diesler

    Runtime and bundle lifecycle/dependency resolution

    alesj

      In Runtime when we delegate most of the work to underlying OSGi framework,
      we still need to tie into existing MC's lifecycle/dependency handling.
      Otherwise the bundle will be pushed to Installed even though its cl isn't resolved.

      We need to add a new DependencyItem
      which does it's resolution based on Bundle resolution.

      e.g. BudleDependencyItem

      public boolean resolve(Controller controller)
      {
       return bundle.isResolved(); // pseudo method
      }
      


      Perhaps this also requires additional deployers
      that will change the Bundle's state.
      * one that would just install the bundle
      * another one that would create it
      * one that would start it (after bundle/cl was resolved)
      (I need to check the spec on how exactly this goes :-))


        • 1. Re: Runtime and bundle lifecycle/dependency resolution
          alesj

          When Bundle is put to resolved state is not defined by the spec.
          e.g. Felix does it like this


          [20:36:06] Ales Justin says: Bundle A depends on Bundle B
          [20:36:06] Ales Justin says: I 1st deploy A
          [20:36:26] Ales Justin says: so, Bundle a = bundleContext.installBundle(urlA);
          [20:36:32] Ales Justin says: its state is INSTALLED
          [20:36:39] Ales Justin says: I install B
          [20:36:48] Ales Justin says: is A's state then resolved?
          [20:37:05] Richard S Hall says: It is up to the framework, but for Felix, no.
          [20:37:34] Richard S Hall says: The framework can decide to resolve at any time it wants.
          [20:37:49] Richard S Hall says: For Felix, we wait for a start or an explicit resolve via PackageAdmin.


          So, I think we should try to make usage of impl details,
          exposed over our spi - if possible.
          In the worst case, use PackageAdmin - which is extension to core api.


          • 2. Re: Runtime and bundle lifecycle/dependency resolution
            thomas.diesler

            The fundamental problem is that a BundleContext.installBundle() does not attempt to resolve the just installed bundle. The information of whether a bundle can be resolved is therefore not available when BundleContext.installBundle() returns.

            Triggering the resolve process varies from framework to framework and in the simplest case will probably boil down to

            
            boolean startResolve()
            {
             try
             {
             bundle.start()
             return true;
             }
             catch (BundleException ex)
             {
             return false;
             }
            


            The above is no good however because it unintentionally starts the bundle.

            I'll have a look at Felix hot deployment - they must have the same problem.



            • 3. Re: Runtime and bundle lifecycle/dependency resolution
              alesj

               

              "thomas.diesler@jboss.com" wrote:

              I'll have a look at Felix hot deployment - they must have the same problem.

              You're not reading my posts. ;-)
              They are using PackageAdmin for that.

              So, to simplify things, let's go with this order:
              (1) try to locate PackageAdmin, and use it to chech if the bundle is resolved
              (2) provide a spi, so we can implement this on per framework impl details
              * we try to provide this - if we find the appropriate info easily
              * 'force' the users to provide this, if they didn't provide the PackageAdmin in the first place
              (3) implement this ugly hack via start() check
              * make it such, that it's not part of default usage - as a separate addon


              • 4. Re: Runtime and bundle lifecycle/dependency resolution
                thomas.diesler

                The PackageAdmin seems to be one of the core services provided by felix

                [tdiesler@tddell default]$ find . -name *.jar | xargs grep PackageAdmin
                Binary file ./deployers/osgi.deployer/org.apache.felix.framework.jar matches
                Binary file ./deployers/osgi.deployer/org.osgi.core.jar matches
                


                I'd suggest the BundleStartStopDeployer maintains a list of unresolved bundles and tries to resolve them before bundle.start() is attempted.

                We could make PackageAdmin a required service without which BundleStartStopDeployer cannot start bundles automatically.

                Only if this approach fails I'd investigate (2) or (3)

                • 5. Re: Runtime and bundle lifecycle/dependency resolution
                  alesj

                   

                  "thomas.diesler@jboss.com" wrote:

                  I'd suggest the BundleStartStopDeployer maintains a list of unresolved bundles and tries to resolve them before bundle.start() is attempted.

                  MC already does this.
                  Bundle == DeploymentControllerContext.

                  You're missing my point.
                  We should make sure the Bundle only gets to BSSD if it's properly resolved.
                  Any other hacking/duplicating is a step in the wrong direction.

                  "thomas.diesler@jboss.com" wrote:

                  We could make PackageAdmin a required service without which BundleStartStopDeployer cannot start bundles automatically.

                  I wouldn't be that strict.
                  Having PackageAdmin means having few more jars/bundles.
                  If it's there, great, if not fallback to (2) or in the worst case (3).

                  "thomas.diesler@jboss.com" wrote:

                  Only if this approach fails I'd investigate (2) or (3)

                  Fine by me.
                  As long as you make it behind under nice spi/api.

                  e.g. BundleClassLoaderDependencyDeployer::createResolveDependencyItem() could return diff DI instance based on what is available


                  • 6. Re: Runtime and bundle lifecycle/dependency resolution
                    alesj

                     

                    "alesj" wrote:
                    "thomas.diesler@jboss.com" wrote:

                    I'd suggest the BundleStartStopDeployer maintains a list of unresolved bundles and tries to resolve them before bundle.start() is attempted.

                    MC already does this.
                    Bundle == DeploymentControllerContext.

                    You're missing my point.
                    We should make sure the Bundle only gets to BSSD if it's properly resolved.
                    Any other hacking/duplicating is a step in the wrong direction.

                    Why do I see
                     // The list of unresolved bundles
                     private List<Bundle> unresolvedBundles = new ArrayList<Bundle>();
                    

                    when I explicitly said this is wrong?
                    Don't get me wrong or harsh or ..., but this way of interaction won't work.
                    At least you could argue/discuss/justify with me on this before you put it in.

                    To get into details even more.
                    All this code is just unnecessary, as it over complicates things
                     // Get the required dependency on the PackageAdmin service
                     if (packageAdmin == null)
                     {
                     ServiceReference sref = systemContext.getServiceReference(PackageAdmin.class.getName());
                     packageAdmin = (PackageAdmin)systemContext.getService(sref);
                     if (packageAdmin == null)
                     throw new IllegalStateException("Cannot obtain PackageAdmin service");
                     }
                    
                     // Always add the bundle as unresolved
                     unresolvedBundles.add(bundle);
                    
                     Bundle[] bundleArr = new Bundle[unresolvedBundles.size()];
                     unresolvedBundles.toArray(bundleArr);
                    
                     // Try to resolve the bundles
                     packageAdmin.resolveBundles(bundleArr);
                    
                     // Find resolved bundles and start them
                     Iterator<Bundle> it = unresolvedBundles.iterator();
                     while(it.hasNext())
                     {
                     Bundle auxBundle = it.next();
                     int state = auxBundle.getState();
                     if (Bundle.RESOLVED == state)
                     {
                     it.remove();
                     try
                     {
                     auxBundle.start();
                     log.info("Started: " + auxBundle.getSymbolicName() + ",state=" + auxBundle.getState());
                     }
                     catch (BundleException e)
                     {
                     log.warn("Cannot start bundle", e);
                     }
                     }
                     }
                    

                    A simple proper DI creation in BundleClassLoaderDependencyDeployer would do all of the "tricks" necessary:
                    * create proper spi/abstraction over what we can use
                    * limit PackageAdmin usage to DI
                    * no need to start all off the non-involved bundles

                    And I guess usage of system Bundle could also be reduced to minimum.
                    Perhaps moving the DI creation into OSGiDeployer.
                    Something to discuss ...


                    • 7. Re: Runtime and bundle lifecycle/dependency resolution
                      thomas.diesler

                      Please see http://www.jboss.org/index.html?module=bb&op=viewtopic&t=151463 on why the DependencyItem approach cannot not (yet) work