Bundle, Extension, Service and Contribution

Component Model

Reference:

http://doc.nuxeo.com/display/NXDOC56/Component+model+overview

  • Bundle is basic unit with MANIFEST packed in a jar
  • One Bundle contains one or more XML components
  • One component can define service and implementation
  • One component can define many extension-points (declaration)
  • One component can define many extensions (extension contribution)

Bundle

Basic unit parts, a .jar, containing:

  • OSGI-cased MANIFEST
  • Java classes
  • XML components (so one bundle may incorporate many components)
  • Resources
  • Deployment descriptor

MANIFEST defines:

  • Bundle-SymbolicName: bundle ID
  • Require-Bundle: dependencies - what other bundles need to be there for this bundle to run, comma separated list
  • Nuxeo-Component: list XML components that are part of the bundle, put in dir OSGI-INF, comma separated list

Example manifest:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: NXCoreConvert
Bundle-SymbolicName: org.nuxeo.ecm.core.convert
Bundle-Localization: plugin
Require-Bundle: org.nuxeo.ecm.core.api,
 org.nuxeo.ecm.core.convert.api
Bundle-Vendor: Nuxeo
Export-package: org.nuxeo.ecm.core.convert.cache,
 org.nuxeo.ecm.core.convert.extension,
 org.nuxeo.ecm.core.convert.service
Bundle-Category: runtime
Nuxeo-Component: OSGI-INF/convert-service-framework.xml

Component

Component are defined by the XML, usually placed in OSGI-INF dir.

Each XML has unique ID (<component name="org.nuxeo.ecm.....">), and can

  • declare requirement on other components
  • declare Java component implementation
  • contain XML contribution
  • declare a Java contribution

Obtain and use component:

  • Direct, but not often used usage: Components usually derive from a base class provided by Nuxeo Runtime and available as a singleton, via a call "Framework.getRuntime().getComponent(componentName)"
  • Used via service interface:
    • XML components declare which Service Interface the component provides
    • Service implemented by
      • either the component itself, directly, or
      • the component delegate to another class
    • Then the Service can be obtained by "Framework.getService(ServiceInterface.class)"

Extension Points and Services

  • What can be done:
    • configure behaviour (= contribute XML configuration)
    • extend behaviour (= contribute Java code or scripting)
  • Development pattern:
    • Components provide services
    • Components expose Extension Points
  • Extension Point can be used (it is used all over the platform: runtime, core, service and UI):
    • to provide configuration
    • to provide additional code
  • Declare extension point (see example below)
    • It's inside a component
    • Component declares a new service "ConversionService" with an interface and also an implementation "ConversionServiceImpl"
    • Service exposes 2 extension points
      • "converter" to be used to contribute new converters implemented with Java code
      • "configuration" to contribute configuration
    • Extension points are points of extension by other components by XML fragment. The contributing XML's structure is defined by annotations in the descriptor class.
    • Runtime instances descriptors and delivers it into the service each time a new contribution of these extension points is detected.
  • Runtime model (package org.nuxeo.runtime.model)
    • interface Extension
      • holds extension data as a DOM element correspond to the "extension" element in XML descriptor
      • holds an array of contribution objects
      • holds the ComponentInstance that owns this extension
    • interface Component
      • life cycle management methods
        • activate / deactivate / applicationStarted
      • getApplicationStartedOrder
      • through sub-interface Extensible
        • registerExtension / unregisterExtension (Extension)
    • interface Adaptable
      • <T> T getAdapter(Class<T> adapter)
    • class DefaultComponent implements Component, Adaptable
      • empty implementation for a component with some default behaviors
      • Long lastModified - set every time something is changed
      • registerExtension(Extension) - how component gets its extension contributions
        • for each contribution held by the Extension instance:
          • call registerContribution with:
            • contrib - the contribution object
            • extension.getExtensionPoint() - the extension name
            • extension.getComponent() - the component instance owning the extension
          • which shall be override if sub-class ever want extension contribution
    • class ConverterDescriptor implements Serializable (discussed as exemplary extension descriptor class implementation)
      • @XObject("converter") - indicate the descriptor class binding an XML node
      • various annotated fields - from configuration
      • getConverterInstance() utility method to obtain the worker instance from the descriptor
        • responsible to obtain an instance of the worker instance from class name hold by the descriptor, or a chain converter from setting of subconverters, etc.
    • class ConversionServiceImpl extends DefaultComponent implements
      • ConversionService (an ECM Core service class here as an exemplary implementation):
      • overrides registerContribution, in which
        • checks which extension is given (code, configuration, etc.)
        • according to type of extension, cast contribution object (an Object) to the corresponding descriptor
        • an instance of the extension code can be obtained from the utility method of the annotated descriptor class

Extension point declaration example:

<?xml version="1.0"?>
<component name="org.nuxeo.ecm.core.convert.service.ConversionServiceImpl">
  <documentation>
   Service to handle conversions
  </documentation>
  <implementation class="org.nuxeo.ecm.core.convert.service.ConversionServiceImpl"/>*
  <service>
   <provide interface="org.nuxeo.ecm.core.convert.api.ConversionService"/>*
  </service>
  <extension-point name="converter">
    <documentation>
      This extension can be used to register new converters
    </documentation>
    <object class="org.nuxeo.ecm.core.convert.extension.ConverterDescriptor"/>
  </extension-point>
  <extension-point name="configuration">
    <documentation>
      This extension can be used to configure conversion service
    </documentation>
    <object class="org.nuxeo.ecm.core.convert.extension.GlobalConfigDescriptor"/>
  </extension-point>
</component>

Extension Point Contribution

Contribution to extension point is made by XML fragments in a component XML.

The component XML is usually placed in OSGI-INF directory and referenced in bundle MANIFEST "Nuxeo-Component" line.

Specify target component and extension point.

Provide expected XML content defined by descriptor class annotations.

Below is an example:

<?xml version="1.0"?>
<component name="org.nuxeo.ecm.platform.convert.plugins">
  <extension target="org.nuxeo.ecm.core.convert.service.ConversionServiceImpl" point="converter">
    <converter name="zip2html" class="org.nuxeo.ecm.platform.convert.plugins.Zip2HtmlConverter">
      <destinationMimeType>text/html</destinationMimeType>
      <sourceMimeType>application/zip</sourceMimeType>
    </converter>
   </extension>
</component>

Browse Extension Point

Go to Nuxeo Platform Explorer, explorer.nuxeo.org.