Lotus Notes 8 Standard offers an elegant deployment mechanism for pushing and pulling of Eclipse features & plugins which leverages the Domino infrastructure and its strengths (high availability, security, offline, policies, synchronization, …). The mechanism is called “Drag-to-Install” and works primarily through a special Domino database called the "widget catalog” and a sidebar application called “My Widgets”.
A widget catalog contains widgets, and widgets are XML documents describing dynamic contributions/extensions to the Notes 8 Standard client. End users drag a widget from the catalog to the “My Widgets” sidebar to install a widget. Installing a widget adds something to the client, like a web page, LiveText content, search engine, Notes object on the sidebar and, of course, Eclipse features & plugins. Likewise, whatever was added is removed when the user removes the widget from “My Widgets”.
In addition to dragging-and-dropping widgets from the widget catalog, the widget XML documents (normally named “extension.xml”) can be drug from the file system or a web server. “My Widgets” basically accepts URLs ending in “extension.xml”.
What a widget does is based on the widget provider and configuration info defined in the widget’s XML. Furthermore, widgets can also make dynamic contributions to Eclipse extension points. In many cases, much of a widget’s work is done through these dynamic extension points.
Both the allowed widget providers and the allowed dynamic extension point contributions can be optionally restricted on clients using a Domino Desktop policy. The Desktop policy can also restrict how users install and share widgets.
One of the widget providers is “com.ibm.rcp.toolbox.prov.provider.ToolboxProvisioning” which invokes the feature/plugin provisioning engine in Lotus Expeditor with a provisioning manifest defined within the widget. Provisioning manifests direct the provisioning engine to install, enable, disable and uninstall Eclipse features. When you configure a new “Features & Plug-ins” widget using the wizard available in Notes 8.5.1, it creates a “com.ibm.rcp.toolbox.prov.provider.ToolboxProvisioning” widget with a provisioning manifest that installs the specified feature(s) from the specified update site.
The following provisioning widget XML contains a provisioning manifest (see the <installManifest> element). The manifest tells the provisioning engine version “184.108.40.206002020358” of the “org.testing.app1” feature needs to be installed. If not already installed, get from update site “nrpc:///__852576be00571335/site.xml”.
Provisioning manifests list Eclipse features that should be present in the platform, at what version levels and where to get the features if not present. Note the “match” attribute on the feature element above – this determines what version(s) of the feature are required on the platform in relation to the version attribute provided in the manifest. “perfect” means a feature with that exact version number must be present in the platform. “compatible” means the feature must have the first 2 version digits in common, e.g. 1.0.1 and 1.0.2 are both compatible with 1.0.0. See the provisioning manifest DTD for reference.
A word on features vs plugins
Plugins contain the executable code, and features package plugins for deployment. Hence deployment activities (aka provisioning) deal with features, not plugins directly.
Plugins are only installed if a feature includes them on its the “Plugins” tab. Plugins are not automatically installed if a feature or other plugin just declares a dependency on them.
Furthermore, only those features which have been provisioned are recognized by the platform. Plugins are only recognized if they are part of a recognized (installed and enabled) feature. This is in contrast to plain Eclipse which recognizes all features and plugins present in its install site folder(s).
Provisioning widget best practices
And without further ado, best practices to consider when packaging Eclipse features and plugins for deployment via widgets.
- Use “perfect” match rule for your feature(s). When your widget installs, the “perfect” match rule guarantees the provisioning engine will attempt to install that version. If the widget intends for version 1.0.1 to be installed and if version 1.0.0 of the feature is already present and if the match rule is “compatible”, version 1.0.1 will not be installed because the “1.0.1 compatible” requirement is met with the presence of 1.0.0 (1.0.1 is considered compatible with 1.0.0 because they only differ in the 3rd version digit).
- Provisioning widgets created using the Features & Plugins wizard in Notes 8.5.1 automatically use “perfect” for the match attribute.
- Never define the same feature using the “perfect” match rule in multiple widgets. If the version numbers do not match, the provisioning engine will be given conflicting requirements (only 1 version of the feature can be enabled at any given time) causing undefined behavior.
- If a widget installs a feature, update that feature by updating the same widget. Do not install a second widget to update the feature. Installing a second widget risks the multiple feature requirement scenario described above.
- Good rule of thumb is make one widget the “owner” of a given feature such that all installs/updates to that feature come through that widget.
- Follow the instructions here to update a feature within a given widget.
- Assign an image for your widget. The widget can reference an image file inside one of the plugins it installs.
- Do not mix deployment mechanisms for a given feature. All features must be provisioned, and the provisioning engine can be invoked in 4 ways: 1) manual install UI (normally hidden to end-users, available via File – Applications – Install), 2) command-line interface (normally used for 3rd party scripted installs, e.g. SMS), 3) through the provisioning API and 4) widgets. Widgets make the assumption no other mechanism is managing the same features deployed through widgets, and unintended results can happen if another mechanism attempts to manage a feature that is also deployed through widgets.
Deploying shared/common features via widgets
Suppose your company wants to roll-out 2 sidebar applications via widgets. Each sidebar application naturally has it’s own plugin, feature and provisioning widget. Users can drag the widget for each application to their sidebar, and this will cause the application’s feature/plugin to be installed. So far, so good.
Now suppose those 2 sidebar applications use a common plugin which is not part of the product and must also be deployed through the widget mechanism. Also suppose the common plugin has a different update cycle than the 2 sidebar applications. What’s the best way to package your features and provisioning widgets such that:
- Users only need to install 1 widget to get an application and its dependencies, e.g. shared features. In other words, users should not have to install 2 or more widgets to get an application and its dependencies.
- Each application can be removed independent of the other. In other words, if features App1 and App2 depend on feature Common, removing App1 should not affect App2. Specifically, it should not remove the Common feature needed by App2.
- The Common feature can be updated without affecting App1 or App2. Of course this assumes the updates to the Common plugin are binary compatible with App1 and App2, e.g. method signatures used by those plugins have not been altered. Use Java interfaces when exposing Common APIs to other plugins to reduce risk of a breaking signature change.
Follow these rules to meet the above requirements:
- Do not declare any dependencies in feature.xml on common/shared plugins. This keeps the features loosely coupled and provisioning flexible. The trade-off is the platform is unaware of the dependencies and won't attempt to enforce them. However the number of common features will be normally be small and manageable, and smooth provisioning is more important. If a plugin's dependency cannot be resolved (because a feature did not deploy that dependency), the plugin will simply not start.
- Do not place shared features in the “Included Features” tab of feature.xml. The “Included Features” tab allows you to create a “master feature” which can roll-up several other features. This is typically for larger applications with many plugins in multiple groupings (features). The master feature rolls-up the sub-features into 1 feature. This simplifies deployment in that only the master feature needs to be installed – the sub-features will be installed automatically.
- Only use the “Included Features” tab when the master and child features are built together, and the child features will never be delivered by other means (i.e. the children will not be part of another widget or included as a child in another master feature).
- Deploy the common feature in its own widget and push to all users via a Domino desktop policy. As of 8.5.1, the best way to ensure the common/shared feature is present is to push it out ahead of time via policy.
- Deploy the application features in widgets by themselves. The dependency on the common plugin will be satisfied with the global push of the Common feature in a separate widget via a widget push policy. In Notes 8.5.1 on startup, Notes will check all of its provisioning widgets to ensure the features they declare are present. If a feature is missing from the platform, it is provisioned from the update site listed in the widget's manifest. So if a user happened to miss provisioning the pushed common feature, they will get on next startup.