Nuxeo Runtime
Documentation

Last Modi cation Project Code Document ID Copyright

0 9 /2 2 / 2 0 0 6 NXECM NXRUNTIME-GUIDE Copyright © 2006 Nuxeo. All Rights Reserved.


Versionning
Version 1.0 1.0.1 1.0.2 Date 2 2 /0 9 / 2 0 0 6 2 6 /0 9 / 2 0 0 6 2 6 /0 9 / 2 0 0 6 Participant(s) · Bogdan Stefanescu · Stefane Fermigier · Bogdan Stefanescu Comments Created Light editting Added Use Cases and changed pictures


Sommaire
1 Overview...........................................................................................................................................4 1.1 Main Goals..................................................................................................................................4 1.2 Main Features..............................................................................................................................5 2 What is OSGi?....................................................................................................................................6 3 OSGi Support.....................................................................................................................................7 3.1 Supported Features.....................................................................................................................7 3.2 Unsupported Features..................................................................................................................8 3.3 Planned Features.........................................................................................................................8 4 Component Model..............................................................................................................................9 4.1 4.2 4.3 4.4 4.5 4.6 4.7 What are components?................................................................................................................9 Main Features..............................................................................................................................9 Planned Features.......................................................................................................................10 Adaptable Components..............................................................................................................10 Flexible Model............................................................................................................................10 Component Life Cycle.................................................................................................................11 Component Extensibility............................................................................................................12 4.7.1 Use Cases...............................................................................................................................................................................................14

5 Supported Host Platforms.................................................................................................................15 5.1 JBoss Integration.......................................................................................................................15 5.1.1 Installation............................................................................................................................................................................................16 5.2 Eclipse Integration.....................................................................................................................16 5.2.1 Installation............................................................................................................................................................................................16 6 User Guide.......................................................................................................................................17 6.1 Creating components.................................................................................................................17 6.1.1 Runtime context...............................................................................................................................................................................17 6.1.2 Creating components from XML descriptor les.......................................................................................................18 6.1.3 Automatic deployment of components..........................................................................................................................18 6.1.4 Creating components programmatically........................................................................................................................19 6.2 Using components.....................................................................................................................19 6.2.1 Responding to life cycle events..............................................................................................................................................19 6.2.2 Looking Up Components...........................................................................................................................................................20 6.2.3 Working with extension points...............................................................................................................................................21 6.3 XML Component Descriptors.......................................................................................................24 References.........................................................................................................................................27


Project title I Document title

1 Overview
Nuxeo Runtime is the foundation of the Nuxeo 5 infrastructure. It handles deployment and extensibility of components to target platforms. This component allows the whole Nuxeo 5 infrastructure to be easily ported between Java platforms (Java EE, OSGi, IKVM, etc.) and features an easy plug-in mechanism that any component can use to declare extension points that can be used by other components to extend the former one. Nuxeo Runtime uses the OSGi component model and a set of adapters to deploy POJO components to Java host platforms, such as Eclipse/Equinox, JBoss or JOnAS. When deployed, Nuxeo Runtime components become actual host platform components. For example on JBoss the component is seen as a MBean while when deployed on Geronimo it is seen as a GBean and on Eclipse it is seen as a native Eclipse plug-in. In short, Nuxeo Runtime offers a new and seamless way to make your Java EE applications and components extensible (as Eclipse developers are already used to). Nuxeo Runtime is not specific to Nuxeo 5, it is a generic deployment and extension system that can be used in any Java or Java EE application. Forget speci c build of your applications for a dedicated project or customer and enjoy "Code once, deploy anywhere" for real!

1.1 Main Goals
One of the main requirements of the "Nuxeo Core" component is to be deployable on both the JBoss and Eclipse platforms. To ease development and allow as much as code reuse, this requirement raised the need of a common component and packaging model that may be deployed and used on both of these platforms without any code change or repackaging. To fulfill these needs, Nuxeo Runtime was developed as the foundation layer for all Nuxeo 5 components. Nuxeo Runtime is not a standalone framework. It is, basically, a component model running on top of an existing platform and providing a common, platform-independent, model to power the applicative components of an application. It is our component architecture allowing flexible and true componentization of applications. Besides its component model, Nuxeo Runtime also defines a common model for packaging. The adopted model is the OSGi bundle model. Actually, OSGi bundles are regular JARs containing an OSGi manifest file. OSGi technology is more and more popular and is currently used by Eclipse, Geronimo and Jonas as their runtime framework. This way, applications based on Nuxeo Runtime can run on different platforms without modifications by using an single component and packaging model - without having to care about platform specificity.

