6 Replies Latest reply on Jun 15, 2012 10:20 AM by thomas.diesler

    Conceptual flaw in wiring to non-osgi modules

    thomas.diesler

      There is likely a conceptual flaw in the way we handle Resources/BundleRevision for non-osgi modules. This thread is related to

       

      * AS7-4915  ClassCastException - AbstractResource cannot be cast to AbstractBundleRevision

      * AS7-4918  Registered module using OSGi capability not visible as a bundle

       

      Currently there are two places when we register a module with the resolver environment

       

      #1 AutoInstallIntegration.installInitialModuleCapability(OSGiCapability osgicap)

       

      // Attempt to load the module from the modules hierarchy
      Module module = null;
      try {
          ModuleLoader moduleLoader = Module.getBootModuleLoader();
          module = moduleLoader.loadModule(moduleId);
      } catch (ModuleLoadException ex) {
          throw MESSAGES.startFailedCannotResolveInitialCapability(ex, identifier);
      }
      if (module != null) {
          OSGiMetaData metadata = getModuleMetadata(module);
          XResourceBuilder builder = XResourceBuilderFactory.create();
          if (metadata != null) {
              builder.loadFrom(metadata);
          } else {
              builder.loadFrom(module);
          }
          XResource res = builder.getResource();
          res.addAttachment(Module.class, module);
          injectedEnvironment.getValue().installResources(res);
          return true;
      }
      

       

      #2 ModuleRegisterProcessor.ModuleRegisterService.start(StartContext context)

       

      LOGGER.tracef("Starting: %s in mode %s", controller.getName(), controller.getMode());
      LOGGER.infoRegisterModule(module);
      try {
          XResourceBuilder builder = XResourceBuilderFactory.create();
          if (metadata != null) {
              builder.loadFrom(metadata);
          } else {
              builder.loadFrom(module);
          }
          resource = builder.getResource();
          resource.addAttachment(Module.class, module);
          injectedEnvironment.getValue().installResources(resource);
      } catch (Throwable th) {
          throw MESSAGES.startFailedToRegisterModule(th, module);
      }
      

       

      The code is very similar and in both cases we create a Resource with associated Capabilities/Requirements. Note, this is a org.osgi.resource.Resource and not a org.osgi.framework.wiring.BundleRevision

       

      As a result the BundleManagerPlugin needs to filter the registered resources in all variants of getBundle

       

      Set<Bundle> getBundles() {
        Set<Bundle> result = new HashSet<Bundle>();
        XEnvironment env = injectedEnvironment.getValue();
        for (Resource aux : env.getResources(IDENTITY_TYPES)) {
            if (aux instanceof AbstractBundleRevision) {
                AbstractBundleRevision brev = (AbstractBundleRevision) aux;
                AbstractBundleState bundleState = brev.getBundleState();
                if (bundleState.getState() != Bundle.UNINSTALLED)
                    result.add(bundleState);
            }
        }
        return Collections.unmodifiableSet(result);
      }
      

       

      Registered modules have hence no Bundle API view.

       

      When a bundle gets resolved it may get wired to package capability provided by a registered module. There is no restriction on the resource type and a Wiring will get created for a given Resource. In various place the framework assumes that a resource that is associated with a given Capability/Requirement is a org.osgi.framework.wiring.BundleRevision rather than a plain org.osgi.resource.Resource which causes the CCE reported in AS7-4915

       

      java.lang.ClassCastException: org.jboss.osgi.resolver.spi.AbstractResource cannot be cast to org.jboss.osgi.framework.internal.AbstractBundleRevision
       at org.jboss.osgi.framework.internal.PackageAdminPlugin$ExportedPackageImpl.getImportingBundles(PackageAdminPlugin.java:536)
       at org.apache.felix.webconsole.internal.core.BundlesServlet.listImportExport(BundlesServlet.java:813)
      

       

      There are potentially several approaches to fix this

       

      #1 Drop wires to non-osgi modules from the wiring API. Module dependencies would still be created but not visible through public API (i.e. PackageAdmin and later the R5 Wiring API). Non-osgi modules don't show up as bundles in the framework.

       

      #2 Always create BundleRevisions with associated BundleCapabilities/BundleRequirements. Non-osgi modules would be managed by the framework as fabricated bundles. Some Bundle API would not be supported. The framework management view would potentially show a large set of bundles which are in fact not bundles.

       

      #3 Lazy transformation from Resource to BundleRevision when a Resource is choosen as a wire target. As above, non-osgi modules would be managed by the framework as fabricated bundles. Some Bundle API would not be supported. Framework management view would only show bundles which are either real bundles or non-osgi bundles that take part in the wiring.

       

      Thoughts?

        • 1. Re: Conceptual flaw in wiring to non-osgi modules
          thomas.diesler

          Here my 2 cents:

           

          The framework and associated resolver APIs provide the low-level functionality for higher level APIs to plug in to. The framework deals with BundleRevision and associated BundleCapabilities/BundleRequirements. It is the responsibility of the client (i.e. AS7) to provide adequate implementations for these entities. So AS7 would decide whether a non-osgi module is visible as a bundle and can part take in bundle wiring.

           

          So  ModuleRegisterProcessor and friends would create a BundleRevision instead of a Resource. System modules (i.e. the ones from the modules hierarchy) need to be registered explicitly as capabilities or requested through the repository API.

          • 2. Re: Conceptual flaw in wiring to non-osgi modules
            mreasy

            Would vote for option #2, since from a monitoring perspective, it may be unknown and not controllable how theresources ended up in the OSGi-container - whether they were added as bundle or as capability. This should be presented in a similar manner.

            • 3. Re: Conceptual flaw in wiring to non-osgi modules
              bosschaert

              Regarding #1, I think this would really cause confusion as the wiring information provided to you through OSGi's reflective would be incomplete. There are potentially wirings that are not reported which I think would definitely not be what you want and could cause a world of hurt when dignosing classloading issues (imagine a classcast exception where you can only see 1 provider of a certain class where in reality there are 2).

               

              Re #2, I think this would be consistent and eliminate 'special casing'. The modules show up as bundles, operations that are not supported could thrown an exception. You mention that a large set of bundles could show up, I wonder how large and what exactly?

              I would not automatically cause all available modules to appear as bundles. I would provide a mechanism to expliclty register modules as bundles, we currently already do this in the capabilities that are part of the configuration.

               

              Re #3, I also think this may cause potential confusion as there are APIs (such as PackageAdmin) the query the framework for potential packages that are available in the framework. You will end up with a situation where less packages are reported than potentially available (as there are modules that could be magically activated to provide the package). It can see that this causes issues for provisioning agents and other management agents.

               

              So I would go for #2 with explicit registration of modules that are visibile to the framework. That should not cause a huge amount of module-bundles being reported unless the user explicitly configured there.

              • 4. Re: Conceptual flaw in wiring to non-osgi modules
                thomas.diesler

                This should be fixed in jbosgi-framework-2.0.0.CR1

                 

                It was a major effort to introduce a proper abstraction for adapted modules. We now have an XBundle and XBundleRevision abstraction that is expected to be implemented by internal bundles as well as modules that are adapted as bundles. Internally the framework now works with these interfaces except in areas where it is guaranteed that we work with internal types. For example a HostBundleState may savely cast its revision to HostBundleRevision. For bundles that come through external API or from the XEnvironment, which is the maintainer of all revisions, an XBundle must be assumed.

                 

                Real OSGi Bundles that have dependencies on adapted Modules have proper wiring information. Most APIs are expected to work with adapted Modules except what is documented in AbstractBundleAdapter and AbstractBundleRevisionAdapter.

                 

                I'm now going to bring this into AS7. As a result it should be possible that every AS7 non-OSGi deployments that gets a ClassLoader (i.e. is a Module) can get registered with the XEnvironment and such is visible through the Bundle API and a valid candidate for OSGi wiring. In reverse, every OSGi Bundle deployment could be resolved (on a trial and error basis) during DeploymentUnit processing. In case the Bundle could get resolved it's associated Module would be available for further DeploymentUnit processing and we would no longer need to distinguish between OSGi and non-OSGi deployments after the MODULE Phase. As a result it should be possible to deploy JBossWeb, EJB3, CDI, etc deployments as OSGi Bundles. Let's see how this works out ;-)

                • 5. Re: Conceptual flaw in wiring to non-osgi modules
                  mreasy

                  Thanks Thomas, do you think it's worth trying to update JBoss 7.1.1 or 7.1.2 with this CR?

                  I think every non-OSGi-deployment being available as source through the OSGi-environment will also help implementing the Repository Service of OSGi Enterprise Release 5 which "can be used with any kind of resource (it doesn't have to be an OSGi bundle)" (cited from this blog).

                  • 6. Re: Conceptual flaw in wiring to non-osgi modules
                    thomas.diesler

                    Yes, its definitely worth giving it a try. Currently AS7 has a very slow community project release cycle. Its therefore import that folks like you try out the latest in master before it goes into a release. You can monitor PR #2509 or AS7-4918. If you cannot wait for this to show up in master, you can already try out https://github.com/tdiesler/jboss-as/tree/as4918