6 Replies Latest reply on Sep 16, 2009 10:03 AM by thomas.diesler

    Cannot resolve dependency against unstarted bundle

    thomas.diesler

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

      The VFSDeploymentClassLoaderPolicyModule creates the dependencies like this

       protected void createDependencies()
       {
       ControllerState classLoaderState = getClassLoaderState();
      
       List<Requirement> requirements = getRequirements();
       if (requirements != null)
       {
       requirementDependencies = new ArrayList<RequirementDependencyItem>();
       for (Requirement requirement : requirements)
       {
       RequirementDependencyItem item = new RequirementDependencyItem(this, requirement, classLoaderState);
       addIDependOn(item);
       requirementDependencies.add(item);
       }
       }
       }
      


      The RequirementDependencyItem always initialized the the dependentState with ControllerState.INSTALLED

       public RequirementDependencyItem(Module module, Requirement requirement, ControllerState state)
       {
       super(module != null ? module.getContextName() : null, null, state, ControllerState.INSTALLED);
      


      which ultimately leads to RequirementDependencyItem.resolve() not being able to find the dependent ControllerContext

       ControllerContext context = controller.getContext(iDependOn, getDependentState());
      


      So it seems that RequirementDependencyItems can only resolve againt INSTALLED contexts.


        • 1. Re: Cannot resolve dependency against unstarted bundle
          thomas.diesler

          If Bundle.RESOLVED maps to ControllerState.CLASSLOADER
          and Bundle.ACTIVE maps to ControllerState.INSTALLED

          we need to somehow resolve PackageRequirements against context's in state CLASSLOADER.

          • 2. Re: Cannot resolve dependency against unstarted bundle
            alesj

             

            "thomas.diesler@jboss.com" wrote:

            So it seems that RequirementDependencyItems can only resolve againt INSTALLED contexts.

            Yes.

            But what's the issue?
            Should it be resolved against deployments that are past CLASSLOADER?

            In my demos, to automagically pick up DESCRIBED deployments,
            I hacked around with this idea:
            - http://anonsvn.jboss.org/repos/jbossas/projects/demos/microcontainer/trunk/igloo/src/main/java/org/jboss/demos/bootstrap/igloo/deployers/BundleResolver.java
            New "Reset" state, after Installed.

            • 3. Re: Cannot resolve dependency against unstarted bundle
              alesj

               

              "alesj" wrote:

              But what's the issue?
              Should it be resolved against deployments that are past CLASSLOADER?

              "thomas.diesler@jboss.com" wrote:

              we need to somehow resolve PackageRequirements against context's in state CLASSLOADER.


              Yeah, I don't see why we need fully installed deployment to resolve against.
              I assumed there is some reason to it, hence hacked around it.


              • 4. Re: Cannot resolve dependency against unstarted bundle

                I think you're missing the point?
                What is actually required is like "on-demand" processing for pojos
                but done for deployments.

                i.e. the bundle/deployment should sit at status DESCRIBED or CLASSLOADER
                (if somebody manually resolved it) until somebody wants to import from it.
                When somebody does that, it should try to move the deployment to INSTALLED

                If you look at the AbstractDependencyItem.resolve() there is this code

                 if (context == null)
                 {
                 resolved = false;
                 ControllerContext unresolvedContext = controller.getContext(iDependOn, null);
                 if (unresolvedContext != null && ControllerMode.ON_DEMAND.equals(unresolvedContext.getMode()))
                 {
                 try
                 {
                 controller.enableOnDemand(unresolvedContext);
                 }
                 catch (Throwable ignored)
                 {
                 if (log.isTraceEnabled())
                 log.trace("Unexpected error", ignored);
                 }
                 }
                 }
                


                but RequirementDependencyItem overrides that method so there is no
                on-demand processing.

                But making deployments have a controller mode of "on-demand" probably isn't
                the correct solution? For normal usage they need to be "manual" so that deployments
                are fully under the control of the MainDeployer.

                But you could add some similar code to the RequirementDependencyItem, e.g.
                (completely untested/compiled etc.)
                 // Resolved against a context in the dependent state
                 Object iDependOn = module.getContextName();
                 ControllerContext context = controller.getContext(iDependOn, getDependentState());
                 if (context != null)
                 {
                 setIDependOn(context.getName());
                 addDependsOnMe(controller, context);
                 setResolved(true);
                 if (module.getClassLoadingSpace() == null)
                 log.warn(getModule() + " resolved " + getRequirement() + " to " + module + " which has import-all=true. Cannot check its consistency.");
                 return isResolved();
                 }
                + else
                + {
                + // The dependent module is not fully installed
                + // if its not currently being processed (required state == state) then try to fully install it
                + context = controller.getContext(iDependOn, null);
                + if (context != null && context.getRequiredState().equals(context.getState()))
                + {
                + try
                + {
                + controller.change(context, ControllerState.INSTALLED);
                + // It worked so we are now resolved
                + if (ControllerState.INSTALLED.equals(context.getState()))
                + {
                + <Same code as above when it was already in the correct state/>
                + }
                + }
                + catch (Throwable t)
                + {
                + log.trace("Error trying to fully install a dependent module: " + module, t);
                + }
                + }
                + }
                


                You almost certainly need to do something for circular dependencies in this code. :-)

                • 5. Re: Cannot resolve dependency against unstarted bundle
                  alesj

                   

                  "adrian@jboss.org" wrote:

                  But making deployments have a controller mode of "on-demand" probably isn't
                  the correct solution? For normal usage they need to be "manual" so that deployments
                  are fully under the control of the MainDeployer.

                  We will need some "on-demand" notion for (OSGi) deployments anyway,
                  if we wanna handle lazy activation of bundles on first class loading hit from this bundle.


                  • 6. Re: Cannot resolve dependency against unstarted bundle
                    thomas.diesler

                    There is also a consideration where the first possible match for a capability/requirement combination is not the one we want in the context of all available modules.

                    Details

                    https://jira.jboss.org/jira/browse/JBKERNEL-54

                    https://jira.jboss.org/jira/browse/JBKERNEL-55