Document type I All Rights Reserved. I Page 4/27


Project title I Document title

1.2 Main Features
The main features provided by Nuxeo Runtime are:
· · ·

OSGi native support Extensible component model through extension points Adapters to support host platforms (JBoss and Eclipse support is built-in by default)

Document type I All Rights Reserved. I Page 5/27


Project title I Document title

2 What is OSGi?
OSGi (Open Services Gateway initiative) is an open standards organization founded by Sun Microsystems, IBM, Ericsson and others in March 1999. OSGi defines a modular and complete Java-based service framework. The deployment units used by this framework are called bundles, so we will refer them as OSGi bundles. OSGi bundles are normal Java libraries (JAR files) containing a special manifest file (META-INF/MANIFEST.MF) describing all aspects related to the bundle like: the bundle name, description, bundle dependencies, exported packages, the bundle classpath, the bundle activator and many other OSG-defined features. Here is a typical OSGi manifest file:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-Name: NxRuntimeEclipseDemo Plug-in Bundle-SymbolicName: org.nuxeo.runtime.demo.eclipse.Demo; singleton:=true Bundle-Version: 1.0.0 Bundle-Activator: org.nuxeo.runtime.demo.eclipse.demo.Activator Bundle-Vendor: Nuxeo Bundle-Localization: plugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.nuxeo.runtime.demo.HelloWorld,

org.nuxeo.runtime

The bundle activator is a Java object that is called when the bundle is started and stopped by the framework. This is the only way available to the application to access the framework functionalities. Besides bundles and bundle management, OSGi provide a service registry and an API to register the services provided by a bundle and to lookup these services. Also, OSGi defines a Declarative Services specification that significantly simplifies the service-oriented programming model. Through this model services can be defined in XML files inside the bundle and automatically deployed by the framework. For a complete definition of OSGi, see Wikipedia. One of the main goal of Nuxeo Runtime is to natively support OSGi frameworks and to use the OSGi bundle model for packaging and deployment. A second goal is to align the Nuxeo Runtime component model with the OSGi Declarative Specifications.

Document type I All Rights Reserved. I Page 6/27


Project title I Document title

3 OSGi Support
Nuxeo Runtime provides built-in integration over OSGi-compliant frameworks. This means Nuxeo Runtime-based components can run "as is" on any OSGi enabled platform. On other platforms like JBoss, an adapter is required. Nuxeo Runtime eases the creation of such adapters by providing an abstract OSGi adapter that can be customized for any platform. Note: It doesn't mean you can transform any platform into a fully OSGi-compliant platform using Nuxeo Runtime adapters. This is mainly due to the fact that the adapter is using in the background the host platform's class-loading and deployment model that is incompatible with OSGi specifications. Adapters only mimic an OSGi environment, using native host platform features, for applications running on top of Nuxeo Runtime. Many OSGi features are not yet provided by the adapter ­ but we hope to add more and more features. If you are interested in helping on this, do not hesitate :-). Currently, one of the most important feature that is missing is OSGi service support, but we are working on this and hope to provide it soon. When running on OSGi-enabled platforms, no adapter is used and thus all OSGi features are available as given by the host platform. Components are running natively on the OSGi platform without any alteration. Currently we provide two built-in adapters:
· ·

JBoss OSGi adapter ­ used to deploy OSGi bundles on JBoss AS 4.x Test OSGi adapter ­ used for JUnit testing and can be used on any simple Java application that is not using a complex class loading or deployment mechanism.

3.1 Supported Features
Currently, Nuxeo Runtime adapters can provide the following OSGi features:
· ·

OSGi Bundle deployment The manifest is loaded, the class path processed and the bundle activator instantiated BundleActivator support Activators are notified each time a bundle is started and stopped Fake Bundle and BundleContext implementations that adapts OSGi operations to native operations of the host platform Thus, Bundle Activators can use the common operations defined by the OSGi API. Bundle lifecycle and framework events support Bundle dependencies (as specified in the manifest)

· · ·

· · ·

Document type I All Rights Reserved. I Page 7/27


Project title I Document title

