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.

Note 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
target/generated/sbbpart-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:

  1. @BinderTargets annotations, declaring the targeted Sentinel services, or

  2. @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, volte.sentinel.ss7

sip

sentinel.sip, volte.sentinel.sip, sentinel.ipsmgw

sip.charge

sentinel.sip, volte.sentinel.sip

sip.test

sentinel.sip, volte.sentinel.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

volte.sentinel.sip

ims.gsm

volte.sentinel.sip

mmtel

volte.sentinel.sip

mmtel.conference

volte.sentinel.sip

scc

volte.sentinel.sip

scc.gsm

volte.sentinel.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.

binder diagram

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.

  1. 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.

  2. 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]
Note 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
Note 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,

Note 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:
  1. a new Child SBB and SBB alias reference, and

  2. 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
Previous page Next page