Author Archive: Mark Bartel

Remember your imports!

One of the most common configuration errors people make is to forget to import the necessary interfaces for a bundle:

<manifest xmlns="http://ns.adobe.com/gravity/manifest/1.0"> 
 
  <interface location="foo_interface.swf"> 
    <exports> 
      <export name="com.example.IFoo"/> 
    </exports> 
  </interface> 
 
  <bundle location="some_bundle.swf"> 
    <imports>
      <import name="com.example.IFoo"/>
    </imports>
  </bundle> 
  
  <bundle location="other_bundle.swf"> 
    <!-- forgot to import IFoo -->
  </bundle> 
  
</manifest>

Such errors may not be immediately apparent as some other bundle that happens to be loaded earlier may happen to import the same interfaces: so long as the interface SWF happens to be loaded before any bundles that require it are loaded, everything will work, since interface SWFs are loaded into the root ApplicationDomain. However, since bundles are loaded in parallel when possible, this can lead to race conditions where the failure is very intermittent since so many different factors come into play: operating system, browser and browser version, network topology, contents of the browser cache, and more. You can experiment with the effects of load ordering with this multiple ApplicationDomain demo.

If you have this issue, it will typically manifest as a failure to find the service that wasn’t imported. If you find yourself thinking, “I can see that the service is registered, why is my lookup failing?” then this is probably the problem.

If you optimize your bundles by excluding the service interfaces, it will show up as a VerifyError, which makes it a little easier to diagnose.

Note that the same issue can occur between interface SWFs if one interface SWF depends on another. Interface SWFs also need to declare imports if they depend on interfaces defined in other interface SWFs:

<manifest xmlns="http://ns.adobe.com/gravity/manifest/1.0"> 
 
  <interface location="foo_interface.swf"> 
    <exports> 
      <export name="com.example.IFoo"/> 
    </exports> 
  </interface> 
 
  <interface location="bar_interface.swf"> 
    <exports> 
      <export name="com.example.IBar"/> 
    </exports> 
    <imports>
      <!-- IBar has methods or properties that reference IFoo,
           or IBar extends IFoo, so we need to import IFoo -->
      <import name="com.example.IFoo"/>
    </imports>
  </interface> 
</manifest>

Quick pointer to the documentation

The not necessarily obvious path to the Client Component Framework documentation is to go here http://help.adobe.com/en_US/enterpriseplatform/10.0/AEPDeveloperGuide/index.html and then click on the ADEP Client Component Framework link at the bottom of the left-hand list.

Propagation of manifest properties

I recently received a question about manifest properties… I thought it would be useful to share the question and answer here.  The question:

I guess this is more of a philosophical question and probably a lack of personal OSGi knowledge but here goes.  Why is the ManifestParseContext the same from manifest to manifest, or at least the properties available the same? If my application loads a manifest at some point later, why is that manifest load subject to all the prior manifest properties?  It would seem like very <manifest></manifest> would be “isolated” from others but, that doesn’t appear to be the case.

Here is the explanation I gave:

OSGi does not have a concept of properties like Gravity. This is a Gravity feature.

The properties are actually isolated, just not in the manner that you’re thinking… if I have this in the initial manifest

    <manifest xmlns="http://ns.adobe.com/gravity/manifest/1.0">
      <bundle location="alice.swf"/>
      <property name="alpha" value="apple"/>
      <include location="other-manifest.gxml"/>
      <property name="delta" value="date"/>
      <bundle location="carol.swf"/>
    </manifest>

and other-manifest.gxml contains

    <manifest xmlns="http://ns.adobe.com/gravity/manifest/1.0">
      <property name="bravo" value="banana"/>
      <bundle location="bob.swf"/>
      <property name="bravo" value="blackberry"/>
      <property name="charlie" value="cranberry"/>
    </manifest>

then the alpha, bravo (with a value of “blackberry”), charlie, and delta properties are visible for the definition of the carol.swf bundle and for any manifests loaded from the carol.swf bundle. Only the alpha and bravo (with the value of “banana”) properties are visible to the bob.swf bundle, and only those properties will be propagated to any calls to installBundlesFrom* from bob.swf (the bob.swf bundle is isolated from later changes). If installBundlesFrom* is called from alice.swf, none of these properties will be defined for that manifest.

In other words, each bundle captures the properties that were valid at the point of definition of that bundle, and the captured values of those properties are propagated in subsequent calls to installBundlesFrom* from within each bundle. This avoids the need to define properties like debug in every single manifest while providing predictability and traceability. If the properties were simply global it’d be difficult to figure out how a property ended up getting set: it could have happened anywhere, and the ordering of independent loads would be significant.