3.2 Unsupported Features
The following OSGi features are not supported (yet):
· · ·

The OSGi service layer OSGi Security layer OSGi class-loading specifications (the class-loading mechanism of the host platform is used) Some methods of interfaces Bundle and BundleContext (unimplemented Methods will thrown an UnsupportedOperationException exception)

·

3.3 Planned Features
· ·

Supporting OSGi Service layer Implementing OSGi Declarative Services based on the runtime component model

Document type I All Rights Reserved. I Page 8/27


Project title I Document title

4 Component Model
The component model provides a flexible way to define, register and locate components. It was designed in order to reuse the same component model on very different platforms like JBoss and Eclipse. A full support of OSGi declarative service specifications is planned in the mid-term future. Moreover, Nuxeo components can describe any kind of components, not only services.

4.1 What are components?
A definition from Wikipedia: A so w a r e component is a system element o ering a predened service and able to communicate with other components. Components as defined by the Nuxeo model are logical units that may depend on and/or extend one another. The Nuxeo Runtime is responsible to provide a common API to register, locate or extend components. Components are commonly registered using XML descriptor files. Components can either be declared as subunits of an OSGi bundle or as independent components - as standalone XML files or programmatically registered components. Components are commonly declared as part of an OSGi bundle through XML descriptors. To declare a component you need to create an XML description file, put it somewhere in the bundle and specify the "Nuxeo-Component" header in the bundle manifest to load components at bundle activation.
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: HelloWorldExtension Plug-in Bundle-SymbolicName: org.nuxeo.runtime.demo.HelloWorldExtension Bundle-Version: 1.0.0 Bundle-Vendor: Nuxeo Bundle-Localization: plugin Require-Bundle: org.nuxeo.runtime.demo.HelloWorld Nuxeo-Component: OSGI-INF/helloworld-extension.xml

4.2 Main Features
·

Declarative components through XML descriptors XML component descriptors are tightly integrated with OSGi ­ you can specify which components should be deployed at bundle installation phase by using a custom manifest header "Nuxeo-Component". Dependency between components Components are installed only when all their prerequisites are met. If prerequisites are not met the components will be put in a pending state until their dependencies

·

Document type I All Rights Reserved. I Page 9/27


Project title I Document title

are completely resolved. In the same manner when uninstalling a component all the components depending on it will be moved to the pending state.
·

Extensibility through extension points Each component can let other components extend itself by defining a set of extension points. Other components (or the component itself) may then plug extensions into one of the declared extension points. This flexible extension mechanism draw inspiration from the Eclipse extension points. Life Cycle Events Component life cycle events are fired by the runtime to anyone interested in. See Adaptable Components for a common use case. OSGi integration The component model is about to be fully integrated with OSGi and will be soon compliant with the OSGi declarative service model. Platform Independence The component model can be used on any platform. It provides a single API to register and localize components ­ the Nuxeo Runtime native API may be used (and in future the OSGi service API will be available too).

·

·

·

4.3 Planned Features
· ·

Complete integration with OSGi declarative services specifications Component lookup through JNDI

4.4 Adaptable Components
The runtime implementation may adapt registered components to native components of the host platform. This can be done using the component life cycle notifications. The JBoss runtime implementation is already doing this to adapt runtime components into JBoss MBean services. This way components may be seamlessly integrated into the host platform, thus leveraging the host platform functionalities (for example, MBean service management on JBoss)

4.5 Flexible Model
You should not be afraid by the "component model" denomination. The runtime component model is not limiting in any way your objects nor imposing extra rules in the development. You don't need to modify your existing objects to derive or implement some runtime classes in order to plug them into the component registry. Objects implementing a component may be of any kind.

Document type I All Rights Reserved. I Page 10/27


Project title I Document title

The only limitation is that component objects must have a public constructor without arguments (the default constructor) so that they can be instantiated via newInstance method on Class. Anyway, if you want to benefit from extension points mechanism or to respond to component life cycle events like activation or deactivation, then you should either implement the Component interface, or define some methods with a given signature in your object so that they will be called by using Java reflection. See User Guide for more details on this. In conclusion the component model is not limiting your objects in any way, it only gives you the capability to register your components, extend and locate them in the same way on any platform supported by Nuxeo Runtime.

4.6 Component Life Cycle
A component has 3 main life cycle states:
1.

