Rhino has a dynamic approach to dependency specification and binding, supported by multiple install levels for components, virtual copy of installed components, and dependency specification and application.
Dynamic component reference bindings
The JAIN SLEE specification states that every deployable component has an identity specified by a name, vendor, and version tuple. This identity must be unique within the scope of a given component type. A component may reference other components of various types by specifying their type and identity in the component deployment descriptor.
These references are static, that is: they are defined prior to installation in the SLEE; and once the component is installed the references cannot be changed. Static references in general function adequately; however they can make the application upgrade process more complicated that it need be.
For example, if a library component used by an application has a bug fixed and a new version of the library is produced, then all dependent components such as SBBs and profile specifications need to have their references updated and new versions released; and all components dependent on those, such as other SBBs and service components, also need updating and releasing; and so on through the chain of dependencies.
A more dynamic approach to dependency specification and binding would help make the upgrade process easier. Rhino provides such an approach, which is supported by the following concepts:
-
multiple install levels for components
-
virtual copy of installed components
-
dependency specification and application.
Each of these concepts is described in detail below.
Install levels
The JAIN SLEE specification defines that a deployable unit and the components it contains is either installed or not installed in the SLEE. When a deployable unit is installed, its components are verified for correctness, and if verification is successful the components are made ready for use; for example, service components are initialised ready for activation.
To facilitate the management of dynamic component bindings, Rhino provides finer-grained control over the degree to which a deployable unit and its components are installed. Installed components each have one of the following install levels:
-
INSTALLED
— The component is installed in the SLEE. The deployment descriptor has been validated for syntax and and has been parsed; however any component and class references, configuration parameters, and other relevant information contained in the deployment descriptor has not been verified for correctness. -
VERIFIED
— The component is installed and has successfully passed all verification checks. -
DEPLOYED
— The component is installed, it has passed verification, any necessary implementation code has been generated, and it has been deployed to each cluster node ready for immediate use (such as service activation).
Here are some ways you can manage install levels:
Specify the level |
The initial install level for a deployable unit and the components it contains can be specified when the deployable unit is installed.
For example, using
|
||
---|---|---|---|
Verify an installed component |
An installed component can subsequently be verified using the
If the component being verified depends on other components that are installed but yet to be verified, then Rhino will automatically verify those dependent components first. (See the note about install levels below.) |
||
Verify an installed DU |
An installed deployable unit may also be "verified".
Deployable unit verification is a convenience mechanism to verify all the components contained in the deployable unit with a single command.
For example, using
Only the deployable unit components that have yet to be verified are affected by this command. As such, verifying a deployable unit that only contains already verified components has no further effect. |
||
Deploy a component |
A component can be deployed using the
If the component being deployed depends on other components that are not yet deployed, then Rhino will automatically deploy those dependent components first, and so on recursively. (See the note about install levels below.) If any component being deployed has not yet been verified, then Rhino will automatically verify the component before deploying it. The deploy operation will fail if any verification errors are found in this case. |
||
Deploy an installed DU |
An installed deployable unit may also be "deployed".
Deployable unit deployment is, again, a convenience mechanism to deploy all the components contained in the deployable unit with a single command.
A deployable unit can be deployed in
Only the deployable unit components that have yet to be deployed are affected by this command. As such, deploying a deployable unit that only contains already deployed components has no further effect. |
||
Undeploy a deployed component |
A deployed component can subsequently be undeployed.
When a component is undeployed it reverts to the A deployed component is undeployed using the
If there are any components that depend on the component being undeployed that themselves have an install level of An undeploy operation will fail if any component that would be affected by the operation does not satisfy the below requirements:
|
||
Unverify a component |
A verified or deployed component can subsequently be unverified.
When a component is unverified it reverts to the A component is unverified using the
If there are any components that depend on the component being unverified that themselves have an install level of |
About install levels
The general rule for install levels is that any given component cannot have an install level greater than any of the components that it depends on. If a component desires to transition to a higher install level then all its dependent components must successfully transition to the new install level first. If a component desires to transition to a lower install level then all components that depend on it must successfully transition to the new install level first. |
Component copy
In order to maintain compatibility with the JAIN SLEE specification, Rhino does not permit the component references of components installed using a standard SLEE deployable unit — hereinafter termed "original" components — to be dynamically modified. Rather, a virtual copy of each component to be modified must be made, and the references of the copied components modified instead. A copied component is still a SLEE component in its own right, and must have a unique identity within the scope of the component type as for any other component. The only difference between an original SLEE component and a copied component is from where the component originates in the SLEE. A copied component uses the same set of interfaces and classes, and inherits the configuration properties such as environment entries, from the component it is copied from.
Here are some commands for managing copies:
Copy |
A component can be copied using the
The install level of the copied component can optionally be specified when the copy is made.
If not specified, a default install level of |
---|---|
Show copy history |
A copied component may be subsequently copied again, leading to the treelike structure of copies branching out from the original.
The
|
Remove copied components |
A copied component has an implicit dependency on its original.
This means that a deployable unit that has copied components cannot be uninstalled from the SLEE until all its copied components have been removed.
Copied components are removed using the
|
Find orphaned copied components |
After some copied components have been removed, other copied components may remain that are no longer referenced by any other component.
The
|
Dynamic dependency specification
Dynamic component dependencies are specified using a binding descriptor. A binding descriptor is a JSON document that describes the changes that should be made to the deployment descriptors of one or more components. For example, a binding descriptor may change the root SBB of a service, or may add a new library reference to an SBB. A binding descriptor can only add to or change existing information contained in a deployment descriptor; it cannot remove any existing information.
A binding descriptor is a new component type in Rhino. As a component type, a binding descriptor has an identity described by the name, vendor, and version tuple — like all other SLEE component types. A binding descriptor document may be installed in Rhino as a new type of deployable entity.
Binding descriptor format
A binding descriptor is a JSON document that must conform to the schema defined by Rhino.
The binding descriptor schema can be found in the doc/dtd
directory of a Rhino install.
Loosely speaking, a binding descriptor document must contain the declaration of a single JSON object with:
-
an optional
description
property containing an arbitrary string description -
mandatory
name
,vendor
, andversion
properties -
an optional
service
property containing a service descriptor -
an optional
sbbs
property containing an array of zero or more SBB descriptors -
an optional
sbbParts
property containing an array of zero or more SBB part descriptors -
an optional
profileSpecs
property containing an array of zero or more profile specification descriptors -
an optional
libraries
property containing an array of zero or more library descriptors.
Each component descriptor that can be contained by a binding descriptor has a structure based on the corresponding SLEE-defined DTD for that component type. Only component properties that can be modified by bindings are defined by the schema and can be included in a binding descriptor.
Below is an example of a binding descriptor that can be used to change the root SBB of a service:
{ "description": "Change service's root SBB", "name": "Example binding descriptor", "vendor": "OpenCloud", "version": "1.0", "service": { "rootSbb": { "name": "MyOtherSBB", "vendor": "OpenCloud", "version": "1.0" } } }
Managing binding descriptors
A binding descriptor is installed into Rhino much like a SLEE deployable unit. The deployable type option must be used to indicate that the type of object being installed is a binding descriptor.
Here’s how to install and uninstall them:
Install a binding descriptor |
The example below shows how a binding descriptor can be installed using
Install levels are not relevant for binding descriptors. Any install level specified when a binding descriptor is installed is ignored.
|
||
---|---|---|---|
Uninstall a binding descriptor |
An installed binding descriptor can be uninstalled in the same way as any other SLEE deployable unit.
For example, using
|
Binding descriptor application
Binding descriptors are applied to components within the scope of a service.
That is, a binding descriptor can be associated with a service, and its effects are propagated to the affected components used by the service.
Binding descriptors can be associated with, and subsequently disassociated from, any service with an install level of INSTALLED
or VERIFIED
.
A service with an install level of DEPLOYED
must be undeployed before its binding descriptor associations can be changed.
Binding descriptors can only be associated with a component copy service component. If a command is given to associate a binding descriptor with an original service component, a new copy of the service component will automatically be made by Rhino and the binding descriptor associated with the copied component instead.
A binding descriptor associated with a service that affects dependent components of the service, such as SBBs or libraries, requires that those components be copied and the effects of the binding descriptor applied to the copied components. Rhino will automatically copy components where necessary to fulfil this requirement, according to the following rules:
-
If an original component needs its bindings modified, a copy is first made and the copy modified.
-
If a copied component needs its bindings modified, and the copied component is not used in any other service, then the copied component is reused for the new modifications.
-
If a copied component needs its bindings modified, but the copied component is in use by some other service, then a new copy is made and the new copy modified.
-
The ripple effect may cause other copies to be generated. For example, if SBB A references SBB B and SBB B is copied and its bindings modified, then SBB A also needs to be modified with an update to reference the copied SBB B. To do this SBB A may also need to be copied first as described above.
The component identifiers of copied components may be specified as part of the binding operation, if specific identifiers are desired. If a component needs to be copied but a component identifier has not been specified for the copy, then Rhino will automatically generate a new unique component identifier based on the original component’s identifier.
Service binding capabilities
A binding descriptor applied to a service may cause any of the following actions:
-
change the root SBB of the service
-
modify one or more dependent SBBs by:
-
adding new library, profile specification, SBB, and/or SBB part references
-
adding new resource adaptor type bindings
-
adding new declarative SBB child relations
-
adding new CMP extension interfaces
-
adding new extension usage parameters interfaces
-
adding new environment entries, or changing the values of existing environment entries
-
-
modify one or more dependent SBB parts by:
-
adding new library, profile specification, and/or SBB part references
-
adding new resource adaptor type bindings
-
adding new CMP extension interfaces
-
adding new extension usage parameters interfaces
-
-
modify one or more dependent profile specifications by:
-
adding new library and/or profile specification references
-
adding new environment entries, or changing the values of existing environment entries
-
changing the definition or options of static queries
-
-
modify one or more dependent libraries by:
-
adding new library references.
-
Due to classloader limitations, a profile specification can only have its bindings modified if there are no profile tables, resource adaptor entities, or services with an install level of DEPLOYED , that depend on any profile specification in the same profile specification component jar present in the SLEE.
Attempting to change the bindings of a profile specification that does not meet this criteria will result in the failure of the binding operation.
|
Binding conflicts
It is possible that a conflict may arise with a binding descriptor that is associated with a service:
-
A binding descriptor may declare a usage parameters interface of type X, as extending a different usage parameters interface type than a previous definition of X (either in the original deployment descriptor or in another associated binding descriptor).
No conflict arises if X has previously been declared with no extends type, but an associated binding descriptor specifies an extends type for X. In this case, the SLEE assumes that X should now extend the specified type rather than extend nothing. -
A binding may declare an environment entry with name X with a different Java type than a previous definition of X.
If either of these types of conflicts occur, the binding descriptor association fails. The conflict must be resolved before the binding descriptor can be successfully associated.
Duplicate definitions such as component references do not cause a conflict. For example if the deployment descriptor and one or more binding descriptors all declare the same library reference, they are simply merged together into a single reference.
Associating a binding with a service
Here’s how to associate a binding descriptor with a service, map target component identifiers of copied component, and disassociate a binding descriptor from a service:
Associate |
A binding descriptor is associated with a service using the
The example below associates a binding descriptor with a service:
|
||
---|---|---|---|
Create mappings |
The
The following example creates a mapping and uses it to control the component identifier of the SBB copied by the binding operation:
|
||
Disassociate |
A binding descriptor can be disassociated from a service using the
An example of a binding descriptor being disassociated from a service is shown below:
|