-
Notifications
You must be signed in to change notification settings - Fork 6
Components
As we saw in the Extension Points section, components are singleton objects that are registered when a bundle declaring an XML component becomes available.
These objects may be used to achieve a variety of tasks like:
- Being notified when the bundle declaring the component is resovled
- Being notified when the bundle declaring the component is unresolved
- Being notified when the ECR application was started
- Providing services. See Services section
- Managing extension points. See Extension Points
A component may look like a sort of Bundle Activator. Both are managed singleton objects activated and deactivated during changes in the bundle's life cycle. But there are also differences:
- You can have any number of components in a bundle
- Components are defined through an XML descriptor file
- Components are mainly used to wire your bundles using ECR extension points
As we've seen in the Extension Points section, to declare a component you should create an XML file, put it somewhere in the bundle, and reference that file inside the MANIFEST.MF
using the Nuxeo-Component
header.
Here is an example of an empty component XML file:
<?xml version="1.0"?>
<component name="org.eclipse.ecr.sample.EmptyComponent"
version="1.0.0">
</component>
To declare this component, put the file, let's say, in OSGI-INF/my-empty-component.xml
inside your bundle and add the following header in your MANIFEST.MF
:
Nuxeo-Component: OSGI-INF/my-empty-component.xml
You can declare any number of component in your bundle by referencing them all in the Nuxeo-Component
header. Example:
Nuxeo-Component: OSGI-INF/my-empty-component.xml, OSGI-INF/my-second-component.xml
Usually, apart the XML descriptor file, components have an Java implementation object that implements the org.eclipse.ecr.runtime.model.Component
interface.
Although, you can directly implement this interface it is recommended to extends the class org.eclipse.ecr.runtime.model.DefaultComponent
which have a richer set of methods.
But, a component may not necessarily provide an implementation class. We will discuss this special case in the next section.
Configuration component are a special case of components that are used only to provide extensions to existing extension points in the application. This type of components doesn't need to provide an Java implementation for the component.
Example:
<?xml version="1.0"?>
<component name="org.eclipse.ecr.core.api.blohodlers.adapters">
<extension target="org.eclipse.ecr.core.api.DocumentAdapterService"
point="adapters">
<adapter class="org.eclipse.ecr.core.api.blobholder.BlobHolder"
factory="org.eclipse.ecr.core.api.blobholder.BlobHolderAdapterFactory" />
</extension>
</component>
You can see that this component is only contributing an extension to DocumentAdapterService
through the adapters extension point.
We will talk now about regular components - that also provides a Java implementation class.
These components are useful to hook into the application (e.g. to be notified about application startup, etc) or to provide services or manage extension points.
This type of component may declare any number of extension points, services or contributions.
Here is a minimal component declaration:
<?xml version="1.0"?>
<component name="org.eclipse.ecr.sample.MyComponent">
<implementation class="org.eclipse.ecr.sample.MyComponent" />
</component>
This XML component descriptor declares a component implemented by the org.eclipse.ecr.sample.MyComponent
class.
Here is an example of a simple component implementation
public class MyComponent extends DefaultComponent {
@Override
public void activate(ComponentContext context) throws Exception {
System.out.println("Activating component "+MyComponent.class);
}
@Override
public void deactivate(ComponentContext context) throws Exception {
System.out.println("Deactivating component "+MyComponent.class);
}
@Override
public void applicationStarted(ComponentContext context) throws Exception {
System.out.println("Application started");
}
@Override
public <T> T getAdapter(Class<T> adapter) {
return null;
}
@Override
public void registerContribution(Object contribution,
String extensionPoint, ComponentInstance contributor)
throws Exception {
}
@Override
public void unregisterContribution(Object contribution,
String extensionPoint, ComponentInstance contributor)
throws Exception {
}
}
-
The activate method
This method should be used to initialize the component and will be invoked by the component manager when the component is put into service.
It takes as argument a
ComponentContext
which can be used to retrieve theBundleContext
and other useful context data.You can use it for example to instantiate the services you want to export.
-
The deactivate method
This method should be used to cleanup any resource held by the component and will be called by the component manager before the component is removed.
-
The applicationStarted method
This method will be called by the component manager after the ECR Application started (that means that all components found at startup were activated and all extension point wiring is done).
-
The getAdapter method
This method is called to get an instance of the services declared by this component.
For more details see the Services section.
-
The registerContribution method
This method will be called for each contribution that is contributed to one of the extension points declared by this component.
It takes as arguments the contribution object, the name of the target extension point and the context of the contributor. (You can use this context to get for example the Bundle of the contributor).
For more details see the Extension Points section.
-
The unregisterContribution method
This method will be called for each contribution that should be removed from one of the extension points declared by this component.
It takes as arguments the contribution object, the name of the target extension point and the context of the contributor. (You can use this context to get for example the Bundle of the contributor).
For more details see the Extension Points section.
Let's look now on how components are activated and when the notification methods we described above are called by the component manager.
When the org.eclipse.ecr.runtime
bundle starts (the bundle activator is started) it will open a bundle tracker to track any resolved bundle declaring components.
At this point all existing resolved bundles are scanned for components.
For each component which was found a new component instance is created (if the component provide an implementation) and the component is activated (by calling the activate
method).
Thus components are activated when the bundle are at least in the RESOLVED state. This means that on OSGi platforms supporting lazy loading, bundles which use lazy activation policy will be automatically STARTED by the component instantiation.
In that case, the component activate
method will always be called after the start
method of the bundle activator was called (if any activator is defined).
After a component is activated all the extensions declared by the component will be contributed to the target extension points, and all the pending extensions contributed to the extension points provided by the component will be registered (i.e. the registerContribution
method will be called).
After all detected components are activated (and extension point wiring is completed) the applicationStarted
method is called on each component.
While te application is running for each newly resolved or unresolved bundle that contains ECR components will trigger the activation/deactivation of the component.
If a component containing extension points is deactivated - all the existing contribution to that extension points will be put into a pending queue - this way if the component will be activated again it will register again all pending contributions.
Next: Go to the Services section for details on how components may provide services.