Registered The component registration information was created and inserted into the registry. The component dependencies are not yet processed or resolved, so the component cannot be activated and would block other registrations depending on this component. Resolved All dependencies of this component are satisfied. The component can be safely activated. Other unresolved components waiting for a resolved component are notified and if they have no more dependencies they will be resolved too.

2.

3.

Activated Component activation may occur immediately a component is resolved, or programmatically at the user request, or lazily the first time the component is referred. The only requirement for a component to be able to activate is to be resolved. Currently only the immediate activation mode is supported. When an activated component is deactivated it is put back in the resolved state. If it is unregistered it will be put in the resolved state then an unresolved event is fired and the component regresses to the registered sate and then it is removed from the registry. When a component is respectively activated or deactivated the runtime will invoke the activate, respectively the deactivate method of the component, if any. Implementing life cycle methods or not is the programmer's choice. These methods can be used to initialize and destroy the component in the given context. Components are not forced to implement any one of these methods.

Document type I All Rights Reserved. I Page 11/27


Project title I Document title

The activation of a component signifies the component is available to be used by other components so that the component should be correctly initialized when it enters this state. Here is the complete life cycle of a component:

4.7 Component Extensibility
One of the most important feature of the component model is the extension mechanism that enable components to extend one another. How does it work? Imagine you have a component A that manages an action menu for the application. It wants to let other components contribute actions in an easy and flexible way ­ for example by using XML files to describe these actions. To be able to do this, component A should declare an extension point, let's say "actions". This way other components willing to contribute some actions to the action menu managed by the component A can contribute these actions to the extension point "actions" exposed by the component A. Obviously one component may declare any number of extension points and any number of extensions contributed to other components. Components may declare extension points and extension contributions using a simple XML syntax like the following:
<?xml version="1.0"?> <component name="org.nuxeo.ecm.core.schema.TypeService">

Document type I All Rights Reserved. I Page 12/27


Project title I Document title

<implementation class="org.nuxeo.ecm.core.schema.TypeService"/> <extension-point name="doctype"> <object class="org.nuxeo.ecm.core.schema.DocumentTypeDescriptor"/> </extension-point> <extension-point name="schema"> <object class="org.nuxeo.ecm.core.schema.SchemaBindingDescriptor"/> </extension-point> <extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype"> <doctype name="File" extends="Document"> <schema name="common"/> <schema name="file"/> </doctype> </extension </component>

You can see here a component declaring two extension points and contributing an extension to its own "doctype" extension point. The content of an extension element is specific to the target extension point. The extension element content is known only by the extension point. How are handled extensions not conforming to the extension point schema is unpredictable ­ generally they will be ignored and some errors will be logged. There is nomechanism of validating XML extensions like in Eclipse. But Nuxeo Runtime provides an easy way to map XML extensions to real Java objects through an XML mapping mechanism called XMap. You can see that each extension point in the example above is specifying an object tag. This means the content of the XML extension should be mapped through XMap to an object instance of this type. If no object tag is specified extensions are returned as DOM elements and thus the component should perform itself the DOM parsing of extension contributions. For details on the XML mapping see the XMap documentation and/or the JavaDoc.

Document type I All Rights Reserved. I Page 13/27


Project title I Document title

4.7.1 Use Cases
Here is the list of some use cases of the extension mechanism identified in the context of Nuxeo ECM Platform:


to define actions and menus to define content schemas (by importing XSD files) to define views (view ids mapped to jsf/xhtml pages) to define content objects (associate a Content Schema with a class that will provide required methods for the content object) to define permissions (usable in security annotations) to define PageFlows for SEAM that, optionally, can extend existing ones to define business processes (in jBPM) to define content transformations (doc -> pdf, doc -> html, odf -> pdf, odf -> html, etc.) to define rules for the rule engine (that can be binded to some objects to run a rule only in a specific folder) scriptable extensions that define scripts binded to interpreters like Groovy, Jython, Jruby etc to define JMS/Event queues to define event types to define security policies to define Access Control Policies to define NXCore storage backends (SQLStorage, LDAPStorage) to define query engines to define indexing engine









Document type I All Rights Reserved. I Page 14/27


Project title I Document title

