This section explains the Binder — what it consists of and how to use it |
- What is the Binder ?
- Module publications
- Required annotations in Sentinel features
- Required Ivy dependencies for bindings
- Annotation processing and Rhino bindings
- Types of SLEE components that bindings are applied to in the Sentinel SDK
- Using the Binder to apply bindings
- Unbinding components
What is the Binder ?
The Binder is a tool supplied with the Sentinel SDK.
It is able to ‘bind’ various components together once they have been deployed into the Rhino.
It makes use of the bindings features introduced in Rhino 2.4.0.
For a comparison between JSLEE deployment descriptor references and Rhino bindings, see this page. |
Module publications
When a module is built, bindings meta-data is created in the target/generated/bindings directory. The bindings meta-data file(s) are then archived and published with the module.
The archive itself is created in target/artifacts, and whether or not it is published is declared in the publications section of a modules ivy.xml file.
Bindings meta-data is produced from the Java annotations in a feature’s source files.
Type of module | Generated bindings files |
---|---|
JSLEE Library |
target/generated/library-bindings.json |
JSLEE Profile |
target/generated/profile-bindings.json |
Sentinel POJO feature |
target/generated/sbbpart-bindings.json |
Sentinel Mapper |
target/generated/sbbpart-bindings.json |
Sentinel SBB feature |
target/generated/sbb-bindings.json |
It may be useful to review the content of the generated bindings meta-data files when developing a module.
Here is an example for a Sentinel POJO feature:
{
"componentType": "SBBPart",
"dependencies": [
{
"type": "Library",
"sleeComponent": {
"name": "SentinelFeaturesCommon",
"vendor": "OpenCloud",
"version": "2.3"
},
"ivyInfo": {
"type": "transitive",
"name": "SentinelFeaturesCommon",
"organisation": "",
"revision": "",
"branch": ""
}
},
{
"type": "Library",
"sleeComponent": {
"name": "SentinelSipFeatureSPI",
"vendor": "OpenCloud",
"version": "2.3"
},
"ivyInfo": {
"type": "transitive",
"name": "SentinelSipFeatureSPI",
"organisation": "",
"revision": "",
"branch": ""
}
},
{
"type": "SBBPart",
"sleeComponent": {
"name": "my-sip-example-mapper",
"vendor": "UNSET",
"version": "1.0"
},
"ivyInfo": {
"type": "direct",
"name": "my-sip-example-mapper",
"organisation": "UNSET",
"revision": "1.0.0-DEV4-davidf",
"branch": "trunk"
}
},
{
"type": "SBBPart",
"sleeComponent": {
"name": "SentinelSipFeatureSPI SBB Part",
"vendor": "OpenCloud",
"version": "2.3"
},
"ivyInfo": {
"type": "transitive",
"name": "SentinelSipFeatureSPI SBB Part",
"organisation": "",
"revision": "",
"branch": ""
}
},
{
"type": "Profile",
"sleeComponent": {
"name": "my-sip-example-profile",
"vendor": "UNSET",
"version": "1.0"
},
"ivyInfo": {
"type": "direct",
"name": "my-sip-example-profile",
"organisation": "UNSET",
"revision": "1.0.0-DEV4-davidf",
"branch": "trunk"
}
}
]
}
-
Each outward reference from the component (in this case a Sentinel POJO feature) is listed in the file.
-
The type of reference (e.g. library, profile, sbb part) is indicated in the "type" field.
-
The “sleeComponent” field provided the SLEE Component ID name, vendor, and version.
-
The “ivyInfo” field states whether the dependency is a direct dependency (i.e. directly depended on in the modules ivy.xml file) or transitive.
-
It also lists the Ivy module’s name. In the case that a dependency is a direct dependency, the organisation, revision and branch fields have values.
-
In the example above, it can be seen that the POJO feature has:
-
two library references
-
two SBB part references
-
one profile reference
Required annotations in Sentinel features
Specific annotations are required in Sentinel feature source file(s) for bindings to successfully occur.
Annotations in the feature source are read when a feature is built, and make their way into the bindings meta-data.
These annotations indicate which type of Sentinel service a feature should be bound into.
Sentinel supports two mechanisms for explicitly declaring which Sentinel services a feature should be bound into:
-
@BinderTargets annotations, declaring the targeted Sentinel services, or
-
@LibraryReference and @SBBPartReference annotations on a Sentinel SPI library or SBB part
The binder will consider @BinderTargets annotations first. For features which do not declare a ‘@BinderTargets’ annotation, the binder will choose the target services based on SLEE references to the relevant SPI library/SBB part.
The @BinderTargets annotation
Sentinel supports a ‘@BinderTargets’ annotation for explicitly declaring which Sentinel services a feature should be bound into.
The services
attribute contains a list of service target names representing the Sentinel services to bind the feature into.
This table shows how the service target names used in the @BinderTargets annotation map to Sentinel services:
Target service name |
Services to bind into |
ss7 |
sentinel.ss7, sentinel.volte.ss7 |
sip |
sentinel.sip, sentinel.volte.sip, sentinel.ipsmgw |
sip.charge |
sentinel.sip, sentinel.volte.sip |
sip.test |
sentinel.sip, sentinel.volte.sip, sentinel.ipsmgw |
ipsmgw |
sentinel.ipsmgw |
ipsmgw.test |
sentinel.ipsmgw |
diameter |
sentinel.diameter |
ussd |
sentinel.ussd |
registrar |
sentinel.registrar |
core |
sentinel.ss7, sentinel.sip, sentinel.diameter |
ims |
sentinel.volte.sip |
ims.gsm |
sentinel.volte.sip |
mmtel |
sentinel.volte.sip |
mmtel.conference |
sentinel.volte.sip |
scc |
sentinel.volte.sip |
scc.gsm |
sentinel.volte.sip |
scc.cdma |
sentinel.volte.sip |
The following example shows how to use the @BinderTargets
annotation to bind MyFeature
into both the SIP and SS7 Sentinel services:
@BinderTargets(services = {"sip", "ss7"})
// ...
public class MyFeature {
// ...
}
Which annotations to use for each Sentinel service
Desired Service | Service name | @BinderTargets annotation target service name | SPI annotation |
---|---|---|---|
Sentinel SIP |
“sentinel.sip” |
sip |
Library reference to “SentinelSipFeatureSPI”, or SBB Part reference to “SentinelSipFeatureSPI SBB Part” |
Sentinel SS7 |
“sentinel.ss7” |
ss7 |
Library reference to “SentinelSs7FeatureSPI”, or SBB Part reference to “SentinelSs7FeatureSPI SBB Part” |
Sentinel Diameter |
“sentinel.diameter” |
diameter |
Library reference to “SentinelDiameterFeatureSPI”, or SBB Part reference to “SentinelDiameterFeatureSPI SBB Part” |
Sentinel Registrar |
“sentinel.registrar” |
registrar |
Library reference to “SentinelRegistrarFeatureSPI”, or SBB Part reference to “SentinelRegistrarFeatureSPI SBB Part” |
The binder will attempt to bind a feature with the above annotations into the particular service or set of services, assuming that those services are deployed. If any of the related services are not deployed, the binder will skip those services and will not treat that situation as an error.
Other annotations needed
Core features
Core features need:
-
a @BinderTargets annotation targeting "core" (e.g.
@BinderTargets(services = "core")
); OR -
a Library reference to “SentinelFeatureSPI”; OR
-
an SBB Part reference to “SentinelFeatureSPI SBB Part”
Diameter Mediation features
Diameter Mediation features need:
-
a @BinderTargets annotation targeting "core" (e.g.
@BinderTargets(services = "core"})
); OR -
a Library reference to “SentinelDiameterMediationFeatureSPI”; OR
-
an SBB Part reference to “SentinelDiameterMediationFeatureSPI SBB Part”.
Result
These mean that the feature will be bound into any of the following Sentinel services:
-
Sentinel SIP
-
Sentinel SS7
-
Sentinel Diameter
If only Sentinel Diameter is deployed, then such a feature will be bound into Sentinel Diameter.
If both Sentinel SIP and Sentinel Diameter are deployed, then such a feature will be bound into Sentinel SIP and Sentinel Diameter services.
Example required annotations
SIP feature annotations
One of the three annotations is required, either will suffice:
@BinderTargets(services = "sip")
@LibraryReferences(
libraryRefs = {
@LibraryReference(library = @ComponentId(name = "SentinelSipFeatureSPI", vendor = "OpenCloud", version = "@sentinel-sip.component.version@"))
}
)
@SBBPartReferences(
sbbPartRefs = {
@SBBPartReference(id = @ComponentId(name = "SentinelSipFeatureSPI SBB Part", vendor = "OpenCloud", version = "@sentinel-sip.component.version@"))
}
)
SS7 feature annotations
One of the three annotations is required, either will suffice:
@BinderTargets(services = "ss7")
@LibraryReferences(
libraryRefs = {
@LibraryReference(library = @ComponentId(name = "SentinelSs7FeatureSPI", vendor = "OpenCloud", version = "@sentinel-ss7.component.version@"))
}
)
@SBBPartReferences(
sbbPartRefs = {
@SBBPartReference(id = @ComponentId(name = "SentinelSs7FeatureSPI SBB Part", vendor = "OpenCloud", version = "@sentinel-ss7.component.version@"))
}
)
Diameter feature annotations
One of the three annotations is required, either will suffice:
@BinderTargets(services = "diameter")
@LibraryReferences(
libraryRefs = {
@LibraryReference(library = @ComponentId(name = "SentinelDiameterFeatureSPI", vendor = "OpenCloud", version = "@sentinel-diameter.component.version@"))
}
)
@SBBPartReferences(
sbbPartRefs = {
@SBBPartReference(id = @ComponentId(name = "SentinelDiameterFeatureSPI SBB Part", vendor = "OpenCloud", version = "@sentinel-diameter.component.version@"))
}
)
Registrar feature annotations
One of the three annotations is required, either will suffice:
@BinderTargets(services = "registrar")
@LibraryReferences(
libraryRefs = {
@LibraryReference(library = @ComponentId(name = "SentinelRegistrarFeatureSPI", vendor = "OpenCloud", version = "@sentinel-registrar.component.version@"))
}
)
@SBBPartReferences(
sbbPartRefs = {
@SBBPartReference(id = @ComponentId(name = "SentinelRegistrarFeatureSPI SBB Part", vendor = "OpenCloud", version = "@sentinel-registrar.component.version@"))
}
)
Core feature annotations
One of the three annotations is required, either will suffice:
@BinderTargets(services = "core")
@LibraryReferences(
libraryRefs = {
@LibraryReference(library = @ComponentId(name = "SentinelFeatureSPI", vendor = "OpenCloud", version = "@sentinel-core.component.version@"))
}
)
@SBBPartReferences(
sbbPartRefs = {
@SBBPartReference(id = @ComponentId(name = "SentinelFeatureSPI SBB Part", vendor = "OpenCloud", version = "@sentinel-core.component.version@"))
}
)
Diameter Mediation feature annotations
One of the three annotations is required, either will suffice:
@BinderTargets(services = "core")
@LibraryReferences(
libraryRefs = {
@LibraryReference(library = @ComponentId(name = "SentinelDiameterMediationFeatureSPI", vendor = "OpenCloud", version = "@sentinel-core.component.version@"))
}
)
@SBBPartReferences(
sbbPartRefs = {
@SBBPartReference(id = @ComponentId(name = "SentinelDiameterMediationFeatureSPI SBB Part", vendor = "OpenCloud", version = "@sentinel-core.component.version@"))
}
)
Required Ivy dependencies for bindings
Modules must publish their bindings archive to the ‘slee-binding’ Ivy configuration.
When modules depend on other modules, typically they should include the ‘slee-binding’ Ivy configuration in their dependencies. This is so that the binder can traverse a graph of modules, binding all of them.
So for example, in the case of a related set of modules, such as a feature, a profile for configuring that feature, and a library containing shared session state fields, the Ivy dependencies from the feature must contain slee-binding.
Here is an example of a features ivy.xml file where the feature depends on a profile and mapper:
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
<info organisation="${sdk.ivy.org}"
module="my-sip-example-feature"
e:sourceurl="${svn.info.url}" e:sourcerev="${svn.info.wcversion}" e:user="${user.name}"
e:indextags="sip, feature, sbb-part"/>
<configurations>
<conf name="antlib" description="Ant tasks used to build this module" />
<conf name="slee-component" description="SLEE Components published by this module" />
<conf name="api" description="Artifacts needed to compile components using this module" />
<conf name="deploy" description="Deployment artifacts" />
<conf name="doc" description="Documentation source artifacts" />
<conf name="config" description="SLEE component configuration files" />
<conf name="module-pack" description="Module source artifact" />
<conf name="slee-binding" description="SLEE component binding metadata" />
<conf name="provisioning" description="Feature provisioning definitions" />
<conf name="self" description="" visibility="private"/>
<conf name="test" description="" visibility="private"/>
</configurations>
<publications>
<artifact name="${ivy.module}" type="sbbpart" ext="jar" conf="slee-component,api"/>
<artifact name="${ivy.module}-javadoc" type="javadoc" ext="zip" conf="doc"/>
<artifact name="${ivy.module}-config" type="config" ext="zip" conf="config"/>
<artifact name="${ivy.module}-provisioning" type="provisioning" ext="xml" conf="provisioning"/>
<artifact name="${ivy.module}-bindings" type="binding" ext="zip" conf="slee-binding"/>
</publications>
<dependencies>
<dependency org="opencloud" name="sentinel-sip-support" rev="${sentinel-sip-support.ivy.revision}" branch="${sentinel-sip-support.ivy.branch}" conf="antlib; self->api" />
<dependency org="${sdk.ivy.org}" name="my-sip-example-profile" rev="latest.${ivy.status}" conf="self,provisioning -> api; slee-component; config; slee-binding"/>
<dependency org="${sdk.ivy.org}" name="my-sip-example-mapper" rev="latest.${ivy.status}" conf="self -> api; slee-component; config; slee-binding"/>
</dependencies>
</ivy-module>
Annotation processing and Rhino bindings
The SLEE annotation processor is executed when a module is built. It produces both component deployment descriptor files, and bindings meta-data files.
It can be configured to generate “outwards” component references in:
-
the component deployment descriptor only
-
the component deployment descriptor, and in the bindings meta-data file
-
the bindings meta-data file only
The Sentinel SDK uses the second of the three options — outwards references in modules are included in both the deployment descriptor and bindings meta-data files.
Sentinel Services themselves are published without any feature or mapper references. This allows features to be added and removed through bindings.
Types of SLEE components that bindings are applied to in the Sentinel SDK
Rhino 2.4.0.x and later enables bindings to be used in place of deployment descriptor references.
From component type | Reference type | Destination component type |
---|---|---|
Service |
Root SBB Ref |
SBB |
SBB |
Child SBB Ref |
SBB |
SBB |
SBB Part Ref |
SBB Part |
SBB |
Library Ref |
Library |
SBB |
RA Type Ref |
RA Type |
SBB Part |
Library Ref |
Library |
SBB Part |
RA Type Ref |
RA Type |
SBB Part |
SBB Part Ref |
SBB Part |
Profile Spec |
Profile Spec Ref |
Profile Spec |
Profile Spec |
Library Ref |
Library |
Library |
Library Ref |
Library |
The binder that ships with the Sentinel SDK applies bindings to a subset of those available in the platform. Specifically binding is used in the Sentinel SDK for:
From component type | Reference type | Destination component type | Purpose |
---|---|---|---|
SBB |
Child SBB Ref |
SBB |
Support Feature SBBs and OCS drivers being dynamically bound into Sentinel Services |
SBB |
SBB Part Ref |
SBB Part |
Support POJO features and mappers being dynamically bound into Sentinel Services |
SBB Part |
SBB Part Ref |
SBB Part |
Support Features and mappers being dynamically bound into Sentinel Services |
Using the Binder to apply bindings
There are two commands that the binder takes - bind or bind-with-deps.
The bind command attempts to bind a single module, whereas bind-with-deps walks the Ivy dependency hierarchy reading the slee-binding Ivy configuration. Each command may require Rhino to make component copies. The bind-with-deps command will perform multiple bindings within a single 'block of work', and so create only one copy of a Service. Whereas if bind is run many times, then multiple copies may be taken.
Walking the Ivy graph, short cutting when finding a Profile or Library.
In this dependency graph there are five modules. Starting from the root:
-
Module A - a Group module. This module does not publish any SLEE components. It has Ivy dependencies on two modules, modules B and C.
-
Module B - a Feature module. This module publishes a POJO feature into the slee-component Ivy configuration and bindings meta-data into the slee-bindings Ivy configuration.
It has an Ivy dependency on a Profile module. -
Module C - a Feature module. This module publishes a POJO feature into the slee-component Ivy configuration and bindings meta-data into the slee-bindings Ivy configuration.
It has an Ivy dependency on a Profile module. -
Module D - a Profile module. This module publishes a Profile component into the slee-component Ivy configuration and bindings meta-data into the slee-bindings Ivy configuration.
It has an Ivy dependency on a Library module. -
Module E - a Library module. This module publishes a Library component into the slee-component Ivy configuration and bindings meta-data into the slee-bindings Ivy configuration.
It has no dependencies.
The Ivy configurations as part of the dependencies are shown in text on the diagram, next to the dependency line. The important thing to note is that all modules are using the 'slee-binding' configuration in their dependencies. This means that the binder can traverse the module structure.
Assume that bind-with-deps is invoked pointing to Module A. The binder will read module A and classify it as a group module. It will then look at the dependencies of Module A finding B and C. B and C are analysed as being POJO Feature modules. Their dependencies are followed to module D. This module is a Profile module. The binder does not ask Rhino to apply bindings to Profile modules, so evaluation of Module D is exited and Module D’s dependencies are not analysed.
The binder is able to classify modules based on their publications and dependencies. To see if there are any bindings present the binder scans the publications of the module, looking for a zip file with the filename ending in 'bindings.zip' published with "type=binding" conf of "slee-binding". If there is a bindings archive present, the binder determines the component type by reading the bindings meta-data contained in the archive. In the case that there is no bindings archive present, the binder queries the Ivy dependencies of the component seeing if they have bindings information present. If any module (either directly or indirectly) depended on by this module publishes bindings, then this module has its type set to 'group'.
Common error messages
The following message is output by the binder when a component is of the wrong type to be bound. In this case the module is a profile module.
[oc:bind] Bind Result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Bind result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Nothing to report: [oc:bind] --------------------------------------------------------------------- [oc:bind] --------------------------------------------------------------------- [oc:bind] All modules bound successfully.
The following error message is output by the binder when a component has not been installed into the Rhino SLEE, but the binder has been asked to bind it.
[oc:bind] Bind Result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Bind result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Failed modules: [oc:bind] | UNSET#my-sip-example-feature#trunk;1.0.0-DEV6-davidf [oc:bind] | |__ ModuleBindResult{resultParts=[bindings installed, bindings failure: Failed to bind module UNSET#my-sip-example-feature#trunk;1.0.0-DEV6-davidf in Rhino. [oc:bind] | Cause: com.opencloud.sleedeployer.binder.BindingFailedException: Unable to apply bindings to service [oc:bind] | at com.opencloud.sleedeployer.binder.InlineModuleBinder.applyBindings(InlineModuleBinder.java:478) [oc:bind] | at com.opencloud.sleedeployer.binder.InlineModuleBinder.bindModule(InlineModuleBinder.java:118) [oc:bind] | at com.opencloud.sleedeployer.binder.BindingModuleVisitor.applyBindingsToService(BindingModuleVisitor.java:93) [oc:bind] | at com.opencloud.sleedeployer.binder.BindingModuleVisitor.preVisitModule(BindingModuleVisitor.java:70) ... pruned for verbosity [oc:bind] | at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109) [oc:bind] | Caused by: com.opencloud.rhino.management.BindingVerificationException: Verification error(s) in one or more components: [oc:bind] | Verification error(s) in binding component BindingDescriptorID[name=my-sip-example-feature-bindings,vendor=UNSET,version=1.0.0-DEV6-davidf]: [oc:bind] | Referenced SBB part not installed: SbbPartID[name=my-sip-example-feature,vendor=UNSET,version=1.0] ... pruned for verbosity
Error messages that are not yet in the doc:
-
No appropriate services installed in Rhino SLEE
-
Component does not participate in Service
Output files when running the Binder
The binder generates Rhino bindings descriptors, and installs them into the Rhino SLEE. These can be located in the target/binder-work/bindings subdirectory.
These files can be viewed in a text editor.
Rhino generated Component copies
When the binder applies bindings in Rhino, Rhino will create copies of components as necessary. If a service is inactive when bindings are about to be applied then Rhino can create the necessary bindings.
An example is shown below. In this example a sip example feature is bound into Sentinel’s SIP Service. The service was inactive at the time bindings ran.
[oc:bind] Finished processing root modules. [oc:bind] Bind Result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Bind result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Successfully processed modules: [oc:bind] | UNSET#my-sip-example-feature#trunk;1.0.0-DEV6-davidf [oc:bind] | |__ ModuleBindResult{resultParts=[bindings installed, bindings applied for service ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3], service copied copy source 'ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3]', new copy 'ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3-copy#1]']} [oc:bind] --------------------------------------------------------------------- [oc:bind] --------------------------------------------------------------------- [oc:bind] | Created service copies: [oc:bind] | ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3-copy#1] [oc:bind] | |__ copied from ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3] [oc:bind] --------------------------------------------------------------------- [oc:bind] All modules bound successfully.
If the service is active at the time bindings are attempted to be applied, Rhino will fail to apply the bindings. The Binder will report an error like the following:
[oc:bind] Bind Result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Bind result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Failed modules: [oc:bind] | UNSET#my-sip-example-feature#trunk;1.0.0-DEV6-davidf [oc:bind] | |__ ModuleBindResult{resultParts=[bindings failure: Failed to bind module UNSET#my-sip-example-feature#trunk;1.0.0-DEV6-davidf in Rhino. [oc:bind] | Cause: com.opencloud.sleedeployer.binder.BindingFailedException: Failed to process module UNSET#my-sip-example-feature#trunk;1.0.0-DEV6-davidf, because the fail_if_active strategy was chosen, and the target service ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3] was active. Try using the copy_if_active or upgrade_if_active strategies, by setting the Ant property slee.binder.service-strategy. E.g. add this line to your build properties to use the copy_if_active strategy: [oc:bind] | slee.binder.service-strategy=copy_if_active
The binder has two strategies that it can apply, these are copy_if_active and upgrade_if_active.
-
The copy_if_active strategy creates a copy of the active service, and applies bindings to the copy.
The new service copy remains inactive, and the active version remains active. -
The upgrade_if_active strategy creates a copy of the active service, and applies bindings to the copy.
It then atomically deactivates the active version and actives the new copy.
In order to pass a strategy from the command line use the following command:
ant -Dslee.binder.service-strategy=copy_if_active bind-with-deps
Binder Dry Run
The binder supports a dry-run option that output a list of potential changes the bind commands would have if run without dry-run enabled. This option will have no effect on the state of Rhino.
In order to run the binder with dry-run enabled from the command line use the following command:
ant -Dslee.binder.dry-run=true bind-with-deps
The following message is output by the binder:
[oc:bind] Finished processing root modules. [oc:bind] Bind Result: [oc:bind] --------------------------------------------------------------------- [oc:bind] | Bind result (dry run mode): [oc:bind] --------------------------------------------------------------------- [oc:bind] | Successfully processed modules: [oc:bind] | UNSET#my-sip-example-feature#trunk;1.0.0-DEV6-davidf [oc:bind] | |__ ModuleBindResult{resultParts=[bindings installed, bindings applied for service ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3.2]]} [oc:bind] --------------------------------------------------------------------- [oc:bind] --------------------------------------------------------------------- [oc:bind] All modules bound successfully.
Viewing bindings inside Rhino
Once bindings have been successfully applied, the rhino-console program can be used to inspect bindings.
In order to see service copies, use the 'listservices' command. The following output is generated when binding a feature to the "sentinel.sip" service:
[Rhino@localhost (#0)] listservices ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3-copy#1] ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3] ServiceID[name=sentinel.subscription,vendor=OpenCloud,version=2.3]
There is a service with -copy#1 present. This service copy was created by Rhino when applying bindings.
If there have been multiple passes by the binder, there may be many copies present, e.g. 'copy-#2', '-copy#3' and so on.
|
The 'getdescriptor' command has been added to enable inspection of components, whether they have bindings applied or not. Rhino terms components that were installed and have not had any bindings applied as "Original components".
Comparing an "Original" service vs a copy is shown below:
[Rhino@localhost (#1)] getdescriptor service name=sentinel.sip,vendor=OpenCloud,version=2.3 For component ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3]: Deployable unit: DeployableUnitID[url=file:modules/opencloud/sentinel-sip-service-build-2.3.0-TRUNK.0-M2-SNAPSHOT.r87525.jar] Component source: service.xml Defined using SLEE version: 1.1 Checksum: 0xc20ac4279fa2c78d3ba1c7fd8a1c72c66a118b11 Install level: DEPLOYED Copies made from this component: ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3-copy#1] Root sbb: SbbID[name=sentinel.sip,vendor=OpenCloud,version=2.3] Address profile table: none This component is a dependent of: none [Rhino@localhost (#2)] getdescriptor service name=sentinel.sip,vendor=OpenCloud,version=2.3-copy#1 For component ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3-copy#1]: Copied from: ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3] Copy date: Fri Nov 07 14:47:41 NZDT 2014 Original component: ServiceID[name=sentinel.sip,vendor=OpenCloud,version=2.3] Copies made from this component: none Install level: VERIFIED Root sbb: SbbID[name=sentinel.sip,vendor=OpenCloud,version=2.3-copy#1] Address profile table: none This component is a dependent of: none
The service with suffix -copy#1 has been copied from the original.
The copied service has a different Root SBB than the original.
|
The 'getdescriptor' command can again be used to view the descriptors of the original vs copied root SBB.
When inspecting a Sentinel Root SBB,
When POJO features are bound, the new Root SBB has an additional SBB part reference. Each POJO feature has one SBB part reference. When SBB features are bound, each new SBB feature will cause the new Root SBB to have: |
-
a new Child SBB and SBB alias reference, and
-
a new SBB Part reference to the generated 'Feature SBB instantiator'.
The 'Feature SBB instantiator' is a component that is generated by the build system. The reason for its existence is to avoid any reflection during runtime.
Unbinding components
Component binding can be undone. This is referred to as 'unbinding'.
There are two targets to unbind modules, these are unbind and unbind-all.
The unbind target functions on a single module, based on the current working directory.
cd module-dir ant unbind
Its behaviour is to unapply the bindings from any Services, and then to undeploy the bindings descriptor from Rhino.
The unbind-all target functions on a directory structure of modules, looking for all modules that are located in subdirectories of the current working directory. It then invokes unbind on each. It is often used in conjunction with bind-with-deps for group modules that a user has defined themselves.
cd module-dir ant unbind-all