6 Replies Latest reply on Sep 16, 2009 9:42 AM by thomas.diesler

    Cannot resolve circular dependencies

    thomas.diesler

      https://jira.jboss.org/jira/browse/JBOSGI-151

      The default bundles can currently not get deployed into AS520 because of this issue.

      The code that tries to resolve the bundles is in PackageAdminImpl and repeatedly calls OSGiBundleManager.resolve()

      AFAICS, circular dependencies cannot get resolved because bundle deployments are requested to change state one-by-one

       ControllerState requiredState = context.getRequiredState();
       DeploymentStage requiredStage = unit.getRequiredStage();
      
       try
       {
       deployerClient.change(unit.getName(), DeploymentStages.CLASSLOADER);
       deployerClient.checkComplete(unit.getName());
       bundleState.changeState(Bundle.RESOLVED);
       return true;
       }
       catch (DeploymentException ex)
       {
       unit.setRequiredStage(requiredStage);
       context.setRequiredState(requiredState);
      
       if (errorOnFail)
       throw new IllegalStateException("Error resolving bundle: " + bundleState, ex);
      
       return false;
       }
      


      I could not find an API similar to

       deployerClient.change(List<String> names, DeploymentStages);
      


      Any hint on a possible solution?

        • 1. Re: Cannot resolve circular dependencies
          thomas.diesler

          The underlying issue is that RequirementDependencyItem is constructed with a required state of the dependent that is hard coded to ControllerState.INSTALLED

           public RequirementDependencyItem(Module module, Requirement requirement, ControllerState state)
           {
           this(module, requirement, state, ControllerState.INSTALLED);
           }
          


          Perhaps the required state of the dependent should be taken from the Requirement itself.

          • 2. Re: Cannot resolve circular dependencies
            thomas.diesler

            It seems that PackageRequirements and their mapping onto RequirementDependencyItem is generally too simplistic.

            The uses clause is not taken into account for example.

            The plain circular dependency like this

            Bundle-SymbolicName: jbosgi151-bundleA
            Export-Package: org.jboss.test.osgi.jbosgi151.bundleA
            Import-Package: org.jboss.test.osgi.jbosgi151.bundleB
            
            Bundle-SymbolicName: jbosgi151-bundleB
            Export-Package: org.jboss.test.osgi.jbosgi151.bundleB
            Import-Package: org.jboss.test.osgi.jbosgi151.bundleA
            


            are probably not very common.

            What is common however, are circular dependencies with option of self dependency

            Bundle-SymbolicName: jbosgi151-bundleC
            Export-Package: org.jboss.test.osgi.jbosgi151.bundleA, org.jboss.test.osgi.jbosgi151.bundleB
            Import-Package: org.jboss.test.osgi.jbosgi151.bundleA, org.jboss.test.osgi.jbosgi151.bundleB
            
            Bundle-SymbolicName: jbosgi151-bundleD
            Export-Package: org.jboss.test.osgi.jbosgi151.bundleA, org.jboss.test.osgi.jbosgi151.bundleB
            Import-Package: org.jboss.test.osgi.jbosgi151.bundleA, org.jboss.test.osgi.jbosgi151.bundleB
            


            Perhaps fixing the latter is sufficient for Beta4 and we look at the more exotic use cases during the course of TCK work


            • 3. Re: Cannot resolve circular dependencies
              thomas.diesler

              I isolated the issue sufficiently to this problem

              BundleC
               exports A, B
               imports A
              
              BundleD
               exports A,
               imports A, B
              


              Both bundles will only resolve if one uses a self dependency.

              I modified the code such that the Domain warns if a requirement resolves against multiple modules

               Module firstMatch = null;
               for (Module other : modules)
               {
               List<Capability> capabilities = other.getCapabilities();
               if (capabilities != null)
               {
               for (Capability capability : capabilities)
               {
               if (capability.resolves(other, module, requirement))
               {
               if (firstMatch != null)
               {
               String otherName = other.getName() + ":" + other.getVersion();
               String firstName = firstMatch.getName() + ":" + firstMatch.getVersion();
               log.warn("Requirement " + requirement + " resolves agaist " + firstName + " and " + otherName + " - using first.");
               }
               if (firstMatch == null)
               firstMatch = other;
               }
               }
               }
               }
              


              and extended the Capability interface such that it allows capability/requirement matching in the context of both modules.

              public interface Capability extends Serializable
              {
               /**
               * Whether this capability resolves the requirement
               *
               * @param capModule the capability module
               * @param reqModule the requirement module
               * @param requirement the requirement
               * @throws IllegalArgumentException for a null requirement
               * @return true when it is resolves the requirement
               */
               boolean resolves(Module capModule, Module reqModule, Requirement requirement);
              }
              




              • 4. Re: Cannot resolve circular dependencies
                thomas.diesler

                The bundles resolve now

                21:17:00,207 INFO [FrameworkEventsPluginImpl] Bundle INSTALLED: Bundle{org.apache.felix.http.jetty:1.0.1}
                21:17:00,585 INFO [FrameworkEventsPluginImpl] Bundle INSTALLED: Bundle{osgi.cmpn:4.2.0.200907101024}
                21:17:00,967 INFO [OSGiBundleManager] Resolve: org.apache.felix.http.jetty:1.0.1
                21:17:01,010 INFO [OSGiPackageCapabilityCache] Blacklist module associations
                 [javax.servlet.http=org.apache.felix.http.jetty:1.0.1]
                 [javax.servlet=org.apache.felix.http.jetty:1.0.1]
                 [org.osgi.service.http=org.apache.felix.http.jetty:1.0.1]
                21:17:01,011 INFO [OSGiPackageCapabilityCache] Unresolved requirements
                 OSGiPackageRequirement{org.osgi.service.log [1.3.0,?) {version="1.3"}}
                 OSGiPackageRequirement{org.osgi.util.tracker [1.3.0,?) {version="1.3"}}
                 OSGiPackageRequirement{org.osgi.service.cm [1.2.0,?) {version="1.2"}}
                21:17:01,011 INFO [OSGiBundleManager] Resolve: osgi.cmpn:4.2.0.200907101024
                21:17:01,263 INFO [FrameworkEventsPluginImpl] Bundle RESOLVED: Bundle{osgi.cmpn:4.2.0.200907101024}
                21:17:01,264 INFO [OSGiPackageCapabilityCache] Endorse module associations
                 [org.osgi.service.blueprint.container=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.util.gsm=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.deploymentadmin.spi=osgi.cmpn:4.2.0.200907101024]
                 [info.dmtree=osgi.cmpn:4.2.0.200907101024]
                 [info.dmtree.spi=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.component=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.monitor=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.wireadmin=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.util.xml=osgi.cmpn:4.2.0.200907101024]
                 [info.dmtree.registry=osgi.cmpn:4.2.0.200907101024]
                 [info.dmtree.notification.spi=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.log=osgi.cmpn:4.2.0.200907101024]
                 [info.dmtree.security=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.prefs=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.application=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.metatype=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.io=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.application=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.http=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.util.mobile=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.util.measurement=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.provisioning=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.cm=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.util.cdma=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.blueprint.reflect=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.deploymentadmin=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.event=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.upnp=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.device=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.util.tracker=osgi.cmpn:4.2.0.200907101024]
                 [info.dmtree.notification=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.service.useradmin=osgi.cmpn:4.2.0.200907101024]
                 [org.osgi.util.position=osgi.cmpn:4.2.0.200907101024]
                21:17:01,265 INFO [OSGiBundleManager] Resolve: org.apache.felix.http.jetty:1.0.1
                21:17:01,389 INFO [FrameworkEventsPluginImpl] Bundle RESOLVED: Bundle{org.apache.felix.http.jetty:1.0.1}
                21:17:01,390 INFO [OSGiPackageCapabilityCache] Endorse module associations
                 [javax.servlet.http=org.apache.felix.http.jetty:1.0.1]
                 [javax.servlet=org.apache.felix.http.jetty:1.0.1]
                21:17:01,393 INFO [FrameworkEventsPluginImpl] Bundle STARTING: Bundle{org.apache.felix.http.jetty:1.0.1}
                21:17:01,862 INFO [FrameworkEventsPluginImpl] Service REGISTERED: Service{id=4 bundle=org.apache.felix.http.jetty:1.0.1 classes=[org.osgi.service.cm.ManagedService]}
                21:17:01,863 INFO [FrameworkEventsPluginImpl] Bundle STARTED: Bundle{org.apache.felix.http.jetty:1.0.1}
                


                However there is a classloading issue for org.osgi.service.http.HttpService, which is expected to come from compendium.

                AFAICS, The OSGiClassLoaderDomain uses DelegateLoaders backed by VFSClassLoaderPolicy delegates for both the http service bundle and the compendium. Since the DelegateLoader for the http service bundle comes first the class is loaded from there despite the fact that the package resolved against compendium.

                I need to figure out how to filter the packages from the delegates such that it is in sync with how the modules got resolved.


                • 5. Re: Cannot resolve circular dependencies

                  This is very broken. You can't change the Capability interface in a stable release.
                  Its part of the public spi.

                  If you want a new method, then you should add a mixin interface, e.g.

                  public interface Capability2 extends Capability { ... }

                  and then have AbstractCapability implement it by invoking the old method
                  calling code should do:

                  if (capability instanceof Capability2)
                   ((Capability2) capability).resolve(x, y, z);
                  else
                   capability.resolve(x, z);
                  



                  • 6. Re: Cannot resolve circular dependencies
                    thomas.diesler

                    yes, we reverted that.

                    The OSGiPackageCapability can give access to it's associated module