5 Supported Host Platforms
5.1 JBoss Integration
Nuxeo Runtime provides a SAR package containing the Runtime and the JBoss OSGi adapter. This package is an OSGi bundle that acts as the OSGi system bundle. Any package (directory, .sar, .jar, .ear, .war or any other JBoss-supported archive) will be treated as an OSGi bundle if it contains a valid OSGi manifest. In order for these bundles to be deployed you need to have NXRuntime.sar already deployed in JBoss. Besides the OSGi adapter and the auto registration of components through bundle manifest the JBoss adapter adds the capability to deploy runtime components as XML files located outside OSGi bundles through the JBoss deployment mechanism. This feature can be useful to register components that provide extensions to other components that can be described by plain XML without any code dependency. Example of a plain XML component that contributes new document types:
<?xml version="1.0"?> <component name="org.nuxeo.ecm.core.CoreExtensions"> <extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype"> <doctype name="File" extends="Document"> <schema name="common"/> <schema name="file"/> </doctype> <doctype name="Folder" extends="Document"> <schema name="common"/> <facet name="Folderish"/> </doctype> <doctype name="Workspace" extends="Document"> <schema name="common"/> <facet name="Folderish"/> </doctype> <doctype name="Domain" extends="Document"> <schema name="common"/> <facet name="Folderish"/> </doctype> </extension> </component>

The NXRuntime.sar offers 2 JMX services: · The adapter service (nx:service=adapter)
· ·

deploys OSGi bundles and declared components provides information about deployed bundles and components through the JBoss JMX Console

Document type I All Rights Reserved. I Page 15/27


Project title I Document title

·

The XML component deployer (nx:name=bundleDeployer,type=deployer) that can deploy XML descriptors as OSGi components

5.1.1 Installation
Deploy the NXRuntime.sar in JBoss then deploy your OSGi bundles as common JBoss packages. That's all, your bundles are deployed and activated.

5.2 Eclipse Integration
For Eclipse, a NXRuntime.jar bundle is provided. Since Eclipse is OSGi-compliant, Nuxeo Runtime will not install any adapter (so it is not intervening on the bundle deployment). When running on OSGi platforms the main role of the runtime is to register components declared inside OSGi bundles (as seen previously through their manifest). Because Eclipse is not starting automatically OSGi bundles (it starts them only on demand or on class loading), you need to update Eclipse's con g.ini and configure it to start Nuxeo Runtime (i.e. org.nuxeo.runtime) when Eclipse starts:
osgi.bundles=org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start,org.nuxeo.runtime@start

5.2.1 Installation
Update the configuration.ini file as described above then copy NXRuntime.jar inside Eclipse plugin directory. Start Eclipse. You're done!

Document type I All Rights Reserved. I Page 16/27


Project title I Document title

6 User Guide
6.1 Creating components
Components may be created either from XML descriptor files, either programatically. In order to register components you always need a runtime context.

6.1.1 Runtime context
A runtime context is the context where a component is registered. Contexts should be always associated to the bundle containing the component classes. Through the context a component can access the runtime service and can load classes and retrieve resources from its bundle and other visible bundles. Runtime Context objects depend on the current implementation of the runtime service. Nuxeo Runtime is providing three implementation of the RuntimeContext interface:
1.

org.nuxeo.runtime.model.impl.DefaultRuntimeContext

This is a simple implementation of a context designed to be used outside an OSGi environment. This context is using the current thread context class loader. It should only be used in simple Java applications like JUnit tests that are not supporting OSGi bundles.
2.

org.nuxeo.runtime.osgi.OSGiRuntimeContext

This context can be used on any platform supporting OSGi bundles. This context is using the bundle ClassLoader to load classes and find resources. This is the right context to use when using Nuxeo Runtime and it is working on any platform as long as it is an OSGi platform or you have an OSGi adapter for it.
3.

org.nuxeo.runtime.jboss.JBossRuntimeContext

This is a JBoss specific context. It is used by the JBoss runtime implementation to load components deployed as standalone XML files. This context is wrapping the DeploymentInfo JBoss object. Once you have a runtime context object you can start registering components.

Document type I All Rights Reserved. I Page 17/27


Project title I Document title

6.1.2 Creating components from XML descriptor les
To create a component using its XML description follow these steps:
1.

Write the XML description of the component Example of a simple XML descriptor:

<?xml version="1.0"?> <component name="org.nuxeo.runtime.EventService"> <implementation class="org.nuxeo.runtime.services.event.EventService"/> <extension-point name="listeners"> <object class="org.nuxeo.runtime.services.event.ListenerDescriptor"/> </extension-point> </component>

2. 3.

Load the XML file and register the component In order to register a component we always need a runtime context.

// retrieve the current bundle Bundle bundle = ... // create a context given the current bundle object RuntimeContext context = new OSGiRuntimeContext(bundle); // load the component XML file given its location relative to the bundle root context.deploy("OSGI-INF/MyComponent.xml");

The current bundle object is usually retrieved from a BundleActivator in the start(BundleContext context) method. You can also lookup other bundles by their symbolic names given a Bundle object. The context has several method of deploying (e.g. installing) components. For example the method used previously is identical to
// load the component XML file given its location relative to the bundle root URL url = context.getLocalResource("OSGI-INF/MyComponent.xml"); if (url != null) { context.deploy(url); }

6.1.3 Automatic deployment of components
Another, and the easiest way to deploy components is to let the bundle deploy them when started. This is the recommended method of deploying components. This can be done by specifying the local paths of the XML description files inside the bundle manifest by using the Nuxeo-Component header as in the following example:

Document type I All Rights Reserved. I Page 18/27


Project title I Document title

Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: HelloWorldExtension Plug-in Bundle-SymbolicName: org.nuxeo.runtime.demo.HelloWorldExtension Bundle-Version: 1.0.0 Bundle-Vendor: Nuxeo Bundle-Localization: plugin Require-Bundle: org.nuxeo.runtime.demo.HelloWorld Nuxeo-Component: OSGI-INF/MyComponent.xml, OSGI-INF/MySecondComponent.xml

This way as soon as the bundle is started the component will be automatically deployed. XML component are contained as resource files in that bundle and its path should be specified as relative to the bundle root

6.1.4 Creating components programmatically.
This method of creating components is not recommended since it's internal to Nuxeo Runtime and it depends on the implementation. Here is an example on how you can use the API to manually register a component. We assume you are running in an OSGi environment and you have a reference to the bundle object containing the component you want to register.
// retrieve the current bundle Bundle bundle = ... RegistrationInfoImpl ri = new RegistrationInfoImpl(); // create a context associated to the current bundle ri.context = new OSGiRuntimeContext(bundle); ri.name = new ComponentName("my.component"); // set the class name of the component to register ri.implementation= "org.nuxeo.runtime.example.MyComponent"; // register the component NXRuntime.getRuntime().getComponentManager().register(ri);

6.2 Using components
6.2.1 Responding to life cycle events
When a component is deployed Nuxeo Runtime will check its dependencies and if all of these ones are resolved the component is resolved and activated. (in future lazy activation or activation on demand will be supported too). If component dependencies are not satisfied the the component will be put in a pending queue until all of its dependencies will be resolved.

Document type I All Rights Reserved. I Page 19/27


Project title I Document title

When activating a component the runtime will check if the component defines the activate life cycle method and if true it will call it to get a chance to the component to initialize itself. The same thing is done when deactivating the component - the runtime will check if the component defines the deactivate life cycle method and if true it will call it to get a chance for the component to dispose itself. There are two way to define methods life cycle:
1.

By implementing the org.nuxeo.runtime.model.Component interface In this case a cast to Component interface is performed and the life cycle methods are called.

public interface Component extends Extensible { public void activate(RuntimeContext context) throws Exception; public void deactivate(RuntimeContext context) throws Exception;

}

2.

By simply declaring a public or protected methods on the component object using the right signature. In this case the Java reflection mechanism is used to call the methods.

public class MyComponent { ... public void activate(RuntimeContext context) throws Exception { ... } public void deactivate(RuntimeContext context) throws Exception { ... } ... }

6.2.2 Looking Up Components
After a component is activated it can be retrieved using the Nuxeo Runtime API. There are several methods to look-up a component: Looking up the component by its name
HelloComponent hc = (HelloComponent)NXRuntime.getRuntime() .getComponent("org.nuxeo.runtime.demo.HelloComponent");

Looking up the ComponentInstance object corresponding to this component. This object is a proxy to the component object.
ComponentInstance ci = NXRuntime.getRuntime()

Document type I All Rights Reserved. I Page 20/27


Project title I Document title

.getComponentInstance("org.nuxeo.runtime.demo.HelloComponent"); if (ci != null) { HelloComponent hc = (HelloComponent)ci.getInstance(); }

6.2.3 Working with extension points
Now let's take a look at how a component may define an extension point and how other components may use this extension point to contribute extensions.

6.2.3.1 De ning an extension point
A component may define any number of extension points. Extension points are identified inside a component by a unique name. We will describe here how to define extensions using the XML descriptor file. Extension points can also by created by hand using the internal API of Nuxeo Runtime but this is no recommended and it is not documented here. Extension points are specified in the XML component descriptor using the extension-point tag. This tag has a required attribute name and one or more optional object sub-tags.
1.

The name attribute This should be unique relative to the parent component and is used to identify the extension points inside a component.

2.

The object sub-tag can be used to define what kind of objects are contributed by XML extensions. These objects will be created from the extension XML fragment by using the XMap engine that maps XML to Java objects through through Java annotations. If no object sub-tag is specified the extension will be contributed as a DOM element. The object tag has a required attribute class that specify the class name of the objects to contribute. The object class will be loaded using the context of the bundle that defined the extension point.

Example of a component declaring two extension points:
1. 2.

listeners asyncListeners

<?xml version="1.0"?> <component name="org.nuxeo.runtime.EventService"> <implementation class="org.nuxeo.runtime.services.event.EventService"/> <extension-point name="listeners"> <object class="org.nuxeo.runtime.services.event.ListenerDescriptor"/> </extension-point>

Document type I All Rights Reserved. I Page 21/27


Project title I Document title

<extension-point name="asyncListeners"> <object class="org.nuxeo.runtime.services.event.AsyncListenerDescriptor"/> </extension-point> </component>

6.2.3.2 Contributing an extension
Once a component declaring some extension points was activated other components may contribute extensions to that extension point. To declare an extension the tag extension is used. This tag must contains a target and a point attribute.
· target

The target attribute specifies the name of the component providing the extension point
· point

The point attribute is the extension point name. The extension element may contain arbitrary XML. The actual XML content is recognized only by the extension point to where the extension is contributed. This means you should know the correct format for the extension XML. For this reason it is important for components to document their extension points. If the extension point is using XMap to map XML to Java objects then you can use annotations existing on the contribution object class to know the XML format. These annotations are very easy to understand and can be used as well as a documentation for the XML extension format. If you are familiar with Eclipse extension points you may wonder why Nuxeo Runtime is not using an XSD schema to define the content of an XML extensions. The reason is simple: because inside our ECM project we need to be able to define any type of XML content - even configuration files from external tools we use like for example a Jackrabbit repository configuration. Defining and maintaining XSD schemas for this kind of extensions would be painful. Anyway, using XMap to map extensions to real Java objects makes it easy to use extensions. Here is an example on how a component is declaring some contributions to the previously defined extension points:
<?xml version="1.0"?> <component name="my.component"> <implementation class="MyComponent"/> <extension target="org.nuxeo.runtime.EventService" point="listeners">
<listener class="org.nuxeo.runtime.jboss.RepositoryAdapter">

<topic>repository</topic>

Document type I All Rights Reserved. I Page 22/27


Project title I Document title

</listener> <listener class="org.nuxeo.runtime.jboss.ServiceAdapter">

<topic>service</topic>
</listener>

</extension> </component>

You can see how the component is declaring an extension to the listeners extension point defined by the component org.nuxeo.runtime.EventService The result of this declaration is that the EventService will register two listeners, one listening on events from the topic "repository", the other on events from the topic "service ".

6.2.3.3 Registering contributed extension
Extensions are contributed to the target extension point immediately after the component declaring these extensions is activated. If the target component (the component declaring the extension point) was not yet activated the contributed extensions are put in a pending queue and they will be contributed as soon as the target component is activated. A component willing to declare extension points and accept contributed extensions should declare two protected or public methods: registerExtension and unregisterExtension. This can be done either by implementing the Component interface, or by declaring these methods with their correct signatures on the component object (as we have seen before for the life cycle methods). These two methods should have the following signature:
public interface Extensible { public void registerExtension(Extension extension) throws Exception; public void unregisterExtension(Extension extension) throws Exception;

}

Note that the Extensible interface is extended by the Component interface. When an extension is contributed the registerExtension method is called with an argument that points to the actual contributed extension as an Extension object. Components should use this method to do something with the extension (usually to register it somewhere). When the component contributing the extension is deactivated the Runtime will call the unregisterExtension method using the same Extension object as a parameter. This gives a chance to the extended component to unregister extensions when they become inactive. Here is an example of how extensions are registered and unregistered:
Document type I All Rights Reserved. I Page 23/27


Project title I Document title

public class HelloComponent implements Component { public final static ComponentName NAME = new ComponentName("org.nuxeo.runtime.demo.HelloComponent"); Collection<HelloMessage> messages = new ArrayList<HelloMessage>(); public void registerExtension(Extension extension) throws Exception { Object[] messages = extension.getContributions(); for (Object message : messages) { HelloMessage msg = (HelloMessage)message; this.messages.add(msg); System.out.println("Registering message: " + msg.getMessage()); } } public void unregisterExtension(Extension extension) throws Exception { Object[] messages = extension.getContributions(); for (Object message : messages) { HelloMessage msg = (HelloMessage)message; this.messages.remove(msg); System.out.println("Un-Registering message: " + msg.getMessage()); }

}
... }

You can see how the contributed objects are fetched from the Extension object and then registered into a Java Map. These contributions are objects of type HelloMessage as defined by the extension point (using the object sub-element) The contributions are also available as a DOM element so you can use this to retrieve contributions in the case you don't use XMap to map XML extensions to Java objects. This DOM element is corresponding to the extension element from the XML component descriptor. So if you need to retrieve the DOM representation of the extension you can do:
public void registerExtension(Extension extension) throws Exception { Element element = extension.getElement(); // parse yourself the DOM element and extract extension data ... }

6.3 XML Component Descriptors
In this section I will describe the most important elements composing an XML component descriptor.

Document type I All Rights Reserved. I Page 24/27


Project title I Document title

You can inspect the XMap annotations on the class org.nuxeo.runtime.mod el.impl.RegistrationInfoImpl to find all elements that may compose an XML component descriptor. A complete component descriptor may look like this:
<?xml version="1.0"?> <component name="org.nuxeo.ecm.core.schema.TypeService"> <implementation class="org.nuxeo.ecm.core.schema.TypeService"/> <require>org.nuxeo.ecm.core.api.ServerService</require> <require>org.nuxeo.ecm.core.repository.RepositoryService</require> <property name="author">Bogdan Stefanescu</property> <property name="description">The component description ...</propert <extension-point name="doctype"> <object class="org.nuxeo.ecm.core.schema.DocumentTypeDescriptor"/> </extension-point> <extension-point name="schema"> <object class="org.nuxeo.ecm.core.schema.SchemaBindingDescriptor"/> </extension-point> <extension target="org.nuxeo.ecm.core.api.ServerService" point="clientFactory"> <factory class="org.nuxeo.ecm.core.api.impl.LocalClientFactory"/> </extension> <extension target="org.nuxeo.ecm.core.schema.TypeService" point="schema"> <schema name="common" src="schema/common.xsd"/> <schema name="core-types" src="schema/core-types.xsd"/> <schema name="file" src="schema/file.xsd"/> </extension> </component>

Each component is defined inside it's own file. As you can see the root element is "component". This element has a required attribute "name". Apart this all other sub-elements are optional. Here is a list with all supported sub-elements:
1.

implementation

This element is used to specify the component implementation class. The element is not required since one may define plain XML components only for contributing some extensions to other components. We will refer to these components as extension components .
2.

r e qu i r e

This element can be used to specify dependencies on other components. The component will be resolved and activated only after all these dependency are resolved.
Document type I All Rights Reserved. I Page 25/27


Project title I Document title

3.

property

This element can be used to define random properties that will be available later to the component when it will be created.
4.

extension-point

This element is used to declare extension points. A component may declare any number of extension points. See more details on this in Working with extension points section.
5.

extension

This element can be used to declare extensions to other components (or to the current component itself). See more details on this in Working with extension points section.

Document type I All Rights Reserved. I Page 26/27


Project title I Document title

References
· · ·

Nuxeo.org website: http://www.nuxeo.org/ OSGi website: http://www.osgi.org/ JSR 277, 291 and OSGi, Oh My! - OSGi and Java Modularity, presented by Richard S. Hall at ApacheCon Europe 2006: http://docs.safehaus.org/download/attachments/2995/osgi-apachecon20060628.pdf

Document type I All Rights Reserved. I Page 27/27