Rhino Extended APIs
TAS-006-Issue 2.5.0-Release 1
September 2018
Rhino Extended APIs (V2.5.0)
Notices
Copyright © 2017 Metaswitch Networks. All rights reserved.
This manual is issued on a controlled basis to a specific person on the understanding that no part of the Metaswitch Networks product code or
documentation (including this manual) will be copied or distributed without prior agreement in writing from Metaswitch Networks.
Metaswitch Networks reserves the right to, without notice, modify or revise all or part of this document and/or change product features or
specifications and shall not be responsible for any loss, cost, or damage, including consequential damage, caused by reliance on these materials.
Metaswitch and the Metaswitch logo are trademarks of Metaswitch Networks. Other brands and products referenced herein are the trademarks or
registered trademarks of their respective holders.
2
Rhino Extended APIs (V2.5.0)
Contents
1 Rhino Extended APIs...................................................................................................................................................... 10
1.1 Topics......................................................................................................................................................................................................... 10
2 Bindings........................................................................................................................................................................... 11
2.1 Dynamic component reference bindings.................................................................................................................................................... 11
2.2 Install levels................................................................................................................................................................................................ 12
2.3 Component copy.........................................................................................................................................................................................16
2.4 Dynamic dependency specification............................................................................................................................................................ 18
2.4.1 Binding descriptor format.............................................................................................................................................................. 18
2.4.2 Managing binding descriptors....................................................................................................................................................... 19
2.4.3 Binding descriptor application....................................................................................................................................................... 20
2.4.4 Service binding capabilities...........................................................................................................................................................21
2.4.5 Binding conflicts............................................................................................................................................................................ 22
2.4.6 Associating a binding with a service............................................................................................................................................. 22
3 CMP Field Enhancements...............................................................................................................................................25
3.1 Array support.............................................................................................................................................................................................. 25
3.2 Serialization enhancements........................................................................................................................................................................25
3.2.1 FastSerializable............................................................................................................................................................................ 26
FastSerialize............................................................................................................................................................................... 27
Example...................................................................................................................................................................................... 27
3.2.2 Encodable..................................................................................................................................................................................... 28
EncoderUtils / DecoderUtils........................................................................................................................................................ 29
Example...................................................................................................................................................................................... 30
3
Rhino Extended APIs (V2.5.0)
3.2.3 Datatype codecs........................................................................................................................................................................... 31
Examples.................................................................................................................................................................................... 32
3.2.4 Encodable context........................................................................................................................................................................ 34
Encodable context definition....................................................................................................................................................... 34
Encodable context provider.........................................................................................................................................................35
3.2.5 Codecs for Java collection types.................................................................................................................................................. 37
Encodable collections................................................................................................................................................................. 37
Datatype codecs for collections.................................................................................................................................................. 40
3.2.6 Predefined datatype codecs......................................................................................................................................................... 41
3.3 Initial values................................................................................................................................................................................................ 42
3.3.1 Initial value fields...........................................................................................................................................................................42
Examples.................................................................................................................................................................................... 43
3.4 Pass-by-reference...................................................................................................................................................................................... 44
3.4.1 Reference scopes......................................................................................................................................................................... 44
Declaration.................................................................................................................................................................................. 45
Additional considerations............................................................................................................................................................ 46
3.5 CMP extension interfaces...........................................................................................................................................................................47
3.6 Arbitrary CMP fields....................................................................................................................................................................................50
3.7 The CMPFields interface............................................................................................................................................................................ 51
3.7.1 CMPFields object..........................................................................................................................................................................54
4 Miscellaneous SLEE Application API Enhancements..................................................................................................55
4.1 SbbContext interface extensions................................................................................................................................................................ 55
4.1.1 RhinoSbbContext interface getConvergenceName method......................................................................................................... 56
4.1.2 RhinoSbbContext interface getTracer method..............................................................................................................................56
4.1.3 RhinoSbbContext interface getActivities methods........................................................................................................................ 57
4
Rhino Extended APIs (V2.5.0)
4.1.4 RhinoSbbContext interface getChildRelationFacility method....................................................................................................... 57
4.1.5 RhinoSbbContext interface getCMPFields method...................................................................................................................... 57
4.1.6 RhinoSbbContext interface getJndiBindings method....................................................................................................................57
4.1.7 RhinoSbbContext interface setServiceContext and getServiceContext methods.........................................................................58
4.1.8 RhinoSbbContext interface setEncodableContext method...........................................................................................................58
4.2 Activity context Suspend/Resume Delivery extensions.............................................................................................................................. 59
4.2.1 RhinoActivityContextInterface interface suspendDelivery methods..............................................................................................60
4.2.2 RhinoActivityContextInterface interface resumeDelivery methods............................................................................................... 61
4.2.3 RhinoActivityContextInterface interface isSuspended methods................................................................................................... 62
4.2.4 Relationship to event context suspend/resume............................................................................................................................ 62
4.3 SBB local home interface........................................................................................................................................................................... 63
4.3.1 How to get an SBB local home object...........................................................................................................................................63
4.3.2 The RhinoSbbLocalHome interface.............................................................................................................................................. 63
4.3.3 SBB service lifecycle callbacks.....................................................................................................................................................64
4.3.4 RhinoSbbLocalHome interface verifyConfiguration method......................................................................................................... 64
4.3.5 RhinoSbbLocalHome interface serviceActivating method............................................................................................................ 65
4.3.6 RhinoSbbLocalHome interface serviceDeactivating method........................................................................................................ 66
4.3.7 Lifecycle callback method invocation cascade............................................................................................................................. 66
4.4 Unchecked throwable propagation............................................................................................................................................................. 67
5 SBB Parts......................................................................................................................................................................... 68
5.1 What are SBB parts?.................................................................................................................................................................................. 68
5.2 SBB part components.................................................................................................................................................................................68
5.3 SBBs and SBB parts...................................................................................................................................................................................69
5.4 SBB part objects......................................................................................................................................................................................... 70
5.4.1 SBB part object lifecycle............................................................................................................................................................... 71
5
Rhino Extended APIs (V2.5.0)
5.5 SBB part class............................................................................................................................................................................................ 73
5.5.1 Lifecycle methods......................................................................................................................................................................... 73
Constructor..................................................................................................................................................................................74
@PreDispose.............................................................................................................................................................................. 74
@PostCreate...............................................................................................................................................................................75
@OnActivate............................................................................................................................................................................... 76
@OnPassivate............................................................................................................................................................................ 76
@PreRemove..............................................................................................................................................................................77
@PostLoad................................................................................................................................................................................. 78
@PreStore.................................................................................................................................................................................. 78
5.5.2 Event handler methods................................................................................................................................................................. 79
5.5.3 Initial event selector methods....................................................................................................................................................... 80
5.5.4 Exception callback method........................................................................................................................................................... 81
RuntimeException handling for transactional methods............................................................................................................... 82
RuntimeException handling for non-transactional methods........................................................................................................82
5.5.5 Transaction rollback processing................................................................................................................................................... 83
5.5.6 Method name restrictions..............................................................................................................................................................83
5.5.7 Dependency injection....................................................................................................................................................................83
5.5.8 SBB abstract class abstract method replacements...................................................................................................................... 84
Per-instance state....................................................................................................................................................................... 84
Activity context interface narrow method.................................................................................................................................... 85
Child relations............................................................................................................................................................................. 85
Profile CMP interface accessor method......................................................................................................................................85
Usage parameters interface accessor methods..........................................................................................................................85
Fire event methods..................................................................................................................................................................... 86
6
Rhino Extended APIs (V2.5.0)
5.6 SbbPartContext interface............................................................................................................................................................................86
5.6.1 Methods inherited from SbbContext............................................................................................................................................. 86
5.6.2 SbbPartContext interface getSbbPart method..............................................................................................................................86
5.6.3 SbbPartContext interface getTracer method................................................................................................................................ 86
5.6.4 SbbPartContext interface asSbbPartActivityContextInterface method......................................................................................... 87
5.6.5 SbbPartContext interface getActivities methods...........................................................................................................................87
5.6.6 SbbPartContext interface getConvergenceName method............................................................................................................88
5.6.7 SbbPartContext interface getCMPFields method......................................................................................................................... 88
5.6.8 SbbPartContext interface getJndiBindings method...................................................................................................................... 88
5.7 SBB part component environment..............................................................................................................................................................88
5.8 SBB part example.......................................................................................................................................................................................88
6 SLEE Facilities................................................................................................................................................................. 90
6.1 SBB child relations......................................................................................................................................................................................90
6.1.1 Extended child relation declarations............................................................................................................................................. 90
6.1.2 Child Relation Facility................................................................................................................................................................... 91
ChildRelationFacility interface.....................................................................................................................................................91
6.1.3 ChildRelationFacility interface getChildRelationNames method...................................................................................................92
6.1.4 ChildRelationFacility interface getChildRelation method.............................................................................................................. 93
6.1.5 ChildRelationFacility interface getChildSbbs methods................................................................................................................. 93
6.1.6 ChildRelationFacility interface getChildSbbLocalHome method...................................................................................................93
6.2 Usage extensions....................................................................................................................................................................................... 94
6.2.1 Usage parameter types.................................................................................................................................................................94
6.2.2 Usage parameter sets...................................................................................................................................................................94
6.3 Usage parameter set types.........................................................................................................................................................................95
6.4 Aggregation and extension......................................................................................................................................................................... 95
7
Rhino Extended APIs (V2.5.0)
6.5 Usage parameters interfaces......................................................................................................................................................................96
6.6 Counter-type usage parameter set method................................................................................................................................................ 97
6.7 UsageParametersInterface interface.......................................................................................................................................................... 98
6.7.1 UsageParametersInterface interface name method..................................................................................................................... 99
6.7.2 UsageParametersInterface interface type method....................................................................................................................... 99
6.7.3 UsageParametersInterface interface key method.........................................................................................................................99
6.7.4 UsageParametersInterface interface getOrCreateChild methods................................................................................................ 99
6.7.5 UsageParametersInterface interface hasChild method................................................................................................................ 99
6.7.6 UsageParametersInterface interface children method................................................................................................................100
6.7.7 UsageParametersInterface interface parent method.................................................................................................................. 100
6.7.8 UsageParametersInterface interface remove method................................................................................................................ 100
6.8 Annotations...............................................................................................................................................................................................100
6.8.1 @UsageParameters annotation..................................................................................................................................................100
6.8.2 @UsageCounter annotation....................................................................................................................................................... 101
6.8.3 @UsageSample annotation........................................................................................................................................................ 102
6.9 SBB usage parameters interface deployment descriptor......................................................................................................................... 103
6.10 Resource adaptor usage parameters interface deployment descriptor.................................................................................................. 105
6.11 Usage facility.......................................................................................................................................................................................... 106
6.11.1 UsageFacility interface..............................................................................................................................................................106
6.11.2 UsageFacility interface getRootUsageParameterSet method.................................................................................................. 108
6.11.3 UsageFacility interface getUsageParameterSet method.......................................................................................................... 108
6.11.4 UsageFacility interface getOrCreateChild methods..................................................................................................................108
6.11.5 UsageFacility interface hasChild method..................................................................................................................................109
6.11.6 UsageFacility interface getChildren method............................................................................................................................. 109
6.11.7 UsageFacility interface removeUsageParameterSet method................................................................................................... 109
8
Rhino Extended APIs (V2.5.0)
6.12 Profile facility extensions........................................................................................................................................................................ 109
6.12.1 ProfileFacility interface..............................................................................................................................................................110
6.12.2 ProfileFacility interface profileTableExists method................................................................................................................... 110
6.12.3 ProfileFacility interface getProfileTableDescriptor method....................................................................................................... 110
6.12.4 ProfileFacility interface ProfileTableDescriptor interface.......................................................................................................... 111
6.12.5 ProfileFacility interface getProfileSpecification method............................................................................................................ 111
6.12.6 ProfileFacility interface getProfileTableInterface method..........................................................................................................111
6.12.7 ProfileFacility interface getProfileLocalInterface method.......................................................................................................... 112
6.13 Tracer extensions................................................................................................................................................................................... 112
6.13.1 Tracer interface.........................................................................................................................................................................112
6.13.2 Tracer interface getParentTracer method.................................................................................................................................112
6.13.3 Tracer interface getChildTracer method................................................................................................................................... 113
6.14 Lock Facility............................................................................................................................................................................................ 113
6.15 JNDI environment metadata................................................................................................................................................................... 115
6.15.1 JndiBinding class...................................................................................................................................................................... 116
6.15.2 JndiBinding class getType method........................................................................................................................................... 117
6.15.3 JndiBindingclass getJndiName method.................................................................................................................................... 117
6.15.4 JndiBindingclass getValue method........................................................................................................................................... 117
6.15.5 Subclasses of JndiBinding........................................................................................................................................................ 118
6.15.6 EnvEntry class.......................................................................................................................................................................... 118
6.15.7 Facility class..............................................................................................................................................................................118
6.15.8 LimiterEndpoint class................................................................................................................................................................118
6.15.9 ResourceAdaptorTypeBinding class.........................................................................................................................................119
6.15.10 ActivityContextInterfaceFactoryBinding class......................................................................................................................... 119
6.15.11 ResourceAdaptorEntityBinding class......................................................................................................................................120
9
Rhino Extended APIs (V2.5.0)
1 Rhino Extended APIs
This document provides API-level details for developers to extend SLEE services and OpenCloud Sentinel features.
Introduced in Rhino 2.4.0
1.1 Topics
Bindings
CMP Field Enhancements
Miscellaneous SLEE Application API Enhancements
SBB Parts
SLEE Facilities
Other documentation for the Rhino TAS can be found on the Rhino TAS product page .
10
Rhino Extended APIs (V2.5.0)
2 Bindings
Rhino has a dynamic approach on page 11 to dependency specification and binding, supported by multiple install levels on page 12 for
components, virtual copy on page 16 of installed components, and dependency specification on page 18 and application.
2.1 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 on page 12 for components
• virtual copy on page 16 of installed components
• dependency specification on page 18 and application.
Each of these concepts is described in detail below.
11
Rhino Extended APIs (V2.5.0)
2.2 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 rhino-console :
[Rhino@localhost:2199 (#0)] installlocaldu /path/to/deployable-unit.jar -installlevel INSTALLED Installed: DeployableUnitID[url=file:/path/to/deployable-unit.jar]
The -installlevel parameter is optional. If an install level is not specified when a deployable unit isinstalled, an install level of DEPLOYED is assumed.
Verify an installed
component
An installed component can subsequently be verified using the verify management operation. For example,
using rhino-console :
12
Rhino Extended APIs (V2.5.0)
[Rhino@localhost:2199 (#0)] verify sbb name=MySBB,vendor=OpenCloud,version=1.0 SbbID[name=MySBB,vendor=OpenCloud,version=1.0] verified The following components were also verified: ProfileSpecificationID[name=MyProfileSpec,vendor=OpenCloud,version=1.0] LibraryID[name=MyLibrary,vendor=OpenCloud,version=1.0]
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 on page
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 rhino-
console :
[Rhino@localhost:2199 (#0)] verify du file:/path/to/deployable-unit.jar Deployable unit file:/path/to/deployable-unit.jar verified The following components were verified: SbbID[name=MySBB,vendor=OpenCloud,version=1.0] ProfileSpecificationID[name=MyProfileSpec,vendor=OpenCloud,version=1.0] LibraryID[name=MyLibrary,vendor=OpenCloud,version=1.0]
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 deploy management operation. For example, using rhino-console :
[Rhino@localhost:2199 (#0)] deploy sbb name=MySBB,vendor=OpenCloud,version=1.0 SbbID[name=MySBB,vendor=OpenCloud,version=1.0] deployed No other components were affected by this operation
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
on page 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.
13
Rhino Extended APIs (V2.5.0)
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 rhino-console , for example, as follows:
[Rhino@localhost:2199 (#0)] deploy du file:/path/to/deployable-unit.jar Deployable unit file:/path/to/deployable-unit.jar deployed The following components were deployed: SbbID[name=MySBB,vendor=OpenCloud,version=1.0] deployed
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
VERIFIED install level. Dynamic changes to a component’s bindings cannot be made while a component is
DEPLOYED ; therefore it is necessary to undeploy a component if it is currently deployed and its bindings need to
be changed.
A deployed component is undeployed using the undeploy management operation. For example, using rhino-
console :
[Rhino@localhost:2199 (#0)] undeploy service name=MyService,vendor=OpenCloud,version=1.0 ServiceID[name=MyService,vendor=OpenCloud,version=1.0] undeployed No other components were affected by this operation
If there are any components that depend on the component being undeployed that themselves have an install level
of DEPLOYED , then those components too will also be undeployed by this operation, and so on recursively. ( See
the note about install levels on page below. )
An undeploy operation will fail if any component that would be affected by the operation does not satisfy the below
requirements:
• A service component can only be undeployed if it is in the INACTIVE state.
• A profile specification component can only be undeployed if there are no profile tables created from it
currently in existence.
14
Rhino Extended APIs (V2.5.0)
• A resource adaptor component can only be undeployed if there are no resource adaptor entities
created from it currently in existence.
Unverify a component A verified or deployed component can subsequently be unverified. When a component is unverified it reverts
to the INSTALLED install level. If the component was deployed then it is undeployed first. Dynamic changes
to a component’s bindings cannot be made while a component install level is not INSTALLED . Rhino will
automatically unverify (but not undeploy) a verified component affected by a binding operation; however the
unverify management operation exists to allow this transition to be manually controlled. Manually unverifying a
component is also necessary if, for example, dependent linked or shadowed components need to be updated.
A component is unverified using the unverify management operation. For example, using rhino-console :
[Rhino@localhost:2199 (#0)] unverify service name=MyService,vendor=OpenCloud,version=1.0 ServiceID[name=MyService,vendor=OpenCloud,version=1.0] unverified No other components were affected by this operation
If there are any components that depend on the component being unverified that themselves have an install
level of VERIFIED or DEPLOYED , then those components too will also be unverified by this operation, and so on
recursively. ( See the note about install levels on page below. )
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.
15
Rhino Extended APIs (V2.5.0)
2.3 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 copyComponent management operation. For example, using rhino-cons
ole :
[Rhino@localhost:2199 (#0)] help copycomponent copycomponent <type> <source-id> <target-name> <target-vendor> <target-version> [-installlevel <level>] Make a copy of the source component with the target identity. The -installlevel option controls to what degree the copied component is installed after it is created [Rhino@localhost:2199 (#1)] copycomponent sbb name=MySBB,vendor=OpenCloud,version=1.0 MySBB OpenCloud 1.0.1 Component SbbID[name=MySBB=OpenCloud,version=1.0] copied to SbbID[name=MySBB,vendor=OpenCloud,version=1.0.1]
The install level of the copied component can optionally be specified when the copy is made. If not specified, a
default install level of DEPLOYED is used. Specifying an install level of INSTALLED is typically most efficient when
making a copy of a component for use in a later binding operation, and is necessary when copying a component
that itself will not pass verification checks.
Show copy history A copied component may be subsequently copied again, leading to the treelike structure of copies branching
out from the original. The ComponentDescriptorExtensions class in rhino-management included in a
component’s metadata descriptor provides information about the source of a component and what copies have
16
Rhino Extended APIs (V2.5.0)
been made of it. The getdescriptor command in rhino-console reports this information, as shown in the
example below:
[Rhino@localhost:2199 (#0)] getdescriptor sbb name=MySBB,vendor=OpenCloud,version=1.0 For component SbbID[name=MySBB,vendor=OpenCloud,version=1.0]: Deployable unit: DeployableUnitID[url=file:/path/to/deployable-unit.jar] Component source: my-sbb.jar Defined using SLEE version: 1.1 ... Copies made from this component: SbbID[name=MySBB,vendor=OpenCloud,version=1.0.1] ... [Rhino@localhost:2199 (#1)] getdescriptor sbb name=MySBB,vendor=OpenCloud,version=1.0.1 For component SbbID[name=MySBB,vendor=OpenCloud,version=1.0.1]: Copied from: SbbID[name=MySBB,vendor=OpenCloud,version=1.0] ... Original component: SbbID[name=MySBB,vendor=OpenCloud,version=1.0] Copies made from this component: none ...
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 removeCopiedComponents management operation. For example, in
rhino-console :
[Rhino@localhost:2199 (#0)] help removecopiedcomponents removecopiedcomponents [<type> <url|component-id>]* Remove components that have been copied from another component. Either individual components or a single deployable unit identifier can be specified. In the latter case, all copied components of the DU will be removed [Rhino@localhost:2199 (#1)] removecopiedcomponents sbb name=MySBB,vendor=OpenCloud,version=1.0.1 1 component removed (or) [Rhino@localhost:2199 (#2)] removecopiedcomponents du file:/path/to/deployable-unit.jar The following copied components were removed: SbbID[name=MySBB,vendor=OpenCloud,version=1.0.1]
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 findOrphanedCopiedComponents command in rhino-console
can be helpful in finding these components, as shown in the example below:
[Rhino@localhost:2199 (#0)] help findorphanedcopiedcomponents findorphanedcopiedcomponents Find copied components that are no longer referenced by any other component. Components such as services and resource adaptors that sit at
17
Rhino Extended APIs (V2.5.0)
the top of the dependency hierarchy are not included [Rhino@localhost (#1)] findorphanedcopiedcomponents Copied components not used by any other component: SbbID[name=MySBB,vendor=OpenCloud,version=1.0.2] ...
2.4 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.
2.4.1 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 , and version 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.
18
Rhino Extended APIs (V2.5.0)
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" } }}
2.4.2 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 rhino-console :
[Rhino@localhost:2199 (#0)] install file:/path/to/my-binding-descriptor.json -type bindings Installed: DeployableUnitID[url=file:/path/to/my-binding-descriptor.json]
Install levels on page 12 are not relevant for binding descriptors. Any install level specified when a binding
descriptor is installed is ignored.
An installed binding descriptor document is a deployable unit that contains one binding descriptorcomponent with an identity as specified by the name , vendor , and version properties in the JSON
19
Rhino Extended APIs (V2.5.0)
document. Binding descriptor components do not support Component copy on page 16 operations,as such an operation has little meaning.
Uninstall a binding
descriptor
An installed binding descriptor can be uninstalled in the same way as any other SLEE deployable unit. For
example, using rhino-console :
[Rhino@localhost:2199 (#1)] uninstall file:/path/to/my-binding-descriptor.json uninstalled: DeployableUnitID[url=file:/path/to/my-binding-descriptor.json]
2.4.3 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 on page 12 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 on page 16 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.
20
Rhino Extended APIs (V2.5.0)
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.
2.4.4 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 on page 90
• adding new CMP extension interfaces on page 47
• adding new extension usage parameters interfaces on page 94
• 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 on page 47
• adding new extension usage parameters interfaces on page 94
• 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.
21
Rhino Extended APIs (V2.5.0)
Due to classloader limitations, a profile specification can only have its bindings modified if there are no profile tables, resource adaptorentities, or services with an install level of DEPLOYED , that depend on any profile specification in the same profile specificationcomponent jar present in the SLEE. Attempting to change the bindings of a profile specification that does not meet this criteria willresult in the failure of the binding operation.
2.4.5 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 bindingdescriptor specifies an extends type for X . In this case, the SLEE assumes that X should now extend thespecified 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.
2.4.6 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 addBindings operation defined on the ServiceMan
agementMBean . This operation may be invoked in rhino-console , for example, as shown below:
[Rhino@localhost:2199 (#0)] help addservicebinding addservicebinding <service-id> [-binding <binding-descriptor-id>]* [-mapping <map-name>] [-dryrun] Add one or more bindings to a service. The -mapping option specifies a component mapping
22
Rhino Extended APIs (V2.5.0)
created with the createbindingcomponentmap command. The -dryrun option will display the affects the binding operation will make but will not actually commit the changes
The example below associates a binding descriptor with a service:
[Rhino@localhost:2199 (#0)] addservicebinding name=MyService,vendor=OpenCloud,version=1.0 -binding name=MyBinding,vendor=OpenCloud,version=1.0 Bindings added to service ServiceID[name=MyService,vendor=OpenCloud,version=1.0] The following new components were created: SbbID[name=MySbb,vendor=OpenCloud,version=1.0-copy#1] ServiceID[name=MyService,vendor=OpenCloud,version=1.0-copy#1] No components were removed
Create mappings The -mapping argument can be used to specify the target component identifiers of copied components, rather
than have Rhino autogenerate them. In rhino-console such a map is managed using the following additional
commands:
createbindingcomponentmap <map-name> Create a component mapping that can be used with the addservicebinding command. Mappings can be added using the addbindingcomponentmapping command. Created mappings exist only in the client, and will be lost when the client terminates removebindingcomponentmap <map-name> Remove an existing bindings component mapping listbindingcomponentmaps List the current bindings component maps addbindingcomponentmapping <map-name> <source-id> <target-name> <target-vendor> <target-version> Add a bindings mapping from the source component to the target identity removebindingcomponentmapping <map-name> <source-id> Remove a bindings component mapping dumpbindingcomponentmap <map-name> Dump the current mappings in the specified bindings component maps
The following example creates a mapping and uses it to control the component identifier of the SBB copied by the
binding operation:
[Rhino@localhost:2199 (#1)] createbindingcomponentmap mymap Bindings component mapping mymap created [Rhino@localhost:2199 (#2)] addbindingcomponentmapping mymap sbb name=MySbb,vendor=OpenCloud,version=1.0 MySbb OpenCloud 1.0.1 Mapping SbbID[name=MySbb,vendor=OpenCloud,version=1.0] -> SbbID[name=MySbb,vendor=OpenCloud,version=1.0.1] added to mapping mymap [Rhino@localhost:2199 (#3)] dumpbindingcomponentmap mymap Component mappings for mymap: SbbID[name=MyS
23
Rhino Extended APIs (V2.5.0)
bb,vendor=OpenCloud,version=1.0] -> SbbID[name=MySbb,vendor=OpenCloud,version=1.0.1] [Rhino@localhost:2199 (#4)] addservicebinding name=MyService,vendor=OpenCloud,version=1.0 -binding name=MyBinding,vendor=OpenCloud,version=1.0 -mapping mymap Bindings added to service ServiceID[name=MyService,vendor=OpenCloud,version=1.0] The following new components were created: SbbID[name=MySbb,vendor=OpenCloud,version=1.0.1] ServiceID[name=MyService,vendor=OpenCloud,version=1.0-copy#2] No components were removed
As part of a binding operation, the service and all its dependent components transition to theVERIFIED install level. This means that the addition (or removal) of a binding to (or from) a servicemust leave the service in a state that will pass all SLEE verification checks. If any of these checks fail,then the binding operation will also fail.
Disassociate A binding descriptor can be disassociated from a service using the removeBindings operation defined on the
ServiceManagementMBean . This operation may be invoked in rhino-console , for example, as shown
below:
[Rhino@localhost:2199 (#0)] help removeservicebinding removeservicebinding <service-id> [-binding <binding-descriptor-id>]* [-dryrun] Remove one or more bindings from a service. The -dryrun option will display the affects the binding operation will make but will not actually commit the changes
An example of a binding descriptor being disassociated from a service is shown below:
[Rhino@localhost:2199 (#0)] removeservicebinding name=MyService,vendor=OpenCloud,version=1.0-copy#1 -binding name=MyBinding,vendor=OpenCloud,version=1.0 Bindings removed from service ServiceID[name=MyService,vendor=OpenCloud,version=1.0-copy#1] No new components were created The following components were no longer required and were removed: SbbID[name=MySbb,vendor=OpenCloud,version=1.0-copy#1] Service ServiceID[name=MyService,vendor=OpenCloud,version=1.0-copy#1] now has no bindings and may be removed if no longer required
24
Rhino Extended APIs (V2.5.0)
3 CMP Field Enhancements
This page provides an API for the following CMP field enhancements:
3.1 Array support
As an extension to the JAIN SLEE specification, Rhino supports CMP field declarations of arrays for the following SLEE-defined types:
• javax.slee.ActivityContextInterface , and any subclass of this interface
• javax.slee.SbbLocalObject , and any subclass of this interface
• If the abstract getter and setter methods for the CMP field are defined in the SBB abstract class (as opposed to a CMP
extension interface on page 47 ), the corresponding <cmp-field> declaration in the deployment descriptor may not
include an <sbb-alias-ref> element.
• javax.slee.EventContext
• javax.slee.profile.ProfileLocalObject , and any subclass of this interface.
Arrays may be declared with any dimension. Array support is automatic wherever the basic type is supported in CMP fields; in other words, no
user prompt or directive is necessary.
3.2 Serialization enhancements
Rhino introduces a number of enhancements that offer significantly more control and flexibility over how CMP field values are serialized, and much
better serialization performance, when compared with standard Java serialization. These include:
• FastSerializable on page 26
• Encodable on page 28
• Datatype codecs on page 31 .
25
Rhino Extended APIs (V2.5.0)
3.2.1 FastSerializable
The com.opencloud.util.FastSerializable interface provides a simple alternative to the standard Java java.io.Serializable
interface where the exact type of an object to be serialized is known at compile time.
The FastSerializable interface is defined as follows:
package com.opencloud.util;
public interface FastSerializable { public void toStream(java.io.DataOutput stream) throws java.io.IOException;}
A class implementing the FastSerializable interface must provide a public constructor that takes either:
• a single java.io.DataInput argument; or
• a java.io.DataInput argument and a java.lang.ClassLoader argument.
If both constructors are declared by a given class then the two-argument constructor is used.
Serialization of the object is performed by an invocation of the toStream method. Object state must be written to the DataOutput passed as the
input argument. Deserialization is performed by new object instantiation and constructor invocation. Object state can be read from the DataInput
argument. The ClassLoader argument, if present, can be used to resolve any application-specific classes stored in the stream.
Rhino recognises and supports the FastSerializable contract on all CMP fields. Arrays of FastSerializable types of any dimension are
handled automatically by Rhino, and no special treatment is necessary.
While the FastSerializable contract has some similarity to the java.io.Externalizable contract, there are some differences that warrant
discussion:
• FastSerializable operates in terms of data I/O streams, while Externalizable operates in terms of object I/O streams. The
reason for this is that FastSerializable desires to avoid the generally costly serialization overhead that occurs when serializing
arbitrary objects. By limiting the stream I/O to basic datatypes, it forces the user to think about the most performance-efficient manner
in which the object state can be serialized and deserialized.
26
Rhino Extended APIs (V2.5.0)
• When FastSerializable types are used in CMP fields, Rhino’s CMP implementation typically determines the type of object to
reconstruct during deserialization at code-generation time, not run time; so care must be taken that objects are restored using the
correct type. Problems occur, for example, if a CMP field is declared in terms of FastSerializable type Foo , but an object of
subclass Bar is stored in the CMP field. The CMP implementation assumes that the CMP field will only store a Foo object, and
will instantiate a Foo object when the CMP field is deserialized, leading to deserialization failures. Making classes that implement
FastSerializable final is good practice, unless this issue is taken into consideration.
• No handling of shared references is performed by the implementation. If the same object is encountered twice during serialization,
then two copies of the object will be stored and subsequently deserialized.
FastSerialize
The com.opencloud.util.FastSerialize class provides some utility functions that may be useful to application developers implementing
their own serialization logic based around FastSerializable .
Example
Below is an example of a FastSerializable type:
import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import com.opencloud.util.FastSerializable;
public final class Person implements FastSerializable { public Person(String firstName, String lastName, int age) { this.firstName = firstName; this.lastName = lastName; this.age = age; }
public Person(DataInput in, ClassLoader classLoader) throws IOException { firstName = in.readUTF(); lastName = in.readUTF(); age = in.readInt(); }
27
Rhino Extended APIs (V2.5.0)
@Override public void toStream(DataOutput out) throws IOException { out.writeUTF(firstName); out.writeUTF(lastName); out.writeInt(age); }
public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getAge() { return age; }
private final String firstName; private final String lastName; private final int age;}
3.2.2 Encodable
The com.opencloud.rhino.cmp.Encodable interface provides a similar contract to that of FastSerializable but is specifically targeted
at types stored in SBB CMP fields. It provides access to utility functions to encode and decode SLEE-specific datatypes that are not defined
as serializable, such as SBB and profile local object references, and an encodable context on page 34 that can be set by an SBB to pass
information to the encoding . decoding methods, such as references to resource adaptor provider objects.
The Encodable interface is defined as follows:
package com.opencloud.rhino.cmp;
import com.opencloud.rhino.cmp.codecs.EncoderUtils;
public interface Encodable { public void encode(java.io.DataOutput out, EncoderUtils utils) throws java.io.IOException;}
A class implementing the Encodable interface must provide a public constructor that takes, in this order: a java.io.DataInput argument, a
java.lang.ClassLoader argument, and a com.opencloud.rhino.cmp.codecs.DecoderUtils argument.
28
Rhino Extended APIs (V2.5.0)
Serialization of the object is performed by an invocation of the encode method. Object state must be written to the DataOutput passed as the
input argument. Deserialization is performed by new object instantiation and constructor invocation. Object state can be read from the DataInput
argument. The ClassLoader argument can be used to resolve any application-specific classes stored in the stream.
The constructor and encode methods of an Encodable type are always invoked with the same transaction context used to access or update the
CMP field. This is typically only of consequence if an encodable context is used to provide access to other SBB CMP fields.
EncoderUtils / DecoderUtils
SLEE-defined datatypes such as SBB and profile local objects, activity context interface objects, and event context objects are not defined by the
SLEE specification as being serializable. The SLEE specification does provide provision for storing objects of these types directly into CMP fields;
but the lack of implicit serializability means that, for example, an SBB local object reference cannot be encapsulated within some other object
which is stored into CMP, as object serialization will fail when it reaches the unserializable SBB local object reference.
The EncoderUtils object passed to the encode method provides access to methods that can serialize these SLEE-defined datatypes,
allowing classes that implement the Encodable contract to encapsulate objects of these datatypes and still be storable into CMP fields. The
corresponding DecoderUtils object passed to the decoding constructor provides access to methods that can deserialize these datatypes,
allowing correct object reconstruction during deserialization.
Rhino recognises and supports the Encodable contract on all CMP fields; however the utility methods provided by SleeDatatypeEncoder
and SleeDatatypeDecoder only function under certain conditions:
• Encode and decode of all SLEE-defined datatypes is supported for SBB and SBB Part on page 68 CMP fields.
• Encode and decode of EventContext objects is supported for Activity Context Interface attributes.
• Encode and decode of SLEE-defined datatypes is unsupported in any other case, and invoked methods will throw a
java.lang.UnsupportedOperationException .
Arrays of Encodable types of any dimension are handled automatically by Rhino, and no special treatment is necessary.
Unlike FastSerializable types, CMP fields that store Encodable types may, at runtime, store a subclass of the declared CMP field type
without issue. For example, if a CMP field is declared in terms of Encodable type Foo , an object of subclass Bar may be stored in the CMP field
and it will serialize and deserialize as expected. Deserialization is, however, more efficient if the type of the stored object is the same as the CMP
field type, as reflection must be used to reconstruct a stored object if the type of the stored object differs from the expected type.
29
Rhino Extended APIs (V2.5.0)
Like FastSerializable , no handling of shared references is performed by the implementation. If the same object is encountered twice during
serialization, then two copies of the object will be stored and subsequently deserialized.
Example
Below is an example of an Encodable type:
import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import javax.slee.ActivityContextInterface;import com.opencloud.rhino.cmp.Encodable;import com.opencloud.rhino.cmp.codecs.DecoderUtils;import com.opencloud.rhino.cmp.codecs.EncoderUtils;import com.opencloud.rhino.cmp.codecs.SleeDatatypeDecoder;import com.opencloud.rhino.cmp.codecs.SleeDatatypeEncoder;
public final class Relay implements Encodable { public Relay(IncomingSbbLocalObject incoming, OutgoingSbbLocalObject outgoing, ActivityContextInterface aci) { this.incoming = incoming; this.outgoing = outgoing; this.aci = aci; }
public Relay(DataInput in, ClassLoader classLoader, DecoderUtils utils) throws IOException { SleeDatatypeDecoder decoder = utils.getSleeDatatypeDecoder(); incoming = decoder.decodeSbbLocalObject(in); outgoing = decoder.decodeSbbLocalObject(in); aci = decoder.decodeActivityContextInterface(in); messageCount = in.readInt(); }
@Override public void encode(DataOutput out, EncoderUtils utils) throws IOException { SleeDatatypeEncoder encoder = utils.getSleeDatatypeEncoder(); encoder.encodeSbbLocalObject(incoming, out); encoder.encodeSbbLocalObject(outgoing, out); encoder.encodeActivityContextInterface(aci, out);
30
Rhino Extended APIs (V2.5.0)
out.writeInt(messageCount); }
public IncomingSbbLocalObject getIncomingSbb() { return incoming; } public OutgoingSbbLocalObject getOutgoingSbb() { return outgoing; } public ActivityContextInterface getActivityContextInterface() { return aci; }
public void incMessageCount() { messageCount++; } public int getMessageCount() { return messageCount; }
private final IncomingSbbLocalObject incoming; private final OutgoingSbbLocalObject outgoing; private final ActivityContextInterface aci; private int messageCount;}
3.2.3 Datatype codecs
The Encodable contract provides an in-line mechanism for object serialization. That is, code for serialization and deserialization forms part of
the class itself. There may be times, however, when it is desired or necessary for the serialization code to be separated from the class being
serialized. For example, the serialization logic may have common components that can be shared between multiple classes, or the source code
for the class being serialized may not be available to be enhanced to support the FastSerializable on page 26 or Encodable on page 28
serialization contracts.
To support these situations, Rhino allows a datatype codec to be defined and associated with either a CMP field or a serializable class directly.
The datatype codec specifies how objects of the target type are serialized and deserialized, essentially providing a third-person perspective to the
Encodable contract.
A datatype codec must implement the com.opencloud.rhino.cmp.codecs.DatatypeCodec interface. This interface is defined as follows:
package com.opencloud.rhino.cmp.codecs;
import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;
public interface DatatypeCodec<T> {
31
Rhino Extended APIs (V2.5.0)
public void encode(T value, DataOutput out, EncoderUtils utils) throws IOException; public T decode(DataInput in, ClassLoader classLoader, DecoderUtils utils) throws IOException;}
A datatype codec class must be public (and static, if an inner class) and implement a public no-argument constructor. The encode method
functions identically to the encode method defined by the Encodable interface, but takes the object to be serialized as an additional argument.
The decode method functions identically to the deserialization constructor required by the Encodable contract, but returns the deserialized
object as the method return result. The generic type parameter T identifies the type of object that the datatype codec is capable of serializing and
deserializing. Generally, a datatype codec does not need to concern itself with encoding or decoding null values, as Rhino will only invoke the
codec for non- null values. There is one exception to this rule, discussed in the Datatype codecs for collections on page 40 section below.
The encode and decode methods are always invoked with the same transaction context used to access or update the CMP field. This is typically
only of consequence if an encodable context on page 34 is used to provide access to other SBB CMP fields.
A datatype codec is associated with the corresponding datatype using the @DatatypeCodecType annotation. This annotation requires the
datatype codec class to be specified as an argument. The annotation can be used either directly on the target class to be serialized, or attached
to a CMP field getter or setter method. If attached to a CMP field getter or setter method of an array type, then the datatype codec need only be
defined in terms of the base array component type. The codec will be invoked for each non- null array element encountered during serialization
or deserialization.
Datatype codecs are supported on all CMP fields where Encodable types are supported, and have the same conditions of use.
The @DatatypeCodecType annotation may not be used on a CMP field getter or setter method where the CMP field is one of the following types,
or is an array of any dimension of one of the following types:
• javax.slee.ActivityContextInterface , and any subclass of this interface
• javax.slee.SbbLocalObject , and any subclass of this interface
• javax.slee.EventContext
• javax.slee.profile.ProfileLocalObject , and any subclass of this interface.
Examples
Below is an example of a datatype codec handling the serialization of class type Customer :
32
Rhino Extended APIs (V2.5.0)
import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import com.opencloud.rhino.cmp.codecs.DatatypeCodec;import com.opencloud.rhino.cmp.codecs.DecoderUtils;import com.opencloud.rhino.cmp.codecs.EncoderUtils;
public class CustomerCodec implements DatatypeCodec<Customer> { @Override public void encode(Customer value, DataOutput out, EncoderUtils utils) throws IOException { ... }
@Override public Customer decode(DataInput in, ClassLoader classLoader, DecoderUtils utils) throws IOException { return ... }}
The datatype codec can be associated directly with the Customer datatype by annotating the class itself as shown below:
@DatatypeCodecType(CustomerCodec.class)public class Customer ...
Alternatively, a CMP field storing a Customer object can be annotated to declare the datatype codec to be used for that CMP field, as shown
below:
public abstract class MySbb implements Sbb { ...
@DatatypeCodecType(CustomerCodec.class) public abstract void setCustomer(Customer customer); public abstract Customer getCustomer();}
The datatype codec can be equally used on a CMP field storing an array of Customer objects, as shown below:
33
Rhino Extended APIs (V2.5.0)
public abstract class MySbb implements Sbb { ...
@DatatypeCodecType(CustomerCodec.class) public abstract void setCustomers(Customer[] customers); public abstract Customer[] getCustomers();}
3.2.4 Encodable context
There are a number of use cases where serialization and/or deserialization of a CMP object requires access to resources that the Encodable on
page 28 and DatatypeCodec on page 31 encode and decode methods may not natively have access to. For example, deserialization of
a stored network message may require access to the owning resource adaptor provider object to reconstruct the correct object graph. To solve
this problem, Rhino defines the concept of an encodable context . An encodable context can provide access to the resources that the encode and
decode methods need in order to fulfill their function.
Encodable context definition
The encodable context required for any given Encodable or DatatypeCodec type may be defined as either a class or interface, though it
is strongly recommended that the context be defined as an interface. The reason for this is to allow the provider of the context to more easily
combine contexts required by multiple Encodable or DatatypeCodec types used in different CMP fields into a single implementation object.
An encodable context may provide read access to other CMP states, but should not provide write access to any CMP state. SLEE behaviour is
undefined if arbitrary CMP fields are modified during the encode or decode of another CMP field. Otherwise, there are no specific requirements or
restrictions about what an encodable context may provide access to.
Below is an example of an encodable context interface:
import org.jainslee.resources.diameter.ro.RoProviderFactory;
public interface RoProviderContext { public RoProviderFactory getRoProviderFactory(); public Tracer getTracer(); public int getSomeContextValue();}
34
Rhino Extended APIs (V2.5.0)
An Encodable or DatatypeCodec object obtains an encodable context object from the EncoderUtils argument passed to the encode
method, or from the DecoderUtils argument passed to the deserialization constructor (for Encodables ) or decode method (for
DatatypeCodecs ).
Encodable context provider
If an Encodable or DatatypeCodec type is a consumer of an encodable context, then there must be a corresponding provider of the context.
Only SBBs currently support providing an encodable context object for use by CMP fields declared by itself or any dependent SBB part. An SBB
sets the encodable context using the setEncodableContext method on its com.opencloud.rhino.slee.RhinoSbbContext object (a
Rhino extension of javax.slee.SbbContext ):
package com.opencloud.rhino.slee;
public interface RhinoSbbContext extends SbbContext { public <T> void setEncodableContext(T context) throws SLEEException;
...}
The encodable context object set by the SBB must implement all encodable context types expected by the Encodable or DatatypeCodec
types that it uses, so that each Encodable or DatatypeCodec type may typecast the object to the encodable context type that it expects.
An encodable context object is scoped to an SBB object; therefore the recommended place to initialise the encodable context is in the SBB’s
setSbbContext method.
Below is an example implementation of the RoProviderContext encodable context interface shown above:
import javax.naming.InitialContext;import javax.slee.Sbb;import javax.slee.SbbContext;import com.opencloud.rhino.slee.RhinoSbbContext;import org.jainslee.resources.diameter.ro.RoProviderFactory;
public abstract class MySbb implements Sbb { public void setSbbContext(SbbContext context) { RhinoSbbContext rhinoContext = (RhinoSbbContext)context;
35
Rhino Extended APIs (V2.5.0)
final RoProviderFactory roProviderFactory = new InitialContext().lookup(...); final Tracer encodableContextTracer = context.getTracer(...); rhinoContext.setEncodableContext(new RoProviderContext() { @Override public RoProviderFactory getRoProviderFactory() { // return provider factory from JNDI return roProviderFactory; } @Override public Tracer getTracer() { // return tracer for encode/decode methods to use return encodableContextTracer; } @Override public int getSomeContextValue() { // return value from SBB CMP return MySbb.this.getSomeContextValue(); } });
.... }
// cmp field declaration public abstract void setSomeContextValue(int value); public abstract int getSomeContextValue();
...}
Since other persistent entities, such as profiles and activity context interface objects, do not currently support the provision of an encodable
context object, Encodable or DatatypeCodec types that require an encodable context cannot be used with these persistent entities. The
getEncodableContext method defined in the EncoderUtils and DecoderUtils interfaces will always return null for these types of
persistent entities.
36
Rhino Extended APIs (V2.5.0)
3.2.5 Codecs for Java collection types
Rhino natively supports FastSerializable and Encodable types, and types using a DatatypeCodec , on array-type CMP fields. Each non-
null array element is individually serialized and deserialized as appropriate. However there are times when using a Java Collections Framework
type, such as List or Set in a CMP field, is preferable to using an array; but retaining the serialization benefits provided by the element type is
desired.
To answer this, Rhino provides a set of base classes that provides a framework for efficient serialization of Encodable on page 28 , List ,
Set , and Map types, and additional datatype codec annotations to simplify the common use cases.
Encodable collections
Rhino provides three base abstract classes to support efficiently serialized collections:
• com.opencloud.rhino.util.EncodableList — implements java.util.List and
com.opencloud.rhino.cmp.Encodable
• com.opencloud.rhino.util.EncodableSet — implements java.util.Set and
com.opencloud.rhino.cmp.Encodable
• com.opencloud.rhino.util.EncodableMap — implements java.util.Map and
com.opencloud.rhino.cmp.Encodable .
Each of these classes wraps an implementation of the corresponding collection type, and implements the Encodable contract to manage the
serialization and deserialization of that collection. To use any of these as a CMP field type, the application developer must implement a concrete
class extending from the relevant base class, taking into account the following rules and considerations.
Constructors
A concrete subclass must provide a public constructor satisfying the Encodable contract which delegates to the equivalent protected constructor
in the base class. The subclass should also provide at least one general user constructor that delegates to one of the base class public
constructors, such as the no-argument constructor. A subclass of EncodableList may also need to provide a constructor suitable for use with
the implementation of the abstract newInstance method.
37
Rhino Extended APIs (V2.5.0)
Implementation of writer / reader methods
A concrete subclass must provide the implementation of the abstract writer and reader methods defined by the base class. These methods are
responsible for the encoding and decoding of individual collection elements, map keys, or map values, as appropriate.
Implementation of EncodableList newInstance method
The java.util.List interface includes a method, subList , which returns a view of a portion of the source list. The EncodableList requires
that a subclass implements the newInstance method it defines to facilitate the implementation of this method. The newInstance method
should return a new instance of the concrete class which wraps the list provided by the method argument. Delegating to the EncodableList
constructor defined with the same arguments as the newInstance method is the recommended approach.
Managing null elements, keys, and values
The default implementation of EncodableList and EncodableSet assumes that null elements will not occur in the collection. The default
implementation of EncodableMap assumes that null keys will not occur in the map, but that null values might. The consequence of this is that
if a null element occurs in a list or set, or null key occurs in a map, then during serialization the corresponding writer method will be asked to
encode the null object. While this is not problematic, it means that the writer and reader methods need to perform additional work to handle the
presence of null objects in the stream they write to or read from.
To simplify the code required of the writer and reader methods when null objects are expected by a given datatype, a subclass may change
the default behaviour of the base class by overriding the manageNullElements method in EncodableList and EncodableSet , or the
manageNullKeys and manageNullValues methods in EncodableMap . If these methods return true , then the base class will check for null
objects of the corresponding type and handle them internally, only invoking the writer and reader methods for non- null objects. If null objects
are never expected, or not supported by the underlying backing store (or the writer and reader methods will handle null objects), then these
methods may return false , resulting in a slightly smaller serialization data stream that doesn’t include the extra information required for null
checks.
Below is an example of subclass of EncodableList that stores a list of strings with possible null elements:
import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import java.util.List;import com.opencloud.rhino.cmp.codecs.DecoderUtils;
38
Rhino Extended APIs (V2.5.0)
import com.opencloud.rhino.cmp.codecs.EncoderUtils;import com.opencloud.rhino.cmp.codecs.SimpleDatatypeCodecs;import com.opencloud.rhino.util.EncodableList;
public class StringList extends EncodableList<String> { // general user constructor // since we implicitly delegate to the default superclass constructor, // the underlying collection will be an ArrayList public StringList() {}
// constructor required by the Encodable contract public StringList(DataInput in, ClassLoader cl, DecoderUtils utils) throws IOException { super(in, cl, utils); }
// constructor used by newInstance() protected StringList(BackingStore backingStore, List<String> list) { super(backingStore, list); }
@Override protected StringList newInstance(BackingStore backingStore, List<String> list) { return new StringList(backingStore, list); }
@Override protected void writeElement(String element, DataOutput out, EncoderUtils utils) throws IOException { CODEC.encode(element, out, utils); }
@Override protected String readElement(DataInput in, ClassLoader cl, DecoderUtils utils) throws IOException { return CODEC.decode(in, cl, utils); }
@Override protected boolean manageNullElements() { // null elements are possible // tell the superclass to deal with them so we don't have to
39
Rhino Extended APIs (V2.5.0)
return true; }
// use predefined datatype codec for encode and decode private static final SimpleDatatypeCodecs.StringCodec CODEC = new SimpleDatatypeCodecs.StringCodec();}
Below is an example of a CMP field declared in terms of this datatype:
public abstract void setNames(StringList names);public abstract StringList getNames();
Datatype codecs for collections
In many use cases, the implementation of an Encodable collection type would look strikingly similar to the example shown in the previous
section. Most of the implementation code is boilerplate, even more so if the writer and reader methods simply delegate to another datatype codec
class. To simplify application development, Rhino provides an alternative through the use of annotations on the CMP field getter or setter method:
• An EncodableList implementation can be substituted with a @ListCodecType annotation.
• An EncodableSet implementation can be substituted with a @SetCodecType annotation.
• An EncodableMap implementation can be substituted with a @MapCodecType annotation.
These annotations have only two minor restrictions:
1. Element, key, and value encoding and decoding must be implemented using datatype codecs on page 31 .
2. Generic type parameters aside, an annotated CMP field must be declared in terms of the base collection interface type, that is:
java.util.List , java.util.Set , or java.util.Map , or an array of any dimension of this type.
• If the CMP field type is scalar, any implementation class of the declared CMP field type may be passed as a parameter to the
CMP field setter method, for example: a java.util.ArrayList or java.util.HashSet . However, no assumption can
be made about the type of object returned from the CMP field getter method, other than it implements the interface declared
as the CMP field type. For example, if the CMP field type is java.util.List , a java.util.ArrayList may be passed
to the CMP field setter method; but it cannot be assumed that a java.util.ArrayList will be returned from the CMP field
getter method.
40
Rhino Extended APIs (V2.5.0)
• If the CMP field type is an array, any implementation class of the base component type of the declared CMP field array
type may be passed as array elements. However, no assumption can be made about the type of objects returned as array
elements from the CMP field getter method, other than they implement the interface declared as the array base component
type.
Below is an example of how the StringList CMP field example from the previous section could be simplified by using the @ListCodecType
annotation:
@ListCodecType(codec = SimpleDatatypeCodecs.StringCodec.class, manageNullElements = true)public abstract void setNames(List<String> names);public abstract List<String> getNames();
The annotations provide a similar level of configurability as can be achieved by manual implementation. For example, the underlying collection
type and management of null objects can be specified as annotation parameters.
Datatype codecs and null objects
If a collection datatype codec annotation indicates that null objects should not be managed internally by Rhino, and null objects occur in the
corresponding data set, then this is one specific case where the serializing datatype codec is expected to handle and manage the null value
itself during serialization and deserialization. For simplicity reasons, it is highly recommended that Rhino be asked to manage null objects when
they are expected through appropriate annotation parameters.
3.2.6 Predefined datatype codecs
Rhino provides two sets of predefined datatype codecs:
• com.opencloud.rhino.cmp.codecs.SimpleDatatypeCodecs — provides codecs for the primitive type wrapper classes and
java.lang.String
• com.opencloud.rhino.cmp.codecs.SleeDatatypeCodecs — provides codecs for JAIN SLEE-defined types such as
javax.slee.SbbLocalObject and javax.slee.ActivityContextInterface .
These predefined codecs can be particularly useful when using datatype codecs for collections on page 40 that store simple types such as
java.lang.Integer or java.lang.String .
41
Rhino Extended APIs (V2.5.0)
3.3 Initial values
Often it is necessary, when a new persistent entity (such as an SBB entity) is created, to initialise various CMP fields to a value different than the
standard Java default. For example: a CMP field storing a counter may need to be initialised to 1 instead of the default value of 0; a CMP field
storing an array may need to be initialised to an empty array rather than default null ; or a CMP field storing a list may need to be initialised to an
empty list. The standard way to achieve this is to add the necessary CMP setter method invocations to the entity’s create lifecycle method; this is
acceptable, but means that the initial value is separated from the CMP field declaration, making the code less obvious than it could be. Also this
technique doesn’t work if, for example, an arbitrary CMP extension interface on page 47 is linked in to the SBB — the SBB needs to know a
priori what CMP fields need initialising — which means CMP fields in CMP extension interfaces dynamically added after compilation cannot be
initialised this way.
To solve this problem, Rhino introduces an annotation that can be used to specify the initial value for a CMP field.
3.3.1 Initial value fields
The initial value for a CMP field can be declared by annotating either the CMP field getter or setter method with the
@com.opencloud.rhino.cmp.InitialValueField annotation. The annotation references, either implicitly or explicitly by parameter, a
class field that contains the initial value for the CMP field. This mechanism means that the initial value can be constructed by any legal Java
means, and initial values for any arbitrarily complex CMP field type can be declared without issue.
If the annotation does not explicitly name a class field to use as the initial value, then a default name of _initial + the CMP field name, with the
first letter capitalised, is assumed. For example, for a CMP field with the name foo , the default initial value field name is _initialFoo .
The initial value class field must:
• be public, static, and final
• be visible in the scope of the annotated CMP field accessor method
• have a type that is assignable to the CMP field.
The @InitialValueField annotation may be used on:
• an SBB abstract class CMP field getter or setter method
• an SBB or SBB part CMP extension interface CMP field getter or setter method
42
Rhino Extended APIs (V2.5.0)
• a profile CMP interface CMP field getter or setter method.
It is illegal to use this annotation on both the getter and setter methods for the same CMP field, or to declare an initial value for the same CMP
field multiple times. For example, if a given CMP field is declared both in an SBB abstract class and an SBB CMP extension interface, only one
CMP field declaration may be annotated with an initial value declaration. It is legal, however, for example, for two separate SBB CMP extension
interfaces to both extend from a common interface that declares a CMP field with an initial value, as the initial value has only been declared once
by the parent interface.
The @InitialValueField annotation may not be used on a CMP field getter or setter method where the CMP field is one of the following types,
or is an array of any dimension of one of the following types:
• javax.slee.ActivityContextInterface , and any subclass of this interface
• javax.slee.SbbLocalObject , and any subclass of this interface
• javax.slee.EventContext
• javax.slee.profile.ProfileLocalObject , and any subclass of this interface.
A error occurs at deployment time if any of the above constraints are violated.
SLEE behaviour is undefined if an object referenced by an initial value class field is mutated at any time. A newly created persistent entity
containing the CMP field could be initialised with either the original initial value or the modified initial value at the discretion of the SLEE
implementation. It is generally advised that initial values be immutable; though in some cases this will not be possible.
Examples
Below is an example where the initial value field is explicitly named by the annotation:
@InitialValueField("aValue")public abstract void setIntValue(int value);public abstract int getIntValue();public static final int aValue = 42;
Below is an example where the initial value field is not explicitly specified, so the default field name is assumed:
@InitialValueFieldpublic abstract void setListValue(List<String> value);
43
Rhino Extended APIs (V2.5.0)
public abstract List<String> getListValue();public static final List<String> _initialListValue = new ArrayList<String>(5);
3.4 Pass-by-reference
The JAIN SLEE 1.1 specification, as written, prescribes that CMP fields have pass-by-value semantics. This means that when an object value
is stored in a CMP field, the SLEE will make and store a copy of that value, rather than store the original value. Similarly when a stored value is
retrieved from a CMP field, the SLEE will name a copy of the stored value and return the copied value. The effect of this is that the stored object
is unaffected by any subsequent changes made by the application to the original or retrieved object — a value retrieved from the CMP field will
always have the exact same state as it did when stored in the CMP field.
Generally speaking, this is desired behaviour, and it makes application code easier to understand. However there are times when pass-by-value
semantics get in the way of efficient programming, requiring additional coding to work around the limitations of these semantics. As an example,
consider an application that needs to use some unchanging session state across multiple transactions. The correct SLEE technique here is to
store the state in a CMP field, then retrieve that state in each transaction as required. Unfortunately the pass-by-value semantics mean that the
application incurs the overhead of a stored value copy every time it retrieves the value from the CMP field, even though the stored value is never
changed. A typical workaround to avoid this overhead is to:
1. create an instance variable which caches a reference to the stored value
2. add alternative getter and setter methods which check the cache first
3. include code in the relevant lifecycle callback methods to clear any cached reference when appropriate…
…all of which is cumbersome, particularly when there are many CMP fields that require this treatment.
To simplify the application developer’s effort in situations like these, Rhino introduces the option to declare pass-by-reference semantics to CMP
fields.
3.4.1 Reference scopes
Pass-by-reference may be declared with one of three reference scopes: TRANSACTIONAL , WHILE_READY , or PERMANENT .
The TRANSACTIONAL and WHILE_READY reference scopes operate in similar ways. An intermediate reference cache is used to store the
CMP field value during a transaction. If the CMP field is written to, the cache simply stores the reference to the stored value. If the CMP field is
44
Rhino Extended APIs (V2.5.0)
read, then the reference stored by the cache is returned. The actual stored value is only written back to persistent storage, and thus a copy is
made, when the transaction commits; and that value is only read back from persistent storage if the CMP field is read by the application and the
cache has been invalidated. The difference in the two reference scopes lies in when the cache is invalidated. When using the TRANSACTIONAL
reference scope, the reference cache is invalidated whenever a bounding transaction completes, either by commit or rollback. When using
the WHILE_READY reference scope, the reference cache is invalidated only when the owning container object (such as an SBB object) leaves
the READY state and is thus disassociated from the persistent entity, or transaction rollback occurs and the owning container object needs to
resynchronise with persistent state.
The PERMANENT reference scope completely removes any pass-by-value semantics. Any value stored in the CMP field is stored by reference
only. Unlike other reference scopes, a permanent reference loses all transactional semantics. Any changes made to the referenced object will
persist irrespective of whether the current transaction commits or rolls back. As such, permanent references are best suited to objects that are
unlikely to change during the lifetime of an application entity, for example: parts of input network messages that must be retained across event
handler transaction boundaries, but serialization of those messages is undesirable.
This reference scope should not be used in replicated SBBs, as object references naturally cannot extend beyond a single JVMboundary; the semantics of such a configuration are undefined.
Declaration
Pass-by-reference semantics are declared using the @com.opencloud.rhino.cmp.PassByReference annotation. This annotation may be
used on:
• an SBB abstract class CMP field getter or setter method
• an SBB or SBB Part on page 68 CMP extension interface on page 47 CMP field getter or setter method
• an SBB abstract class itself
• an SBB or SBB part CMP extension interface.
If the annotation is used on a class or interface declaration, then its meaning is applied to all CMP fields declared in the class or interface, and
also any subclass if the annotation’s inherited attribute is set to true . An individual CMP field may override any pass-by-reference semantics
inherited from a class or interface annotation by being annotated itself with a different reference scope. The reference scope DISABLED can also
be used in this case to remove any inherited pass-by-reference semantics from the CMP field.
It is illegal for a single CMP field’s getter and setter methods to be annotated with different reference scopes.
45
Rhino Extended APIs (V2.5.0)
A @PassByReference annotation with WHILE_READY or PERMANENT scope may not be used on a CMP field getter or setter method where the
CMP field is one of the following types, or is an array of any dimension of one of the following types:
• javax.slee.ActivityContextInterface , and any subclass of this interface
• javax.slee.SbbLocalObject , and any subclass of this interface
• javax.slee.EventContext
• javax.slee.profile.ProfileLocalObject , and any subclass of this interface.
Additional considerations
• If pass-by-reference semantics are desired for a CMP field that holds, either directly or indirectly, a reference to a SLEE-defined
object that is only valid in the transaction it was materialised (for example an SbbLocalObject , ProfileLocalObject ,
ActivityContextInterface , or EventContext ), then the reference scope must be limited to TRANSACTIONAL to avoid
runtime application failures. Note that if a CMP field directly storing one of these types inherits pass-by-reference semantics from
a class or interface annotation, Rhino will automatically limit the scope to TRANSACTIONAL for that CMP field. This means it is not
necessary to specifically annotate a CMP field directly storing one of these types if the inherited scope is wider — the correct scope
will be used automatically.
• The @PassByReference annotation naturally has no effect on CMP fields that store primitive types. Primitive types are always
stored by value.
• The @PassByReference annotation also has no effect on CMP fields that store types that Rhino understands to be immutable, such
as java.lang.Integer (and other primitive type wrappers), java.lang.String , javax.slee.Address , and so on… nor any
class that implements com.opencloud.util.Immutable . Immutable types are always stored by reference.
Examples
Below is an example of how a CMP field annotation declaring pass-by-reference semantics can be applied using the default ( WHILE_READY )
reference scope:
@PassByReferencepublic abstract void setValue(FooValue value);public abstract FooValue getValue();
46
Rhino Extended APIs (V2.5.0)
Below is an example of how a CMP field annotation declaring pass-by-reference semantics can be applied using the TRANSACTIONAL reference
scope:
@PassByReference(scope = PassByReference.Scope.TRANSACTIONAL)public abstract void setValue(FooValue value);public abstract FooValue getValue();
Below is an example of how an SBB abstract class annotation declaring pass-by-reference semantics can be used to apply the semantics to all
CMP fields, unless otherwise indicated, using the default ( WHILE_READY ) reference scope. These pass-by-reference semantics will also be
inherited by any subclass of this SBB abstract class.
@PassByReference(inherited = true)public abstract class MySbb implements Sbb { ...
// this CMP field will automatically be demoted to use the TRANSACTIONAL reference scope public abstract void setSbbObject(SbbLocalObject sbb); public abstract SbbLocalObject getSbbObject();
// this CMP field will revert to pass by value semantics @PassByReference(scope = PassByReference.Scope.DISABLED) public abstract void setValue(FooValue value); public abstract FooValue getValue();}
3.5 CMP extension interfaces
The SLEE specification requires the SBB CMP fields be defined using abstract getter and setter methods. For example, the SBB CMP field named
firstName of type java.lang.String must have the following method declarations in the SBB abstract class:
public abstract void setFirstName(String firstName);public abstract String getFirstName();
Rhino allows SBB CMP fields alternatively to be defined in separate CMP extension interfaces. A CMP extension interface is simply an interface
that declares methods related only to CMP fields. One use of a CMP extension interface is to allow an SBB to store additional state that may not
47
Rhino Extended APIs (V2.5.0)
be known when the SBB abstract class is developed. For example, the SBB build process may allow additional components to be "plugged in" to
the base SBB, each of which may require its own CMP state. The plug-in components can define the CMP state they need using CMP extension
interfaces; then these interfaces can be declared in the SBB deployment descriptor when the SBB is packaged.
CMP extension interfaces are also the sole mechanism by which an SBB part on page 68 component can define CMP fields.
The firstName CMP field example above could be defined in a CMP extension interface as shown below:
public interface MySbbCMPInterface { public void setFirstName(String firstName); public String getFirstName();
...}
A CMP extension interface may also optionally include has and reset methods for each CMP field.
• The has method determines if a value for the CMP field is present. Primitive types always have a value, so this method will always
return true for a CMP field of a primitive type. For CMP fields storing object types, this method returns true if the CMP field has
been assigned a non- null value. While this method is generally for convenience only, a has method can offer the potential for
better-performing code when only the presence of a value in the CMP field is required to be known, as the implementation does not
necessarily require the stored CMP field value to be deserialized in order to test for a non-null value.
• The reset method resets the CMP field value to its initial value. The initial value is determined by an @InitialValueField
on page 42 annotation, if present. Otherwise, the Java-defined default initial value for the field type is used; for example: 0 for
numeric primitives, null for object references.
Adding the has and reset methods to the MySbbCMPInterface example shown above results in the interface shown below:
public interface MySbbCMPInterface { public void setFirstName(String firstName); public String getFirstName();
// returns true if firstName has an assigned non-null value // effectively equivalent to: getFirstName() != null public boolean hasFirstName();
48
Rhino Extended APIs (V2.5.0)
// effectively equivalent to: setFirstName(null) public void resetFirstName();
...}
Below is an example of a how the reset method is influenced by an @InitialValueField annotation:
public interface MySecondSbbCMPInterface { @InitialValueField public void setNames(String[] names); public String[] getNames(); public static final String[] _initialNames = new String[0];
// effectively equivalent to: setNames(_initialNames) public void resetNames();
...}
A CMP extension interface must be public, and optionally may extend the com.opencloud.rhino.cmp.CMPFields on page 51 interface.
A single SBB or SBB part may declare as many CMP extension interfaces as desired. An SBB declares its CMP extension interfaces in the
oc-sbb-jar.xml extension deployment descriptor, while an SBB part declares its CMP extension interfaces in the oc-sbb-part-jar.xml
deployment descriptor. Since a CMP extension interface defines only CMP fields, an SBB deployment descriptor does not need to specify <cmp-
field> elements for any CMP field defined only in a CMP extension interface. The CMP fields will be determined by class introspection.
All methods defined in a CMP extension interface are mandatory transactional methods. If they are invoked without a valid transaction
context, a javax.slee.TransactionRequiredLocalException will be thrown. In addition, these methods may only be invoked
on an SBB or SBB part object that has been assigned to an SBB entity, or is in the process of being assigned to an SBB entity using the
sbbCreate method. If the SBB or SBB part object is not assigned to an SBB entity (with the exclusion of the sbbCreate method), a
java.lang.IllegalStateException is thrown.
49
Rhino Extended APIs (V2.5.0)
An SBB or SBB part obtains access to the CMP fields defined in CMP extension interfaces using a com.opencloud.rhino.cmp.CMPFields
object. The CMPFields object may be typecast to any CMP extension interface declared by the SBB or SBB part, regardless of whether or not
the CMP extension interface extends the CMPFields interface, thus exposing the CMP field accessor methods defined by the interface.
The CMP fields defined by an SBB in its SBB abstract class, in any CMP extension interfaces, and in any CMP extension interfaces used by
dependent SBB parts, all share the same namespace. As such, if the same CMP field is defined in multiple places, for example in the SBB
abstract class and in a CMP extension interface, then it must be declared with the same type. All these CMP accessor methods will refer to the
same underlying SBB CMP field.
3.6 Arbitrary CMP fields
There are sometimes occasions when an SBB needs to store arbitrary CMP state which cannot be predetermined at development time. For
example, arbitrary session state could be created in response to interactions with some other network element. The typical response is to define
a CMP field that stores a map and store the session state in the map as key, value pairs. This is an acceptable solution; however, serialization of
the stored map value can be a performance hit if not explicitly managed; and even then a change to any mapped value requires serialization of the
entire map as it is read from CMP, updated, then rewritten to CMP.
To help in these situations, Rhino allows an SBB or SBB part to optionally support arbitrary CMP fields. Arbitrary CMP fields are simply CMP
fields that have not been explicitly defined in the SBB abstract class or any CMP extension interface. Support for arbitrary CMP fields is disabled
by default but can be enabled using the arbitrary-cmp-fields-allowed attribute in the oc-sbb-jar.xml SBB extension deployment
descriptor or oc-sbb-part-jar.xml SBB part deployment descriptor. Note that if an SBB has a dependency on an SBB part that has enabled
support for arbitrary CMP fields, then support for arbitrary CMP fields extends back to the SBB and all its dependent SBB parts. It is not possible
for an SBB or SBB part to override a positive setting of this support from some other dependent SBB part (or the SBB itself in the case of an SBB
part).
Arbitrary CMP fields have only a few basic rules and restrictions:
• Arbitrary CMP fields must have a non-null name. Any non-null name is valid, including a zero-length name.
• An arbitrary CMP field cannot have the same name as a CMP field predefined in the SBB abstract class or any CMP extension
interface on page 47 .
50
Rhino Extended APIs (V2.5.0)
• An arbitrary CMP field is only deemed to exist if it has an assigned non- null value. An existing arbitrary CMP field ceases to exist if
assigned a null value.
• Any non- null value assigned to an arbitrary CMP field must be serializable using standard Java serialization. FastSerializable on
page 26 types are also supported. Encodable on page 28 types and those annotated with @DatatypeCodec , however, are
not currently supported. FastSerializable should be used instead where possible.
• Arbitrary CMP fields always exhibit pass-by-value semantics as per standard JAIN SLEE-defined CMP field behaviour. Pass-by-
reference on page 44 is not supported for these CMP fields.
Arbitrary CMP fields are accessed and managed using a CMPFields on page 51 object.
3.7 The CMPFields interface
The CMPFields interface provides a means to access CMP fields indirectly by name, access metadata about CMP fields, and obtain information
about and determine which CMP fields currently have a value. Arbitrary CMP fields on page 50 are also managed using a CMPFields object.
The CMPFields interface is shown below:
package com.opencloud.rhino.cmp;
public interface CMPFields { public <T> T get(String name) throws NullPointerException, UnrecognisedFieldNameException, ClassCastException; public <T> void set(String name, T value) throws NullPointerException, UnrecognisedFieldNameException, ClassCastException; public boolean has(String name) throws NullPointerException, UnrecognisedFieldNameException; public void reset(String name) throws NullPointerException, UnrecognisedFieldNameException; public void reset(); public Class<?> typeOf(String name) throws NullPointerException, UnrecognisedFieldNameException; public boolean isPredefined(String name) throws NullPointerException; public Set<String> predefinedNames(); public Set<String> keySet();
51
Rhino Extended APIs (V2.5.0)
public Set<Map.Entry<String,Object>> entrySet();}
The get , set , has , and parameterised reset methods allow any CMP field to be accessed by name parameter. These methods provide
an alternative access mechanism for CMP fields predefined in the SBB abstract class or a CMP extension interface on page 47 . These
methods also allow arbitrary CMP fields to be created and managed if support for this feature has been enabled. Predefined and arbitrary
CMP fields all share the same namespace. If any of these methods are invoked with a name parameter that matches a predefined CMP
field name, then the name refers to the predefined CMP field; otherwise it refers to an arbitrary CMP field. These methods throw an
UnrecognisedFieldNameException if the name refers to an arbitrary CMP field, but support for arbitrary CMP fields has not been enabled for
the SBB.
When any of these methods are used to access a predefined CMP field, the invocation is equivalent to the corresponding CMP field method
declaration. The example below illustrates this point:
public abstract class MySbb implements Sbb { public abstract void setFirstName(String firstName); public abstract String getFirstName();
public void someMethod() { CMPFields cmpFields = ...
// set CMP field to "Alice" setFirstName("Alice");
// returns "Alice" String firstName = cmpFields.get("firstName");
// set CMP field to "Bob" cmpFields.set("firstName", "Bob");
// returns "Bob" firstName = getFirstName();
// as the CMP field currently contains a value, // this will reset the CMP field to its initial value null if (cmpFields.has("firstName") { cmpFields.reset("firstName");
52
Rhino Extended APIs (V2.5.0)
}
// returns null firstName = getFirstName();
... }
...}
The unparameterised reset method resets all predefined CMP fields to their initial value and removes all arbitrary CMP fields that exist. This
method effectively returns the SBB CMP state to as it was when the SBB entity was first created.
The typeOf method returns the Java class type of the named CMP field. For a predefined CMP field the return value is equal to the class used
in its CMP field method declarations. For an arbitrary CMP field, this method returns the class of the value stored in the CMP field. The arbitrary
CMP field must exist for this method to return a successful result, otherwise an UnrecognisedFieldNameException is thrown.
The isPredefined method returns true if the name corresponds with a predefined CMP field, and false otherwise. The predefinedNames
method returns a set containing the names of all predefined CMP fields.
The keySet method returns a set containing the names of all CMP fields that currently have a value. The entrySet method returns a map
containing the names and values of all CMP fields that currently have a value. The CMP fields that are deemed to have a value include:
• any predefined CMP field of a primitive type
• any predefined CMP field of an object type that currently has a non- null value
• any arbitrary CMP field that currently exists.
All methods defined in the CMPFields interface are mandatory transactional methods. If they are invoked without a valid transaction
context, a javax.slee.TransactionRequiredLocalException will be thrown. In addition, these methods may only be invoked
on an SBB or SBB part object that has been assigned to an SBB entity, or is in the process of being assigned to an SBB entity using the
sbbCreate method. If the SBB or SBB part object is not assigned to an SBB entity (with the exclusion of the sbbCreate method), a
java.lang.IllegalStateException is thrown.
53
Rhino Extended APIs (V2.5.0)
3.7.1 CMPFields object
An SBB obtains a CMPFields object from its com.opencloud.rhino.slee.RhinoSbbContext object (a Rhino extension of
javax.slee.SbbContext ). An SBB part obtains a CMPFields object from its com.opencloud.rhino.slee.sbbpart.SbbPartContext
object.
A CMPFields object may be typecast to any CMP extension interface on page 47 declared by the SBB or any of its dependent SBB parts,
regardless of whether or not the CMP extension interface extends the com.opencloud.rhino.cmp.CMPFields interface.
54
Rhino Extended APIs (V2.5.0)
4 Miscellaneous SLEE Application API Enhancements
This page details the following enhancements to SLEE APIs, which Rhino provides for SLEE applications:
4.1 SbbContext interface extensions
Rhino provides an extension to the standard javax.slee.SbbContext interface with the com.opencloud.rhino.slee.RhinoSbbContext
interface. The RhinoSbbContext interface provides additional functionality to SBBs running in Rhino. The RhinoSbbContext interface is as
follows:
package com.opencloud.rhino.slee;
import java.util.Map;import javax.slee.SLEEException;import javax.slee.Sbb;import javax.slee.SbbContext;import javax.slee.TransactionRequiredLocalException;import javax.slee.TransactionRolledbackLocalException;import com.opencloud.rhino.cmp.CMPFields;import com.opencloud.rhino.cmp.Encodable;import com.opencloud.rhino.cmp.codecs.DatatypeCodec;import com.opencloud.rhino.cmp.codecs.DecoderUtils;import com.opencloud.rhino.cmp.codecs.EncoderUtils;import com.opencloud.rhino.facilities.Tracer;import com.opencloud.rhino.facilities.childrelations.ChildRelationFacility;import com.opencloud.rhino.slee.environment.JndiBinding;
public interface RhinoSbbContext extends SbbContext { public String getConvergenceName() throws TransactionRolledbackLocalException, IllegalStateException, SLEEException;
public Tracer getTracer(String tracerName) throws NullPointerException, IllegalArgumentException, SLEEException;
55
Rhino Extended APIs (V2.5.0)
public RhinoActivityContextInterface[] getActivities() throws TransactionRequiredLocalException, IllegalStateException, SLEEException;
public RhinoActivityContextInterface[] getActivities(Class<?> type) throws NullPointerException, TransactionRequiredLocalException, IllegalStateException, SLEEException;
public ChildRelationFacility getChildRelationFacility() throws SLEEException;
public CMPFields getCMPFields() throws SLEEException;
public Map<String,JndiBinding> getJndiBindings() throws SLEEException;
public <T> void setServiceContext(T context) throws SLEEException;
public <T> T getServiceContext() throws SLEEException;
public <T> void setEncodableContext(T context) throws SLEEException;}
4.1.1 RhinoSbbContext interface getConvergenceName method
The getConvergenceName method returns the convergence name that the SBB entity was created with. The value returned from this method is
a vendor-specific string that uniquely identifies the initial event selector conditions that led to the SBB entity’s creation.
This method only returns a non- null value if invoked on a RhinoSbbContext object belonging to a root SBB entity.
4.1.2 RhinoSbbContext interface getTracer method
The getTracer method overrides the same method from SbbContext to return a Rhino-specific extension of the Tracer interface.
56
Rhino Extended APIs (V2.5.0)
For more about this Tracer extension, please see Tracer extensions on page 112 .
4.1.3 RhinoSbbContext interface getActivities methods
The RhinoSbbContext interface defines two getActivities methods:
• getActivities() — This method overrides the same method from SbbContext to return a Rhino-specific extension of the
ActivityContextInterface interface. This ActivityContextInterface extension is described in more detail below.
Otherwise, this method behaves in the same way as defined by the JAIN SLEE specification.
• getActivities(Class) — This method behaves similarly to the no-argument version; however it only returns activity context
objects where the type of the underlying activity object is assignable to the class argument. For example, if this method was invoked
with NullActivity.class as an argument, then only activity context objects for the null activities the SBB entity is attached to
would be returned.
4.1.4 RhinoSbbContext interface getChildRelationFacility method
The getChildRelationFacility returns a Child Relation Facility object for the SBB.
For more about the Child Relation Facility, please see Child Relation Facility on page 91 .
4.1.5 RhinoSbbContext interface getCMPFields method
The getCMPFields method provides the SBB with access to its per-instance state.
For details on the CMPFields object returned from this method, please see The CMPFields interface on page 51 .
4.1.6 RhinoSbbContext interface getJndiBindings method
The getJndiBindings method returns a map describing the JNDI bindings available to the SBB.
57
Rhino Extended APIs (V2.5.0)
For more about this method, please see JNDI environment metadata on page 115 .
4.1.7 RhinoSbbContext interface setServiceContext and getServiceContext methods
The setServiceContext and getServiceContext methods allow setting and retrieving the service context object for the SBB. The service
context provides an alternative storage mechanism to using static class fields for arbitrary, typically constant data that the SBB wants to share
between SBB objects in the same service. The use of static class fields to store shared data becomes problematic when the encapsulating class
resides in a library component jar rather than an SBB jar. In this case the static fields end up being shared between all uses of that library, rather
than being scoped to a single service. The service context provides similar functionality to that of a static class field, but it is guaranteed to have
visibility only within the service.
A typical use of the service context is to store data calculated by the SBB during the SBB Service Lifecycle Callbacks on page 64 service
lifecycle callback methods.
Any object may be stored in the service context. The service context object is stored by reference, and is never serialised. As the service context
object may be accessed concurrently by different SBB objects, care must be taken that the service context object provides thread-safe access
where necessary.
A service context object will persist across service deactivation and reactivation cycles unless the SBB explicitly resets the service context to null
at the appropriate time.
The visibility of a service context object is scoped to a single SBB type within a service. All SBB objects of the same SBB type share the same
service context. Different SBB types within the same service may each store their own service context object without conflict.
4.1.8 RhinoSbbContext interface setEncodableContext method
The setEncodableContext method sets the encodable context for the SBB.
For more about encodable contexts, please see Encodable context on page 34 .
58
Rhino Extended APIs (V2.5.0)
4.2 Activity context Suspend/Resume Delivery extensions
The JAIN SLEE specification allows delivery of events to be suspended and resumed using the methods defined in the
javax.slee.EventContext interface. An obvious restriction to this is that suspending event delivery requires an EventContext object, and
the only way to obtain an EventContext object of an unsuspended event is by event handler method argument; therefore an SBB can only
suspend delivery of an event that is being delivered to it. An SBB that attaches to multiple activities may at times desire to suspend delivery of
events on a selected subset of these activities while waiting for the result of some asynchronous action. The SLEE specification does not provide
a trivial solution to this problem, instead requiring a complicated process of suspending events on those activities as they are received, then
resuming and processing those events at an appropriate time in a later transaction.
Rhino simplifies this problem by allowing event delivery on any activity context to be suspended and resumed at any time.
Rhino defines the com.opencloud.rhino.slee.RhinoActivityContextInterface interface, an extension to
javax.slee.ActivityContextInterface , with methods providing this functionality. The RhinoActivityContextInterface interface is
shown below:
package com.opencloud.rhino.slee;
import javax.slee.ActivityContextInterface;import javax.slee.SLEEException;import javax.slee.TransactionRequiredLocalException;
public interface RhinoActivityContextInterface extends ActivityContextInterface { public void suspendDelivery() throws IllegalStateException, TransactionRequiredLocalException, SLEEException;
public void suspendDelivery(int timeout) throws IllegalArgumentException, IllegalStateException, TransactionRequiredLocalException, SLEEException;
public void resumeDelivery() throws IllegalStateException, TransactionRequiredLocalException, SLEEException;
public boolean isSuspended() throws TransactionRequiredLocalException, SLEEException;
59
Rhino Extended APIs (V2.5.0)
}
All activity context objects that Rhino provides to SBBs implement RhinoActivityContextInterface ; therefore a typecast of an activity
ccntext object to this interface will always succeed. Rhino will also recognise an event handler method defined with this type, instead of the
standard ActivityContextInterface , as the second method argument, removing the need to perform a typecast within the method body if
the extensions are required.
An SBB or SBB Part activity context Interface on page 68 may be declared as extending RhinoActivityContextInterface rather than
ActivityContextInterface if desired.
4.2.1 RhinoActivityContextInterface interface suspendDelivery methods
The suspendDelivery methods suspend further delivery of events on the invoked activity context. An activity context is only ever suspended for
a specific period of time. The no-argument variant of this method suspends event delivery until some system specific default timeout is reached,
while the one-argument variant suspends event delivery for a specific timeout period in milliseconds. The timeout period is measured from the time
the suspendDelivery method is invoked. Some time after the timeout period expires, delivery of events on the activity context is automatically
resumed. Event delivery can also be manually resumed by an SBB before the timeout period expires, using the resumeDelivery method.
If an SBB suspends delivery of events on an activity context for which it is currently processing an event, then event delivery of that event is
suspended in the same way as if suspended using the event context associated with the event.
If an SBB suspends delivery of events on an activity context for which it is not currently processing an event, and the SLEE is already
asynchronously delivering an event on that activity context to an SBB, then event delivery suspension of that activity context takes effect after the
event handler method invoked on that SBB returns. If the SLEE is not currently delivering an event on that activity context, then event delivery
suspension takes immediate effect.
These methods are mandatory transactional methods. The delivery of events fired on the activity context is only suspended if the enclosing
transaction commits. If the transaction does not commit, then event delivery will not be suspended.
These methods throw the following exceptions:
Exception When thrown
60
Rhino Extended APIs (V2.5.0)
java.lang.IllegalArgumentException
The timeout argument is zero or a negative value.
javax.slee.IllegalStateException
Event delivery has already been suspended on the activity context, either by a suspendDel
ivery method invocation on the activity context itself or a suspendDelivery method
invocation on an EventContext object associated with an event delivered on the activity
context.
javax.slee.TransactionRequiredLocalException
This method is invoked without a valid transaction context.
javax.slee.SLEEException Event delivery on the activity context could not be suspended due to a system-level failure.
4.2.2 RhinoActivityContextInterface interface resumeDelivery methods
The resumeDelivery method resumes the delivery of events on the invoked activity context.
This method is a mandatory transactional method. The delivery of events occurring on the activity context is only resumed if the enclosing
transaction commits. If the transaction does not commit, then event delivery will not be resumed.
This method throws the following exceptions:
Exception When thrown
javax.slee.IllegalStateException
Delivery of events on the activity context is not currently suspended; for example, if event
delivery has not been suspended or has already been resumed.
javax.slee.TransactionRequiredLocalException
This method is invoked without a valid transaction context.
javax.slee.SLEEException Event delivery on the activity context could not be resumed due to a system-level failure.
61
Rhino Extended APIs (V2.5.0)
4.2.3 RhinoActivityContextInterface interface isSuspended methods
The isSuspended method determines if the delivery of events on the activity context is currently suspended. This method returns true if the
event delivery is suspended or false otherwise.
This method is a mandatory transactional method. This method throws the following exceptions:
Exception When thrown
javax.slee.TransactionRequiredLocalException
This method is invoked without a valid transaction context.
javax.slee.SleeException The event delivery status of the activity context could not be determined due to a system-level
failure.
4.2.4 Relationship to event context suspend/resume
The event delivery status of an event context is linked to the event delivery status of its associated activity context. If an event context is
suspended, then event delivery on the activity context is also suspended, and vice versa. Similarly, if an event context is resumed, then event
delivery on the activity context is also resumed. Therefore, an SBB that wants to suspend delivery of events on an activity context for which it
is currently processing an event may do so in one of two ways — by invoking a suspendDelivery method on either the event context for the
received event or on the activity context that the event was delivered on.
Both these operations have the same effect. Of particular note, after either method has been invoked, both the event context and the activity
context will return true from their respective `isSuspended methods.
An SBB may also resume delivery of events on an activity context in one of two ways — by invoking the resumeDelivery method on either the
event context of the suspended event (if the event context is available) or on the activity context.
Again, both these operations will have the same effect; and after either method has been invoked, both the event context and the activity context
will return false from their respective isSuspended methods.
62
Rhino Extended APIs (V2.5.0)
4.3 SBB local home interface
The JAIN SLEE specification allows an SBB component to declare a local interface. An SBB entity can invoke a target SBB entity in a
synchronous manner through the SBB local interface of the target SBB. Rhino also allows an SBB to declare a local home interface. Methods
invoked on the local home interface are not specific to any SBB entity and are executed by an SBB object in the Pooled state. An SBB local home
object is an instance of a SLEE-implemented class that implements an SBB local home interface.
4.3.1 How to get an SBB local home object
An SBB can only get an SBB local home object for its child SBBs. An SBB can get an SBB local home object for each of its child SBBs using the
Child Relation Facility on page 91 . The getChildSbbLocalHome method defined by the ChildRelationFacility interface returns an
SBB local home object for the specified child SBB relation.
4.3.2 The RhinoSbbLocalHome interface
This interface is the base interface of all SBB local home interfaces. Currently Rhino does not allow an SBB to extend this interface; so all SBB
local home interfaces, if declared, must be declared as this interface. If an SBB does not declare an SBB local home interface, then the SBB local
home interface defaults to RhinoSbbLocalHome .
The RhinoSbbLocalHome interface is shown below:
package com.opencloud.rhino.slee;
import javax.slee.TransactionRequiredLocalException;
public interface RhinoSbbLocalHome { public Object verifyConfiguration() throws InvalidConfigurationException, TransactionRequiredLocalException;
public void serviceActivating(Object config) throws TransactionRequiredLocalException;
public void serviceDeactivating() throws TransactionRequiredLocalException;}
63
Rhino Extended APIs (V2.5.0)
If an SBB declares a local home interface in its deployment descriptor, then the local home interface methods must be implemented in the SBB
abstract class using a method name constructed by capitalising the first letter of the method name as defined in this interface then prefixing
sbbHome . The method parameters and return type must be identical, and the throws clause of the implemented method must be the same as or a
subset of the interface method declaration, excluding any runtime exceptions.
Although an SBB that does not declare an SBB local interface receives RhinoSbbLocalHome as a default local home interface, such an SBB
is not required to implement the local home interface methods in the SBB abstract class. The SLEE will instead provide a default no-operation
implementation of these methods.
4.3.3 SBB service lifecycle callbacks
The RhinoSbbLocalHome interface defines methods that allow an SBB to receive callbacks when a service it is used in is activated or
deactivated. These methods are described below.
4.3.4 RhinoSbbLocalHome interface verifyConfiguration method
The SLEE invokes the verifyConfiguration method on the root SBB of a service when the service is about to transition from Inactive to
Active. This callback can be used by an SBB, for example, to check that its configuration in environment entries or elsewhere is valid. The SBB
can throw an InvalidConfigurationException from this method if a configuration error or other reason means that the service should not
be activated at this time.
Child SBBs in the service may also receive this callback method invocation, as described in the Lifecycle callback method invocation cascade on
page 66 section below.
In Rhino, this method is invoked on a service on each cluster node where the service is about to transition to the Active state.
If an SBB declares a local home interface, then a corresponding method with the following signature must be implemented in the SBB abstract
class:
public Object sbbHomeVerifyConfiguration() throws InvalidConfigurationException;
The throws clause is optional.
• If the method throws an InvalidConfigurationException when the administrator has requested activation of the service on a
node that is currently operational, then the activation request fails and the service state remains unchanged.
64
Rhino Extended APIs (V2.5.0)
• If the method throws an InvalidConfigurationException exception when a node (re)starts, where the per-node state for that
node indicates that the service should be reactivated, then the reactivation attempt fails, the service transition back to the Inactive
state on that node, and an alarm is raised to indicate that the service could not be activated.
The return result from this method is passed as an argument to the serviceActivating method if the service successfully activates. This
object can be used, for example, to pass some configuration information calculated during this method to the serviceActivating method if that
method would otherwise need to recalculate the same information again.
This method is a mandatory transactional method. When this method is invoked by the SLEE, it is invoked with an active transaction context. If
this method is invoked by an SBB without a valid transaction context then a TransactionRequiredLocalException is thrown.
4.3.5 RhinoSbbLocalHome interface serviceActivating method
The SLEE invokes the serviceActivating method on the root SBB of a service when the service is about to transition from Inactive to Active.
This method is invoked after the verifyConfiguration method has returned successfully and the SLEE has determined that the service
activation can proceed to completion. The SBB can use this callback, for example, to initialise common state shared between SBB objects (such
as the service context of the same SBB).
Child SBBs in the service may also receive this callback method invocation, as described in the Lifecycle callback method invocation cascade on
page 66 section below.
In Rhino, this method is invoked on a service on each cluster node where the service is about to transition to the Active state. The service
transitions to the Active state on the corresponding node after this method returns.
If an SBB declares a local home interface, then a corresponding method with the following signature must be implemented in the SBB abstract
class:
public void sbbHomeServiceActivating(Object config);
When this method is invoked by the SLEE, the object passed as an argument to this method is the return result from the previous corresponding
verifyConfiguration method invocation.
This method is a mandatory transactional method. When this method is invoked by the SLEE, it is invoked with an active transaction context. If
this method is invoked by an SBB without a valid transaction context then a TransactionRequiredLocalException is thrown.
65
Rhino Extended APIs (V2.5.0)
4.3.6 RhinoSbbLocalHome interface serviceDeactivating method
The SLEE invokes the serviceDeactivating method on the root SBB of a service when no SBB entity trees remain in the service and it is
about to transition from the Stopping state to the Inactive state. An SBB can use this callback, for example, to clean up any shared state that is no
longer required after the service has deactivated.
Child SBBs in the service may also receive this callback method invocation, as described in the Lifecycle callback method invocation cascade on
page 66 section below.
In Rhino, this method is invoked on a service on each cluster node where the service is about to transition to the Inactive state. The service
transitions to the Inactive state on the corresponding node after this method returns.
If an SBB declares a local home interface, then a corresponding method with the following signature must be implemented in the SBB abstract
class:
public void sbbHomeServiceDeactivating();
This method is a mandatory transactional method. When this method is invoked by the SLEE, it is invoked with an active transaction context. If
this method is invoked by an SBB without a valid transaction context, then a TransactionRequiredLocalException is thrown.
4.3.7 Lifecycle callback method invocation cascade
The SBB service lifecycle callback methods are initially invoked by the SLEE on the root SBB of a service. If the root SBB has child SBB relations
where the cascade-service-lifecycle-callbacks option in the SBB extension deployment descriptor is set to True , then the SLEE will
also automatically invoke the same lifecycle callback method on each of those child SBBs. This process repeats or "cascades" to each child SBB
in the service where the cascade-service-lifecycle-callbacks option in the parent SBB requests it. The SLEE however will invoke this
method at most once for each SBB type present in the service, regardless of how many times a given SBB appears as a child SBB in the service.
Lifecycle callback method invocation cascade is enabled by default on all child relations. Cascade may be disabled for a given child SBB relation
by setting the corresponding cascade-service-lifecycle-callbacks option in the SBB extension deployment descriptor to False . As
an alternative to automatic cascade, an SBB can manually invoke the lifecycle callback methods directly on any of its child SBBs by obtaining
the child SBB’s local home object from the Child Relation Facility on page 91 . Lifecycle callback methods invoked by an SBB, rather than the
SLEE, do not cascade to other child SBBs, even if those child SBB relations are flagged for cascade.
66
Rhino Extended APIs (V2.5.0)
Lifecycle callback method invocations proceed to cascade through eligible child SBB relations irrespective of whether or not the root SBB or any
given child SBB declares a local home interface. An SBB that does not declare a local home interface is simply unaware that the callback method
invocation occurred.
4.4 Unchecked throwable propagation
The JAIN SLEE specification states that if a method invocation on an SBB or a profile returns by throwing an unchecked exception, then (amongst
other things) the transaction is marked for rollback and a javax.slee.TransactionRolledBackLocalException is propagated back to the
caller. There may be times, however, in certain applications where this behaviour is undesirable, and the caller would rather catch and handle the
exception itself rather than have the transaction forcibly rolled back.
To address this need, Rhino provides the @PropagateUncheckedThrowables annotation. This annotation can be used on any SBB local
interface method or profile local interface method to indicate that any unchecked throwable ( RuntimeException s or Error s) produced by the
method must be propagated back to the caller as-is. The transaction is not marked for rollback, and the invoked SBB or profile object remains in
the same state; in other words, it is not discarded by a transition to the Does Not Exist state.
An SBB local interface or profile local interface class declaration may also be annotated with @PropagateUncheckedThrowables . When used
in this way, the annotation indicates that all methods defined in the interface, and all inherited methods, shall exhibit the behaviour defined by the
annotation, as if all these methods were annotated individually.
The propagation of unchecked throwables only applies to exceptions produced by the invoked method itself. The annotation has no effect
against container-generated exceptions that cause rollback, such as trying to invoke a local interface method on an SBB that no longer
exists. The annotation is also ignored for methods originally defined in the base local interfaces: javax.slee.SbbLocalObject and
javax.slee.profile.ProfileLocalObject .
67
Rhino Extended APIs (V2.5.0)
5 SBB Parts
This page includes these details for using SBB parts:
5.1 What are SBB parts?
An "SBB part", as its name implies, can be thought of as a sub-component of a JAIN SLEE SBB (Service Building Block). An SBB part is an
installable SLEE component in its own right. It may have dependencies, and other components may depend on it. The concept of the SBB part
component was borne from a use case where the developer wanted to put a number of common shared classes into a library-type component;
but the classes had dependencies on various profile specifications, event types, and resource adaptor types — all of which a standard JAIN SLEE
library component cannot provide (a library component may only depend on other library components). We thought it might be desirable to extend
the definition of the standard library component with the option to declare these other types of references, mainly because a library component
was always seen as a passive "primitive" type of component that sat at the top of the dependency hierarchy. Adding dependency links to other
component types would significantly complicate the SLEE component dependency hierarchy. In particular, it would create the possibility of cyclic
dependencies between different component types — which must be avoided, as in practise they cannot be mapped to a realistic runtime class
loader hierarchy. So instead, a new component type was created to fulfill this need: the SBB part.
SBB part components have one other feature that make them distinct from library components: at runtime the SBB part component classes are
included in the same class loader as the SBB classes for the service, rather than in a parent class loader (as standard library components are).
5.2 SBB part components
An SBB part component may define:
• dependencies — on libraries, event types, resource adaptor types, profile specifications and other SBB parts
• per-instance state — held in Container Managed Persistence (CMP) fields that can maintain persistent state that should persist
across failures
• usage statistics — collected through usage parameters interface types declared by the SBB part component (see Usage in the
Rhino Administration and Deployment Guide for a description of Rhino’s usage extension mechanism)
68
Rhino Extended APIs (V2.5.0)
• event handler methods — provided by the SBB part component for each event type it receives, with application logic to process
events of a specific event type
• shareable data — defined by the SBB part component to share with other components as a set of activity context attributes (each
activity context attribute has a name and a type, and is stored in one or more activity contexts — an SBB part component defines an
activity context interface interface that provides type-safe accessor methods to get and set these attributes).
An SBB part component can only be referenced by SBB components or other SBB part components.
5.3 SBBs and SBB parts
An SBB may depend on one or more SBB parts. An SBB part may also depend on other SBB parts. An SBB that depends on one or more SBB
parts, both directly and indirectly, has its definition implicitly extended in the following ways:
per-instance state The per-instance persistent state of the SBB is defined by the union of the CMP fields declared by the SBB
and the CMP fields declared by each dependent SBB part. All CMP fields declared by these components
share the same namespace. A CMP field declared by both the SBB and a dependent SBB part, or two
different dependent SBB parts, must be declared with the same field type, as they each refer to the same
piece of per-instance state.
usage statistics The usage parameters interface types available to the SBB is the union of the usage parameters interface
types declared by the SBB and the usage parameters interface types declared by each dependent SBB part.
All usage parameters interface types declared by these components share the same namespace. A usage
parameters interface type declared by both the SBB and a dependent SBB part, or two different dependent
SBB parts, must be declared with the same usage parameters interface class name. Amongst the SBB and
all dependent SBB parts, at most one usage parameters interface type may be declared as the root usage
parameter set type.
event handler methods The event handler methods available to the SBB is the union of the event handler methods defined by the
SBB and the event handler methods defined by each dependent SBB part. Any given event type can have
at most one event handler method defined between the SBB and the SBB parts — if the SBB declares an
69
Rhino Extended APIs (V2.5.0)
event handler method for a given event type, then no dependent SBB part may also declare an event handler
method for the same event type.
shareable data The activity context attributes of the SBB are the union of the activity context attributes declared by the SBB
and the activity context attributes declared by each dependent SBB part. All activity context attributes declared
by these components share the same namespace. An activity context attribute declared by both the SBB and
a dependent SBB part, or two different dependent SBB parts, must be declared with the same type, as they
each refer to the same attribute. The SBB and dependent SBB parts may each declare an alias for the same
activity context attribute, but the alias name must be identical; in other words, each alias declaration must be
identical. If any of the components declare an alias for a given activity context attribute, then the alias applies
to all the components.
JNDI environment The JNDI bindings available to the SBB is the union of all JNDI bindings declared by the SBB and all JNDI
bindings declared by each SBB part. A binding to a given name declared by both the SBB and a dependent
SBB part, or two different dependent SBB parts, must be declared with the same value. For example, if the
binding is made to a resource adaptor entity, then each binding declaration must have the same resource
adaptor type reference.
Put simply, an SBB becomes the union of the declarations made by itself and all its dependent SBB parts; and there must be no conflict between
components that make the same declarations.
5.4 SBB part objects
An SBB part may optionally declare an SBB part class on page 73 . The SBB part class contains the event-processing logic of the SBB part
component. An instance of the SBB part class is known as an SBB part object.
The lifecycle of an SBB part object is tightly coupled to the lifecycle of an SBB object. When an SBB object is created, an SBB part object for each
dependent SBB part that declares an SBB part class is also created; and the SBB object maintains a reference to this SBB part object for the
lifetime of the SBB object. When the SBB object undergoes a lifecycle state transition, for example from the Pooled state to the Ready state, each
dependent SBB part object also undergoes the same lifecycle transition. If the SLEE determines that the SBB object is no longer required and
becomes eligible for JVM garbage collection, then so too do the dependent SBB part objects.
70
Rhino Extended APIs (V2.5.0)
During the lifetime of an SBB part object, it may be assigned to different SBB entities. When the SBB part object is assigned to an SBB part entity,
it can receive events destined for the SBB entity and can manipulate the persistent state of the SBB entity. It can also access the relationships of
the SBB entity.
5.4.1 SBB part object lifecycle
An SBB part object can be in one of the following three states:
• Does Not Exist — The SBB part object does not exist. It may not have been created or it may have been deleted.
• Pooled — The SBB part object exists but is not assigned to any particular SBB entity.
• Ready — The SBB part object is assigned to an SBB entity. It is ready to receive events through its event handler methods.
The following steps describe the lifecycle of an SBB part object:
1. An SBB part object’s lifecycle starts when the SLEE creates the object using newInstance . The SLEE passes the SBB part object
an SbbPartContext on page 86 object to the constructor if the constructor defines such an argument. The SbbPartContext
object allows the SBB part object to invoke functions provided by the SLEE. Once the SBB object is created, the SLEE then injects
values into SBB part class fields annotated for dependency injection.
2. The SBB part object is bound to an owning SBB object. While the SBB object is in the Pooled state, the SBB part object is also in the
Pooled state, and is not associated with any particular SBB entity.
3. An SBB part object transitions from the Pooled state to the Ready state when the SLEE selects the owning SBB object to process an
event or to service a logic object invocation. There are two possible transitions from the Pooled state to the Ready state: through the
@PostCreate method, or through the @OnActivate method.
• The SLEE invokes the @PostCreate method when the SBB part object is assigned to a new SBB entity that has just been
created explicitly by an invocation of the create method on a ChildRelation object, or implicitly by the SLEE to process an
initial event.
• The SLEE invokes the @OnActivate method on an SBB part object when the owning SBB object needs to be activated to
receive a method invocation on an existing SBB entity. This occurs when there is no existing SBB object in the Ready state
assigned to the SBB entity available to receive the invocation.
4. When an SBB part object is in the Ready state, the SBB part object is associated with a specific SBB entity. While the SBB part
object is in the Ready state, the SLEE can synchronise the transient state held in the SBB part object with the persistent state of the
71
Rhino Extended APIs (V2.5.0)
SBB entity whenever it determines the need to, by invoking the @PostLoad and @PreStore methods zero or more times. Event
handler and exception callback methods can be invoked on the SBB part object zero or more times. Invocations of the @PostLoad
and @PreStore methods can be arbitrarily mixed with invocations of these methods subject to the SBB part object lifecycle.
5. The SLEE can choose to passivate an SBB object. Passivating an SBB object disassociates the SBB object from the SBB entity
it is currently assigned to. When an SBB object is passivated, its dependent SBB part objects are also passivated and therefore
disassociated from the SBB entity. When an SBB part object is passivated, the SLEE first invokes the @PreStore method to allow
the SBB part object to prepare itself for the synchronisation of the SBB entity’s persistent state with the SBB part object’s transient
state; then the SLEE invokes the @OnPassivate method to return the SBB part object to the Pooled state.
6. Eventually, the SLEE will transition the SBB part object to the Pooled state. There are two possible normal transitions from the Ready
state to the Pooled state: through the @OnPassivate method, and through the @PreRemove method.
• The SLEE invokes the @OnPassivate method when the SLEE wants to disassociate the SBB object and its dependent SBB
part objects from the SBB entity without removing the SBB entity.
• The SLEE invokes the @PreRemove method when the SLEE wants to remove the SBB entity (in other words, when the SBB
entity is removed as part of cascading removal of an SBB entity sub-tree).
7. When the SBB object and its dependent SBB part objects are put back into the pool, they are no longer associated with the SBB
entity. The SLEE can assign the SBB object and SBB part objects to any SBB entity of the same SBB component.
8. The SLEE may release its references to an SBB object in the pool, along with its dependent SBB part objects, allowing them to be
garbage collected. It may do this after calling the unsetSbbContext method on the SBB object, and the @PreDispose method on
each SBB part object.
• The SbbPartContext object passed by the SLEE to the SBB part object in the constructor, or by dependency
injection, is not an object that contains static information. For example, the result of the getSbbLocalObject method
might be different each time an SBB part object moves from the Pooled state to the Ready state, and the result of the
getActivities method may be different in different event handler method invocations.• An SBB part object is only ever associated with one SBB in one service. This means that the getService , getSbb ,
and getSbbPart methods of an SbbPartContext object always return the same result during the lifetime of the SBB
part object.
72
Rhino Extended APIs (V2.5.0)
• The order in which the SLEE invokes dependent SBB part objects for a given lifecycle callback method is not defined.
The SBB part objects may be invoked in any order; however the SBB part object callbacks will always be made before
or after the corresponding SBB object lifecycle callback method invocation, as defined in the Lifecycle methods on page
73 section.• A RuntimeException thrown from any method of an SBB part object (including the event handler methods and
the lifecycle callbacks invoked by the SLEE) results in the transition to the Does Not Exist state after the appropriate
exception handler methods have been invoked. The SLEE will not invoke any method except the @OnException method
on the SBB part object after a RuntimeException has been caught. The corresponding SBB entity continues to exist.
The SBB entity can continue to receive events and synchronous invocations because the SLEE can use different SBB
and SBB part objects to process events and synchronous invocations that should be sent to the SBB entity. For more on
exception handling, see the Exception callback method on page 81 section.
5.5 SBB part class
An SBB part must define an SBB part class if the SBB part declares event handler methods. In any other case, the definition of an SBB part class
is optional. An SBB part class must:
• be defined in a named package; that is, the class must have a package declaration
• be defined as public
• not be abstract or final
• not define the finalize method.
The SBB developer implements the SBB part class. In it, they may define lifecycle and event handler methods, and an exception callback. The
SBB part class may also use Dependency Injection on page 83 for various types of fields.
5.5.1 Lifecycle methods
Each SBB part object has a lifecycle. The SLEE invokes the lifecycle methods of the SBB part object to make the SBB part object aware of its
lifecycle state. The SLEE invokes a given lifecycle method on an SBB part object at the same time that it invokes the corresponding lifecycle
method on the owning SBB object; however the order in which different dependent SBB parts are invoked for a given lifecycle method invocation
is not defined.
73
Rhino Extended APIs (V2.5.0)
The lifecycle methods are described below. In the case of lifecycle methods denoted by annotations, at most one of each lifecycle method may be
declared in an SBB part class.
Constructor
The SBB part class must define a public constructor that takes either no arguments or a single argument of type
com.opencloud.rhino.slee.sbbpart.SbbPartContext on page 86 . The SLEE invokes the constructor of an SBB part class to create a new SBB
part object. The SLEE creates a new SBB part object when the owning SBB object transitions from the Does Not Exist state to the Pooled state.
If the SBB part object needs to use the SbbPartContext object during its lifetime, it should keep a reference to the SbbPartContext object in an
instance variable. Alternatively, the SBB part object may obtain a reference to an SbbPartContext object using Dependency Injection on page
83 .
During the constructor invocation, the SBB part object is not assigned an SBB entity. The SBB part object can use the constructor to allocate and
initialise state or connect to resources that are to be held by the SBB part object during its lifetime. Such state and resources cannot be specific to
an SBB entity, because the SBB part object might be reused during its lifetime to service multiple SBB entities.
The SBB part object constructor invocation corresponds to the setSbbContext lifecycle method of the SBB abstract class, and is invoked after
the setSbbContext method returns successfully.
If both supported constructors are defined, then the one-argument constructor is used.
• The SBB part class constructor must not define a throws clause.• The SBB part object must not attempt to access its persistent state using the CMP field accessor methods during the
constructor invocation.• The constructor is invoked with an unspecified transaction context.
@PreDispose
The SBB part class may optionally implement a lifecycle callback method invoked by the SLEE before the SLEE terminates the life of the SBB part
object. This method must be annotated with the @PreDispose annotation. This method is invoked when the SBB part object transitions from the
Pooled state to the Does Not Exist state. During this method, an SBB entity is not assigned to the SBB part object. The SBB part object can use
this method to free state or resources that are held by the SBB part object. These state and resources typically had been allocated by the SBB
part class constructor.
74
Rhino Extended APIs (V2.5.0)
This method corresponds to the unsetSbbContext lifecycle method of the SBB abstract class, and is invoked before the unsetSbbContext
method is invoked on the owning SBB object.
• A method annotated with @PreDispose method must be declared as public and cannot be static, abstract, or final.• This method must not take any arguments, must have a void return type, and must not define a throws clause.• The SBB part object must not attempt to access its persistent state using the CMP field accessor methods during this
method.• This method is invoked with an unspecified transaction context.
@PostCreate
The SBB part class may optionally implement a lifecycle callback method invoked when a new SBB entity is created. The method must be
annotated with the @PostCreate annotation. This method is invoked when the SBB part object transitions from the Pooled state to the Ready
state as a result of SBB entity creation, and is invoked after the persistent representation of the SBB entity has been created and the SBB part
object is assigned to the created SBB entity. This method can be used to initialise any transient state and acquire any resources that the SBB part
needs while it is in the Ready state.
• A method annotated with @PostCreate must be declared as public and cannot be static, abstract, or final.• This method must not take any arguments and must have a void return type.• This method may throw a javax.slee.CreateException when there is an application level problem (rather than
a SLEE or system level problem). The SLEE will also propagate the CreateException unchanged to the caller that
requested the creation of the SBB entity. The caller may be the SLEE or an SBB object. The throws clause is optional.• This method may not define a throws clause that includes any exception other than CreateException .• The SLEE guarantees that the values that will be initially returned from the getter methods of any CMP field declared
exclusively by the SBB part will be the Java language defaults (such as 0 for integer, or null for object references),
unless those CMP fields have been annotated with CMP Field Enhancements on page 25 @InitialValueFields on page 42
, in which case the initial value returned by the CMP field getter method will be as defined by the initial value field.• The SLEE invokes this method with the transaction context used to invoke the sbbCreate and sbbPostCreate
methods on the owning SBB object.
75
Rhino Extended APIs (V2.5.0)
• The SBB part object enters the Ready state after this method returns normally. If this method returns by throwing an
exception, the SBB part object does not become Ready.
This method corresponds to the sbbPostCreate lifecycle method of the SBB abstract class, and is invoked after the sbbPostCreate method
returns successfully.
Note that there is no SBB part lifecycle method equivalent to the SBB abstract class sbbCreate method.
@OnActivate
The SBB part class may optionally implement a lifecycle callback method invoked when the SLEE needs to assign an SBB part object in the
Pooled state to a existing SBB entity. This method must be annotated with the @OnActivate annotation. The SBB part object transitions to the
Ready state after this method returns. This method gives the SBB part object a chance to initialise additional transient state and acquire additional
resources that it needs while it is in the Ready state.
• A method annotated with @OnActivate must be declared as public and cannot be static, abstract, or final.• This method must not take any arguments, must have a void return type, and must not define a throws clause.• The SBB part object must not attempt to access its persistent state using the CMP field accessor methods during this
method.• This method executes with an unspecified transaction context.
This method corresponds to the sbbActivate lifecycle method of the SBB abstract class, and is invoked after the sbbActivate method returns
successfully.
@OnPassivate
The SBB part class may optionally implement a lifecycle callback method invoked when the SLEE decides to disassociate an SBB part object
in the Ready state from the SBB entity it is currently associated with. This method must be annotated with the @OnPassivate annotation. The
SBB part object transitions to the Pooled state after this method returns. This method gives the SBB part object the change to release any state or
resources that should not be held while the SBB part object is in the Pooled state. These state and resources typically had been allocated during
the @OnActivate method.
76
Rhino Extended APIs (V2.5.0)
• A method annotated with @OnPassivate must be declared as public and cannot be static, abstract, or final.• This method must not take any arguments, must have a void return type, and must not define a throws clause.• The SBB part object must not attempt to access its persistent state using the CMP field accessor methods during this
method.• This method executes with an unspecified transaction context.
This method corresponds to the sbbPassivate lifecycle method of the SBB abstract class, and is invoked after the sbbPassivate method
returns successfully.
@PreRemove
The SBB part class may optionally implement a lifecycle callback method invoked by the SLEE when the SBB entity assigned to the SBB part
object is about to be removed. This method must be annotated with the @PreRemove annotation. The SBB part object is in the Ready state when
this method is invoked, and it will transition to the Pooled state after this method returns. This method can be used to implement any actions that
must be done before the SBB entity’s persistent representation is removed.
• A method annotated with @PreRemove must be declared as public and cannot be static, abstract, or final.• This method must not take any arguments, must have a void return type, and must not define a throws clause.• The SLEE synchronises the SBB part object’s state before it invokes the @PreRemove method. This means that the
CMP state of the SBB part object at the beginning of this method is the same as it would be at the beginning of an event
handler method.• This method is invoked with same transaction context as used to invoke the sbbRemove method on the owning SBB
object.• Since the SBB part object will transition to the Pooled state, the state of the SBB part object at the end of this method
must be equivalent to the state of a passivated SBB part object. This means that the SBB part object must free any state
and release any resource that it would normally release in the @OnPassivate method (if declared).
This method corresponds to the sbbRemove lifecycle method of the SBB abstract class, and is invoked before the sbbRemove method is invoked
on this owning SBB object.
77
Rhino Extended APIs (V2.5.0)
@PostLoad
The SBB part class may optionally implement a lifecycle callback method invoked by the SLEE to synchronise the state of the SBB part object with
its assigned SBB entity’s persistent state. This method must be annotated with the @PostLoad annotation. The SBB developer can assume that
the persistent state of the SBB entity the SBB part object is assigned to has been loaded just before this method is invoked. It is the responsibility
of the SBB developer to use this method to re-compute or initialise the values of any transient instance variables in the SBB part object that
depend on the SBB entity’s persistent state. In general, any transient state that depends on the persistent state of an SBB entity should be
recalculated in this method. The SBB developer can use this method, for instance, to perform some computation on the values returned by the
CMP field accessor methods, such as converting text fields to more convenient objects or binary representations.
• A method annotated with @PostLoad must be declared as public and cannot be static, abstract, or final.• This method must not take any arguments, must have a void return type, and must not define a throws clause.• The SLEE invokes this method within a transaction context.
This method corresponds to the sbbLoad lifecycle method of the SBB abstract class, and is invoked after the sbbLoad method returns
successfully.
@PreStore
The SBB part class may optionally implement a lifecycle callback method invoked by the SLEE to synchronise the SBB entity’s persistent state
with the state of the SBB part object. This method must be annotated with the @PreStore annotation. The SBB developer should use this method
to update the SBB entity using the CMP field accessor methods before its persistent state is synchronised. For example, this method may perform
conversion of object or binary data representations to text. The SBB developer can assume that after this method returns, the persistent state is
synchronised.
• A method annotated with @PreStore must be declared as public and cannot be static, abstract, or final.• This method must not take any arguments, must have a void return type, and must not define a throws clause.• The SLEE invokes this method within a transaction context.
This method corresponds to the sbbStore lifecycle method of the SBB abstract class, and is invoked after the sbbStore method returns
successfully.
78
Rhino Extended APIs (V2.5.0)
5.5.2 Event handler methods
An SBB part class may receive an event through one of its event handler methods. An SBB part declares event handler methods in the same way
as an SBB. For each event type received by the SBB part, you must:
• provide an event element in the SBB part’s sbb-part deployment descriptor element — the value of the event-direction
attribute of the event element must be Receive . It must also include an event-name element and an event-type-ref element.
• The event-name element provides the SBB part scoped name used within the SBB part class to identify the event type, and
determines the name of the event handler method.
• The event-type-ref element references an event-definition element that provides the event type and the event
class.
• The event-definition element is provided and defined by the event producer of the event type.
• The initial-event attribute of the event element may optionally be set to True .
• The event element may optionally include an event-resource-option element.
• implement the event handler method in the SBB part class — this method contains the application logic that will be invoked to process
events of this event type.
The name of the event handler method is derived from the event name of the event type that will be received by the event handler method.
The method name of the event handler method is derived by adding an on prefix to the event name. The event handler method has one of the
following method signatures:
public void on<event name>(<event class> event, <SBB Part Activity Context Interface interface> activity);public void on<event name>(<event class> event, <SBB Part Activity Context Interface interface> activity, EventContext eventContext);
• The first method signature without an event context argument is used if the SBB does not need access to event context.• The second method signature provides access to the event context associated with the event.• An SBB part can only have one event handler method for each event type.• The event handler method must be declared as public and cannot be static, abstract, or final.
79
Rhino Extended APIs (V2.5.0)
• The event handler method is a mandatory transactional method. Hence, the SLEE always invokes this method within a
transaction.• An SBB part object as an event consumer receives an event on an activity context. This activity context is the activity
context on which the event was fired. In the case of an event handler method, an SBB part activity context interface
object (if the SBB part defines an SBB part activity context interface interface) or a generic activity context interface object
represents the activity context on which the event was fired.• An event context is associated with the event that is fired if the SBB part implements an event handler method that
includes an event context argument. The event context can be used to suspend and resume further event processing of
this event.• The event handler method may return inadvertently by throwing a RuntimeException . See RuntimeException
handling for transactional methods on page 82 for details on how the SLEE handles this situation.
Event handler methods declared by SBB parts have the same rules and restrictions as event handler methods declared by SBBs.
An SBB part can manage the event types that it may receive for a particular activity context which it is attached to, by altering the event mask as
an SBB would. The maskEvent and getEventMask methods defined in the SbbPartContext interface behave identically to the same methods
defined in the SbbContext interface. An individual SBB or SBB part may only mask the events that it receives. For example, an SBB cannot
mask an event received by a dependent SBB part.
5.5.3 Initial event selector methods
An SBB part class may define an initial event selector method for any event declared as an initial event. The behaviour and function of an initial
event selector declared by an SBB part is identical to the behaviour and function of an initial event selector method declared by an SBB. The
method signature of the initial event selector method is as follows:
public InitialEventSelector <initial event selector method name>(InitialEventSelector ies);
• The initial event selector method must be declared as public and cannot be static, abstract, or final.• The method name is declared in the SBB part deployment descriptor. The method name must not begin with sbbPart ,
and must be a valid Java identifier.• This method is a non-transactional method.
80
Rhino Extended APIs (V2.5.0)
• It is only invoked on SBB part objects in the Pooled state.
5.5.4 Exception callback method
The SBB part class may optionally implement a callback method invoked by the SLEE to handle RuntimeExceptions thrown by the SBB
part’s event handler methods and the mandatory transactional lifecycle callback methods: @PostCreate , @PreRemove , @PostLoad , and
@PreStore . This method must be annotated with the @OnException annotation.
• A method annotated with @PreStore must be declared as public and cannot be static, abstract, or final.• This method must declare three arguments in the following order:
1. an Exception argument — this is the exception thrown by one of the methods invoked by the SLEE, such as an
event handler method or a lifecycle method.2. an Object argument — this is the event argument passed to the event handler method, if the exception was
thrown by an event handler method. If the exception was not thrown by an event handler method, this argument
is null .3. an ActivityContextInterface argument — this is the ActivityContextInterface argument passed
to the event handler method, if the exception was thrown by an event handler method. If the exception was
not thrown by an event handler method, this argument is null . The specific type of this argument may be
any subclass of ActivityContextInterface that is assignable to the SBB part’s declared activity context
interface type.• The method must have a void return type, and must not define a throws clause.• This method is a mandatory transactional method.• The SLEE does not invoke this method if a non-transactional method invocation returns by throwing a RuntimeExc
eption .• If this method is invoked on an SBB part object in the Ready state, the state of the SBB part object remains as it was
at the point that the RuntimeException was thrown. The SBB part object moves to the Does Not Exist state after the
@OnException method has been invoked.
81
Rhino Extended APIs (V2.5.0)
A well-written SBB part should not throw any RuntimeExceptions from any of its SLEE invoked methods. Instead, the SBB partshould place the exception handling logic inside a try { } catch (Throwable) clause and handle RuntimeExceptions withineach invoked method.
RuntimeException handling for transactional methods
When a SLEE originated mandatory transactional method is invoked on an SBB part object and the invocation returns with a RuntimeException
thrown, the SLEE performs the following actions:
• The SLEE logs this condition.
• The SLEE marks the transaction of the invocation for rollback.
• The SLEE invokes the @OnException method, if declared, of the same SBB part object with the same transaction. The SBB part
object may be in the Pooled state or in the Ready state. For example, if a @PostCreate method throws the RuntimeException
, then the SBB part object remains in the Pooled state when the SLEE invokes the @OnException method on the SBB part object.
If an event handler method throws the RuntimeException , then the SBB part object remains in the Ready state when the SLEE
invokes the @OnException method on the SBB part object.
• The SLEE moves the SBB part object, along with the owning SBB object and any other dependent SBB part objects, to the Does Not
Exist state.
• If the @OnException method of the SBB part object returns with another RuntimeException thrown, the SLEE logs this condition.
The @OnException method is not reinvoked in this case.
RuntimeException handling for non-transactional methods
When the SLEE invokes a non-transactional method of an SBB part object and the invocation returns by throwing a RuntimeException , the
SLEE performs following sequence of actions:
• The SLEE logs this occurrence.
• The SLEE moves the SBB part object, along with the owning SBB object any other dependent SBB part objects, to the Does Not
Exist state.
82
Rhino Extended APIs (V2.5.0)
5.5.5 Transaction rollback processing
An SBB part object is not involved with transaction rollback processing. If transaction rollback occurs after the SLEE invokes a mandatory
transactional method on an SBB part object, such as an event handler method, the sbbRolledBack callback method will be invoked on an SBB
object of the SBB part’s owning SBB in accordance with the normal SLEE rules for rollback processing.
5.5.6 Method name restrictions
Non-private (such as public, protected, or package private) methods that are defined in an SBB part class must not begin with sbbPart .
5.5.7 Dependency injection
When implementing an SBB part class, the SBB developer has the option to use dependency injection to initialise the value of certain types of
class fields. Dependency injection eliminates the need for the typical boilerplate code associated with the initialisation of these fields.
Dependency injection is supported using the API provided by JSR 330 Dependency Injection for Java , in particular the @javax.inject.Inject
and @javax.inject.Named annotations. Any SBB part class field where dependency injection is required must be annotated with @Inject .
The @Named annotation may also be used, where permitted, to provide an additional parameter to the injector.
The @Inject annotation may be used on SBB part class fields of the following types:
• com.opencloud.rhino.slee.sbbpart.SbbPartContext
• com.opencloud.rhino.cmp.CMPFields , and any type that can be assigned any CMP Extension Interface on page 47 defined
by the SBB part
• javax.slee.facilities.Tracer or com.opencloud.rhino.facilities.Tracer
• The @Named annotation may be used to specify the name of the tracer to assign to the field. The named value must be a valid
SLEE tracer name.
• javax.slee.facilities.ActivityContextNamingFacility
• javax.slee.facilities.AlarmFacility
• javax.slee.facilities.TimerFacility
• javax.slee.profile.ProfileFacility or com.opencloud.rhino.facilities.profile.ProfileFacility
• com.opencloud.rhino.facilities.childrelations.ChildRelationFacility
• com.opencloud.rhino.facilities.usage.UsageFacility
83
Rhino Extended APIs (V2.5.0)
• The UsageFacility is only available to SBB parts that declare at least one usage parameters interface.
• If the SBB part declares a root usage parameter set type, then any type that can be assigned the usage parameters interface
of the root usage parameter set type.
• This field will be assigned the root usage parameter set for the SBB part.
• com.opencloud.rhino.license.LicenseFacility
• javax.slee.profile.ProfileTableActivityContextInterfaceFactory
• javax.slee.nullactivity.NullActivityFactory
• The @Named annotation may be used to indicate the specific type of null activity factory to assign to the field. The named
value must be one of replicated , non-replicated , or the empty string . The empty string results in the default null
activity factory for the service to be used, and is equivalent to omitting the @Named annotation.
• javax.slee.nullactivity.NullActivityContextInterfaceFactory
• javax.slee.serviceactivity.ServiceActivityFactory
• javax.slee.serviceactivity.ServiceActivityContextInterfaceFactory
An injected field must not be static or final. Any access modifier (public, protected, package private, or private) is permitted.
If an SBB part class makes use of dependency injection, the SLEE injects these references after the SBB part object is created; in other words,
after the constructor invocation has returned, and before any other methods are invoked on the object. Fields are injected beginning with the
topmost superclass that requests injection, then working down through each subclass as required.
5.5.8 SBB abstract class abstract method replacements
The SBB abstract class allows the declaration of abstract methods in order to provide various functionality to the SBB code. Since the SBB part
class cannot be abstract, alternative mechanisms are provided so that the same functionality is available to SBB parts. These mechanisms are
described below.
Per-instance state
An SBB declares its per-instance state by defining abstract getter and setter methods in the SBB abstract class and indicating that they relate
to CMP fields using <cmp-field> entries in the SBB deployment descriptor. Rhino also allows an SBB to declare CMP fields using CMP
extension interfaces on page . An SBB part can also define its per-instance state using CMP extension interfaces. The SBB part obtains
84
Rhino Extended APIs (V2.5.0)
access to the CMP fields defined in CMP extension interfaces using a com.opencloud.rhino.cmp.CMPFields object, obtainable from its
SbbPartContext object. The CMPFields object may be typecast to any CMP extension interface declared by the SBB part, thus exposing the
CMP field accessor methods defined by the interface.
Activity context interface narrow method
An SBB that declares an activity context interface that is a subtype of javax.slee.ActivityContextInterface is expected to
define an abstract activity context interface narrow method in the SBB abstract class. This method converts or "narrows" a generic
javax.slee.ActivityContextInterface object to an object implementing the SBB’s activity context interface. An SBB part that
declares an activity context interface that is a subtype of javax.slee.ActivityContextInterface can similarly narrow a generic
javax.slee.ActivityContextInterface object using the asSbbPartActivityContextInterface method on its SbbPartContext
object. This method returns an activity context interface object that implements the SBB part’s declared activity context interface.
Child relations
For each child relation that an SBB has, an abstract child relation accessor method must be declared in the SBB abstract class. This method
returns a javax.slee.ChildRelation object that allows child SBBs to be created, inspected, and removed.
As SBB parts cannot declare their own SBB child relations, SBB parts do not need to define child relation accessor methods.
Profile CMP interface accessor method
The profile CMP interface accessor method was deprecated in the JAIN SLEE 1.1 specification. As a replacement, SBBs can use the profile
facility and ProfileTable objects to query and access profiles.
There is no equivalent to the profile CMP interface accessor method for SBB parts. Like SBBs, SBB parts can use the profile facility to query and
access profiles.
Usage parameters interface accessor methods
An SBB that declares a usage parameters interface is expected to declare at least one abstract usage parameters interface accessor method in
the SBB abstract class. This method returns an object implementing the SBB’s usage parameters interface allowing usage statistics for the SBB to
be accumulated.
Rhino provides an extension mechanism on page 94 that allows an SBB to declare more than one usage parameters interface, and defines
a usage facility with which SBBs can manage and access their usage parameter sets. the usage facility eliminates the need for an SBB to
85
Rhino Extended APIs (V2.5.0)
declare the usage parameters interface accessor methods. An SBB part may also declare usage parameters interfaces using the same extension
mechanism, and also may manage and access the SBB’s usage parameter sets using the usage facility.
Fire event methods
If an SBB needs to fire an event as part of its application logic, it must declare an abstract fire event method to do so. Event firing is not supported
for SBB parts, so an SBB part has no equivalent to a fire event method.
5.6 SbbPartContext interface
The SLEE provides each SBB part object, if requested through an SBB part class constructor argument or dependency injection, with an
SbbPartContext object. The SbbPartContext object gives the SBB part object access to the SBB part object’s context maintained by the
SLEE, allows the SBB part object to invoke functions provided by the SLEE, and obtains information about the SBB entity assigned to the SBB
part object.
An SbbPartContext object is associated with one service and one SBB; and the associated service and SBB do not change during the lifetime
of that SbbPartContext object.
The SbbPartContext object implements the SbbPartContext interface. The SbbPartContext interface extends the JAIN SLEE defined
SbbContext interface with additional functionality, as described below.
5.6.1 Methods inherited from SbbContext
The methods inherited from the JAIN SLEE defined SbbContext interface have the same meaning and purpose when used by SBB parts.
5.6.2 SbbPartContext interface getSbbPart method
The getSbbPart method returns an SbbPartID object that encapsulates the component identity of the SBB part.
5.6.3 SbbPartContext interface getTracer method
The getTracer method overrides the same method from SbbContext to return a Rhino-specific extension of the Tracer interface.
86
Rhino Extended APIs (V2.5.0)
For more about this Tracer extension, please see SLEE Facilities on page 90 .
5.6.4 SbbPartContext interface asSbbPartActivityContextInterface method
The asSbbPartActivityContextInterface method is used by the SBB part to narrow an object that implements the generic
ActivityContextInterface to an object that implements the SBB part activity context interface so that the SBB part can access the activity
context interface attributes defined in the SBB part activity context interface.
This method takes as its input parameter an activity context interface object and returns an object that implements the SBB part activity context
interface interface of the SBB part. The SBB part activity context interface interface provides the accessor methods that allow an SBB part object
to access the shareable attributes of the SBB part that are stored in the activity context interface.
If the SBB part does not define an SBB part activity context interface interface, then this method returns the same object passed in as a
parameter.
5.6.5 SbbPartContext interface getActivities methods
The SbbPartContext interface defines two getActivities methods:
• getActivities() — This method overrides the same method from SbbContext to return a Rhino-specific extension of
the ActivityContextInterface interface. Otherwise, this method behaves in the same way as defined by the JAIN SLEE
specification for SBBs.
For more about this ActivityContextInterface extension, please see Miscellaneous SLEE API Enhancements on page 55 .
• getActivities(Class) — This method behaves similarly to the no-argument version; however it only returns activity context
interface objects where the type of the underlying activity object is assignable to the class argument. For example, if this method was
invoked with NullActivity.class as an argument, then only activity context interface objects for the null activities the SBB entity
currently associated with the SBB part is attached to would be returned.
87
Rhino Extended APIs (V2.5.0)
5.6.6 SbbPartContext interface getConvergenceName method
The getConvergenceName method returns the convergence name that the SBB entity the SBB part is associated with was created with. The
value returned from this method is a vendor-specific string that uniquely identifies the initial event selector conditions that led to the SBB entity’s
creation.
This method only returns a non- null value if invoked on an SbbPartContext object belonging to a root SBB entity.
5.6.7 SbbPartContext interface getCMPFields method
The getCMPFields method provides the SBB part with access to its per-instance state on page 84 .
5.6.8 SbbPartContext interface getJndiBindings method
The getJndiBindings method returns a map describing the JNDI bindings available to the SBB part.
For more about this method, please see SLEE Facilities on page 90 .
5.7 SBB part component environment
An SBB part has access to the same JNDI environment bindings as its owning SBB. All the SLEE facilities, environment entries, and resource
adaptor type bindings that are available to an SBB are also available to all its dependent SBB parts. An SBB part accesses its JNDI environment
in exactly the same way as an SBB.
The current specification of SBB parts does not yet allow an SBB part component to declare its own environment entries. An SBB part component
may however define its own resource adaptor type bindings.
5.8 SBB part example
Below is an example of an SBB part class. The SBB part declares an event handler method that receives a SLEE timer event, which logs the
event and increments a CMP field and a usage counter:
import javax.inject.Inject;
88
Rhino Extended APIs (V2.5.0)
import javax.inject.Named;import javax.slee.CreateException;import javax.slee.facilities.TimerEvent;import com.opencloud.rhino.facilities.Tracer;import com.opencloud.rhino.slee.lifecycle.PostCreate;
public class ExampleSbbPart {public void onCreate() throws CreateException {rootTracer.info("SBB part created");}
public void onTimerEvent(TimerEvent event, ExampleSbbPartActivityContextInterface aci) {int count = cmpFields.getCounter() + 1;
timerTracer.info("received timer event: " + count);
cmpFields.setCounter(count);
rootUsage.incrementTimerEvents(1);
...}
private Tracer rootTracer;
@Inject @Named("timer")private Tracer timerTracer;
private ExampleSbbPartCMPInterface cmpFields;
private ExampleSbbPartUsageInterface rootUsage;}
89
Rhino Extended APIs (V2.5.0)
6 SLEE Facilities
Rhino provides many extensions to the standard facilities and application functions provided by the JAIN SLEE specification, as detailed below.
6.1 SBB child relations
The JAIN SLEE specification defines that an SBB child relation requires:
• an abstract get child relation method declared in the SBB abstract class; and
• a <get-child-relation-method> deployment descriptor entry that binds the get child relation method to a particular SBB type.
The get child relation method returns a ChildRelation object, which the SBB developer uses to create, remove, or manage the SBBs in the
child relation.
A difficulty with this approach is that child relations cannot be added to an SBB without code changes to the SBB abstract class. For example,
consider an SBB that delegates call processing to different child SBBs based on the protocol in use for the call (CAPv2, CAPv3, ETSI INAP CS1,
and so on). Since the child SBB for each protocol needs its own get child relation method in the SBB abstract class, it’s not easy to decide at build
time what protocols will be supported without modifying the SBB abstract class and recompiling. Code changes are also extremely undesirable
when service bindings on page 21 are used to change the child relationships of the SBB after the SBB has been installed in the SLEE.
Rhino provides an alternative mechanism to declare and use SBB child relations, which eliminates the recompilation part of the build cycle in
these types of use cases. Child relations are still declared in the deployment descriptor, but the SBB accesses the child relations using a Child
Relation Facility provided by the SLEE.
6.1.1 Extended child relation declarations
Rhino allows an SBB to declare a child relation with an extension deployment descriptor entry only; in other words, no corresponding get child
relation method is needed in the SBB abstract class. As such, these child relations are termed "declarative" child relations, to differentiate them
from the standard child relations defined by the SLEE specification. Declarative child relations may be added to or removed from an SBB without
the need to recompile any code.
90
Rhino Extended APIs (V2.5.0)
Declarative child relations are declared in the oc-sbb-jar.xml extension deployment descriptor using the <child-relations> element. The
child-relations element contains a child-relation element that defines each declarative child relation. A child-relation element
contains the following sub-elements:
Sub-element What it does
description Provides information ( optional ).
child-relation-name Defines the name of the declarative child relation. The SBB uses this name with the Child Relation Facility to
access the child relation. This name must be unique within the scope of the SBB’s declarative child relations.
sbb-alias-ref References an SBB by its sbb-alias that is specified within the corresponding sbb element in the standard
sbb-jar.xml deployment descriptor. This element defines the type of the child SBB.
default-priority Specifies the default event delivery priority of the child SBB relative to its sibling SBBs.
6.1.2 Child Relation Facility
The Child Relation Facility is a Rhino extension that is used by SBBs to gain access to their declarative child relations. The Child Relation Facility
bypasses the need for the SBB developer to declare a get child relation method in the SBB abstract class for each child SBB that the SBB desires.
ChildRelationFacility interface
SBB objects access the Child Relation Facility through a ChildRelationFacility object that implements the ChildRelationFacility
interface. A ChildRelationFacility object can be obtained from the SBB’s RhinoSbbContext on page 55 object (an extension of the standard
SbbContext object).
The ChildRelationFacility interface is as follows:
package com.opencloud.rhino.facilities.childrelations;
import java.util.Collection;import javax.slee.ChildRelation;import javax.slee.SbbLocalObject;
91
Rhino Extended APIs (V2.5.0)
import javax.slee.TransactionRequiredLocalException;import javax.slee.facilities.FacilityException;import com.opencloud.rhino.slee.RhinoSbbContext;import com.opencloud.rhino.slee.RhinoSbbLocalHome;
public interface ChildRelationFacility { public Collection<String> getChildRelationNames() throws FacilityException;
public ChildRelation getChildRelation(String name) throws NullPointerException, TransactionRequiredLocalException, IllegalStateException, UnrecognizedChildRelationException, FacilityException;
public Collection<SbbLocalObject> getChildSbbs() throws TransactionRequiredLocalException, IllegalStateException, FacilityException;
public <T> Collection<T> getChildSbbs(Class<T> type) throws NullPointerException, TransactionRequiredLocalException, IllegalStateException, FacilityException;
public RhinoSbbLocalHome getChildSbbLocalHome(String name) throws NullPointerException, UnrecognizedChildRelationException, FacilityException;}
• All methods of the ChildRelationFacility interface, except for the getChildRelationNames method and the
getChildSbbLocalHome method, are required transactional methods. The getChildRelationNames method and
the getChildSbbLocalHome method are non-transactional.• The SLEE provides a concrete class implementing the ChildRelationFacility interface.• The methods of this interface throw the javax.slee.facilities.FacilityException if the requested operation
cannot be completed because of a system-level failure.
6.1.3 ChildRelationFacility interface getChildRelationNames method
The getChildRelationNames method returns the set of declarative child relation names declared by the SBB. Each name contained by this set
corresponds with a name contained by a <child-relation-name> element in the oc-sbb-jar.xml extension deployment descriptor.
92
Rhino Extended APIs (V2.5.0)
6.1.4 ChildRelationFacility interface getChildRelation method
The getChildRelation method returns a standard ChildRelation object for the named declarative child relation. The specified name
argument must be one of the names contained by the <child-relation-name> elements in the oc-sbb-jar.xml extension deployment
descriptor; that is, it must be one of the names contained in the set of names returned by the getChildRelationNames method.
This method performs the same function as the get child relation methods declared in the SBB abstract class for standard JAIN SLEE child
relation declarations. A ChildRelation object returned from this method can be used in exactly the same way as a ChildRelation object
returned by a get child relation method.
This method throws a NullPointerException if the name argument is null . If the name argument does not correspond with a declarative
child relation, then this method throws an UnrecognizedChildRelationException . If this method is invoked without a valid transaction
context, then the method throws a TransactionRequiredLocalException . If the method is invoked by an SBB object that is not assigned to
an SBB entity, then the method throws an IllegalStateException .
6.1.5 ChildRelationFacility interface getChildSbbs methods
The getChildSbbs methods each return a collection of child SBB local interface objects. The no-argument variant returns a collection of all child
SBBs. The one-argument variant returns a collection of all child SBBs where the child SBB’s local interface is assignable to the specified Class
argument. Both these methods will consider all SBB child relations; that is, child relations declared both in the standard JAIN SLEE manner and
declarative child relations.
If either of these methods are invoked without a valid transaction context then a TransactionRequiredLocalException is thrown. If invoked
by an SBB object that is not assigned to an SBB entity, then an IllegalStateException is thrown. If the one-argument method variant is
invoked with a null argument, then the method throws a NullPointerException .
6.1.6 ChildRelationFacility interface getChildSbbLocalHome method
The getChildSbbLocalHome method returns an object implementing the local home interface of the child SBB of the named declarative child
relation. For more information on SBB local home interfaces, please see Miscellaneous SLEE Application API Enhancements on page 55 .
This method throws a NullPointerException if the name argument is null . If the name argument does not correspond with a declarative
child relation, then this method throws an UnrecognizedChildRelationException .
93
Rhino Extended APIs (V2.5.0)
6.2 Usage extensions
The JAIN SLEE specification allows SLEE components such as SBBs and resource adaptors to define a single usage parameters interface for
the collection of runtime statistics. Statistics may be collected in different usage parameter sets — essentially named buckets each containing
the same set of usage parameters as defined by the usage parameters interface. Creation and removal of named usage parameter sets is only
supported through JMX management clients.
When building large SLEE applications or complex resource adaptors, the limitations of the SLEE-defined usage mechanism quickly becomes
apparent. A single usage parameters interface lacks flexibility, and means that statistics from all parts of the system need to be lumped into
a single view; and the inability of an application to be able to control its own named usage parameter sets can create a discord between any
dynamic application behaviour and usage parameter set management requirements.
To alleviate these problems, Rhino provides a usage extension mechanism that allows an SBB or resource adaptor to declare multiple usage
parameters interfaces, and defines a usage facility with which SBBs and resource adaptors can manage and access their own usage parameter
sets. This section describes that extension mechanism.
6.2.1 Usage parameter types
The JAIN SLEE specification defines two types of usage parameters: counter-type and sample-type. Rhino’s extension mechanism does not add
any new type of usage parameter, but does allow counter-type usage parameters to be set to a specific value rather than only incremented or
decremented.
6.2.2 Usage parameter sets
A usage parameter set is a set that contains a usage parameter for each usage parameter name declared in the usage parameters interface of the
corresponding SLEE component. Each method of the usage parameters interface declares the usage parameter name and type of a single usage
parameter in this set. A SLEE component that generates usage information may access multiple usage parameters with the same lowest-level
usage parameter name component, by using multiple usage parameter sets. The JAIN SLEE specification defines: a default usage parameter set,
automatically available to any SLEE component that defines a usage parameters interface; and named usage parameter sets — which can also
be used by the SLEE component, but can only be created and removed using the JMX management interface. Usage parameter sets in the JAIN
SLEE specification occupy a flat namespace, and there is no relationship between any two usage parameter sets.
94
Rhino Extended APIs (V2.5.0)
Rhino’s extension mechanism introduces a hierarchical structure and namespace for usage parameter sets. The SLEE-defined default usage
parameter set is replaced with a root usage parameter set, and each usage parameter set can have zero or more child usage parameter sets. A
usage parameter set name must be unique amongst its sibling usage parameter sets, but in any other case usage parameter set names may be
reused.
A SLEE component creates, removes, or otherwise manages its own usage parameter sets itself using the Usage Facility and the methods
defined on the Usage Parameter Interfaces .
6.3 Usage parameter set types
Each usage parameter set may or may not have a type. Usage parameter set types are declared in the deployment descriptor, each with a
corresponding usage parameters interface. A usage parameter set with no type has no usage parameters, and can be used as a structural
placeholder in the usage parameter set hierarchy.
The type of the root usage parameter set is also declared in the deployment descriptor. This declaration is optional. If declared, the root usage
parameter set will be created with the specified type; otherwise the root usage parameter set will be created with no type.
The type of a child usage parameter set is specified at runtime when the usage parameter set is created by the SLEE component. A child usage
parameter set may be created with any recognised usage parameter set type, or may be created with no type.
A SLEE component must declare at least one usage parameter set type in order to use the usage facility and manage its usage parameter sets.
6.4 Aggregation and extension
Under certain conditions, a usage parameter update to a usage parameter set may aggregate to its parent usage parameter set. Aggregation
simply means that the update is also applied to the parent usage parameter set, and then its parent, and so on, so long as an aggregation
relationship holds between the parent and child usage parameter sets, or the root usage parameter set is reached. Aggregation is useful, for
example, to record total usage in a parent usage parameter set where individual child usage parameter sets record usage for different conditions,
such as the triggering protocol of the session.
Aggregation for a given usage parameter name can only occur from a child usage parameter set to a parent usage parameter set if:
• the parent usage parameter set and the child usage parameter set have the same usage parameter set type; or
95
Rhino Extended APIs (V2.5.0)
• the child usage parameter set type extends, either directly or indirectly, the parent usage parameter set type; and both usage
parameter set types declare a usage parameter of the same type (counter-type or sample-type) with that usage parameter name.
Usage parameter set type extension is declarative rather than programmatic. A usage parameter set type declares in the deployment descriptor
if it extends another usage parameter set type. The usage parameters interface of a usage parameter set type that extends another usage
parameter set type is not required to extend or otherwise be related in any way to the usage parameters interface of the extended usage
parameter set type. As long as the two usage parameters interfaces declare a usage parameter with the same name and type (counter-type or
sample-type), then aggregation may occur between the two usage parameter set types for that usage parameter name.
Aggregation is enabled by default for all usage parameters. Aggregation can be disabled on a per usage parameter name basis using the relevant
annotation on page 100 on each usage parameters interface usage parameter method declaration.
6.5 Usage parameters interfaces
SLEE components declare their usage parameters using one or more usage parameters interfaces. Each usage parameters interface must be
defined according to the following rules:
• A usage parameters interface must be defined in a named package; in other words, the class must have a package declaration.
• A usage parameters interface must be declared as public .
• A usage parameters interface may optionally extend the
com.opencloud.rhino.facilities.usage.UsageParametersInterface interface.
• Each increment, set, or sample method within the usage parameters interface must declare a lowest-level usage parameter name
relevant to the SLEE component.
• The SLEE derives the usage parameter type associated with this usage parameter name from the method name of the
declared method.
• Each get accessor method within the usage parameters interface provides access to the current approximate value or sample
statistics for the lowest-level usage parameter name.
• A single usage parameter name can only be associated with a single usage parameter type. The SLEE will reject a usage parameters
interface that declares both a sample method and an increment or set method for the same usage parameter name.
96
Rhino Extended APIs (V2.5.0)
• It is legal to declare both increment and set methods for the same usage parameter name. These two methods simply offer
alternative ways to update the same counter-type usage parameter.
• A usage parameter name must be a valid Java identifier and begin with a lowercase letter, as determined by
java.lang.Character.isLowerCase .
Counter-type usage parameter increment methods, sample-type usage parameter sample methods, and all usage parameter accessor methods,
are declared in the usage parameters interface as defined in the SLEE specification.
6.6 Counter-type usage parameter set method
A usage parameter set method must be defined in the usage parameters interface to declare the presence of and to permit updates to a counter-
type usage parameter. The method name of the set method is derived by adding a "set" prefix to the usage parameter name. The set method has
the following method signature:
public abstract void set<usage parameter name>(long value);
• The set method must be declared as public and abstract.• The first letter of the usage parameter name is uppercased in the definition of the set method.• The set method does not have a throws clause.• This method runs in an unspecified transaction context. Counter-type usage parameter updates do not require an active
transaction. Counter-type usage parameter updates occur regardless of the outcome of any transaction active at the time
of the update. If multiple threads update the same usage parameter at the same time, these updates are applied as if the
updates were serial.• The method throws a javax.slee.SLEEException if the requested operation cannot be performed due to a system-
level failure.
97
Rhino Extended APIs (V2.5.0)
6.7 UsageParametersInterface interface
A usage parameters interface may optionally extend the UsageParametersInterface . By extending this interface, a usage parameters
interface provides its corresponding usage parameter sets with easy access to methods reporting metadata about themselves and methods to
manage their child usage parameter sets. The UsageParametersInterface is shown below:
package com.opencloud.rhino.facilities.usage;
import java.util.Collection;import javax.slee.SLEEException;import javax.slee.usage.SampleStatistics;
public interface UsageParametersInterface { public String name(); public String type(); public String key(); public <T extends UsageParametersInterface> T getOrCreateChild(String name) throws NullPointerException, IllegalArgumentException, SLEEException; public <T extends UsageParametersInterface> T getOrCreateChild(String name, String type) throws NullPointerException, IllegalArgumentException, UnrecognizedUsageParameterSetTypeException, SLEEException; public boolean hasChild(String name) throws NullPointerException, SLEEException; public Collection<? extends UsageParametersInterface> children() throws SLEEException; public <T extends UsageParametersInterface> T parent() throws SLEEException; public void remove() throws SLEEException;}
All methods in the UsageParametersInterface are non-transactional methods; that is, they do not require an active transaction to return a
successful result, and their effects persist regardless of the outcome of any transaction active at the time of the method call.
The methods throw a SLEEException if the requested operation cannot be performed due to a system-level failure.
98
Rhino Extended APIs (V2.5.0)
6.7.1 UsageParametersInterface interface name method
The name method returns the name of the usage parameter set that the UsageParametersInterface object is providing usage access to. This
name is the name that the usage parameter set was created with. The root usage parameter set has no name; therefore this method will return
null if invoked on the root usage parameter set.
6.7.2 UsageParametersInterface interface type method
The type method returns the type name of the usage parameter set that the UsageParametersInterface object is providing usage access to.
If the usage parameter set was created with no type, this method returns null .
6.7.3 UsageParametersInterface interface key method
The key method returns a unique identifier that identifies the usage parameter set that the UsageParametersInterface object is providing
usage access to. The key differs from the parameter set name in that the key is an absolute identifier that takes into account the usage parameter
set’s place in the usage parameter set hierarchy, and is able to identify the usage parameter set without any other context; whereas the usage
parameter set name is relative to the usage parameter set’s parent usage parameter set only.
6.7.4 UsageParametersInterface interface getOrCreateChild methods
The getOrCreateChild methods return the child usage parameter set with the name specified by the name argument. If the usage parameter
set already exists, then the existing usage parameter set is returned; otherwise a new usage parameter set is created. If a new usage parameter
set is created, and the type argument is specified, then the child usage parameter set is created with the specified type; otherwise it is created
with the same type as the usage parameter set the method is invoked on.
These methods throw a NullPointerException if the name argument is null . The methods throw an IllegalArgumentException if the
name argument is zero-length. If the type argument is specified and not null , but is not recognised as a defined usage parameters interface
type, the method throws an UnrecognizedUsageParameterSetTypeException .
6.7.5 UsageParametersInterface interface hasChild method
The hasChild method returns a Boolean value indicating if a child usage parameter set with a name equal to the name argument currently exists.
This method throws a NullPointerException if the name argument is null .
99
Rhino Extended APIs (V2.5.0)
6.7.6 UsageParametersInterface interface children method
The children method returns a collection containing all the child usage parameter sets of the usage parameter set that the
UsageParametersInterface object is providing usage access to.
6.7.7 UsageParametersInterface interface parent method
The parent method returns the usage parameter set that is the parent of the usage parameter set that the UsageParametersInterface
object is providing usage access to. If the UsageParametersInterface object represents the root usage parameter set, then this method
returns null .
6.7.8 UsageParametersInterface interface remove method
The remove method removes the usage parameter set that the UsageParametersInterface object is providing usage access to. All child
usage parameter sets are also removed, recursively.
The root usage parameter set cannot be removed; however, this method may be invoked on a root usage parameter set, in which case the
following behaviour is observed:
• All child usage parameter sets are removed as usual.
• All usage parameters in the root usage parameter set are reset to their initial value, as if the root usage parameter set had been
removed and recreated in a single atomic action.
6.8 Annotations
A usage parameters interface and its usage parameter methods may all be annotated to provide additional information to Rhino’s statistics and
SNMP subsystems. This is supported in both the SLEE-defined usage mechanism and Rhino’s extension mechanism. Information provided to the
statistics subsystem helps clients display statistics appropriately, whereas information provided to the SNMP subsystem is used to configure the
OIDs included in SNMP notifications for usage parameter set updates.
6.8.1 @UsageParameters annotation
A usage parameters interface may be annotated with the @UsageParameters annotation. The @UsageParameters annotation is shown below:
100
Rhino Extended APIs (V2.5.0)
package com.opencloud.rhino.facilities.usage;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface UsageParameters { String description() default ""; String oid() default "";}
• The description parameter provides a general description for the usage parameters interface.• The oid parameter defines the base SNMP Object Identifier (OID) to use for all the usage parameter sets created from
the usage parameters interface. The base OID must be specified using dotted string notation, such as 1.3.6.1.4.
1.19808.2.1.1001 . If a base OID is not specified, or is specified as a zero-length string, then a base OID is
dynamically generated for the usage parameters interface. See SNMP statistics for OID detailed explanation.
When installing a SLEE component that has default oid parameter specified, please make sure the base oid mapping is not in-use.Otherwise a duplicate oid mapping alarm will be raised. If the mapping is in-use, rhino console commands setsnmpoidmapping orremovesnmpmappingconfig can be used to clear/remove it.
6.8.2 @UsageCounter annotation
A counter-type usage parameter increment or set method may be annotated with the @UsageCounter annotation. The @UsageCounter
annotation is shown below:
package com.opencloud.rhino.facilities.usage;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface UsageCounter { String description() default ""; CounterType counterType();
101
Rhino Extended APIs (V2.5.0)
boolean aggregate() default true; String shortName() default ""; String unitLabel() default ""; int mapping() default -1;}
• The description parameter provides a general description for the usage parameter.• The counterType parameter identifies the specific type of counter that the usage parameter represents. A counter-type
usage parameter may be one of the following subtypes:
• counter — an unbounded counter that typically only either increments or decrements.• gauge — a counter that typically has a lower and/or upper bound with a value that may oscillate within the
bounds.• The aggregate parameter indicates whether or not updates to the usage parameter may aggregate on page 95 to
the parent usage parameter set.• The shortName parameter defines a short, possibly abbreviated version of the usage parameter name.• The unitLabel parameter specifies a label for the counter’s unit type.• The mapping parameter specifies a numeric SNMP ID for the usage parameter. This ID is appended to the usage
parameter interface’s base SNMP OID to form the OID of the usage parameter. Defining a static ID for each usage
parameter can eliminate renumbering issues if the usage parameters interface is later expanded with new usage
parameters.
If both an increment method and a set method are defined for a single counter-type usage parameter, and both methods are annotated with
@UsageCounter , then Rhino will arbitrarily choose one of the annotations to use for the usage parameter, and ignore the other annotation. In
this case it is recommended only one of the methods be annotated.
6.8.3 @UsageSample annotation
A sample-type usage parameter sample method may be annotated with the @UsageSample annotation. The @UsageSample annotation is shown
below:
package com.opencloud.rhino.facilities.usage;
102
Rhino Extended APIs (V2.5.0)
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface UsageSample { String description() default ""; SampleUnits sourceUnits(); SampleUnits displayUnits(); boolean aggregate() default true; String shortName() default ""; String unitLabel() default "";}
• The description parameter provides a general description for the usage parameter.• The sourceUnits parameter identifies the units that the sample values are recorded with. Units must be one of: time in
seconds, time in milliseconds, time in nanoseconds, or a dimensionless count.• The displayUnits parameter identifies the units with which the sample statistics should be displayed.
• This parameter has no effect on how sample values are reported when using a JMX Usage MBean interface
to inspect usage parameters. The parameter is only meaningful to statistics clients using Rhino’s proprietary
statistics API.• The aggregate parameter indicates whether or not updates to the usage parameter may aggregate on page 95 to
the parent usage parameter set.• The shortName parameter defines a short, possibly abbreviated, version of the usage parameter name.• The unitLabel parameter specifies a label for the sample’s unit type.
6.9 SBB usage parameters interface deployment descriptor
If an SBB declares one or more usage parameters interfaces using the Rhino usage extension mechanism, the oc-sbb-jar.xml Rhino
extension deployment descriptor of the SBB must identify the usage parameters interfaces. The sbb-usage-parameters-interfaces
element of the SBB extension deployment descriptor identifies these interfaces. It contains the following sub-elements:
103
Rhino Extended APIs (V2.5.0)
Sub-element What it does
description This is an optional informational element.
sbb-usage-parameters-interface Each usage parameters interface type defined by the SBB must be identified by a
sbb-usage-parameters-interface element.
Each sbb-usage-parameters-interface element has the following attributes and sub-elements:
Sub-element or attribute What it does
root This attribute indicates if this usage parameters interface should be used as the root
usage parameter set type on page 94 . At most one usage parameters interface
may be declared as the root usage parameter set type.
description This is an optional informational element.
sbb-usage-parameters-interface-type This element specifies the usage parameters interface type name. This type name
identifies the usage parameters interface when creating new child usage parameter
sets. Each usage parameters interface declared in the deployment descriptor must
have a unique type name.
sbb-usage-parameters-interface-name This element identifies the interface name of the usage parameters interface.
The sbb-usage-parameters-interface-type element has the following attribute:
Attribute What it does
extends This attribute indicates if the usage parameters interface type extends on page 95
another usage parameters interface type. The extends attribute contains the type
104
Rhino Extended APIs (V2.5.0)
name of the usage parameters interface that this usage parameters interface type
extends.
6.10 Resource adaptor usage parameters interface deployment descriptor
If a resource adaptor declares one or more usage parameters interfaces using the Rhino usage extension mechanism, the oc-resource-
adaptor-jar.xml Rhino extension deployment descriptor of the resource adaptor must identify the usage parameters interfaces. The
resource-adaptor-usage-parameters-interfaces element of the resource adaptor extension deployment descriptor identifies these
interfaces. It contains the following sub-elements:
Sub-element What it does
description This is an optional informational element.
resource-adaptor-usage-parameters-interface Each usage parameters interface type defined by the resource adaptor
must be identified by a resource-adaptor-usage-parameters-
interface element.
Each resource-adaptor-usage-parameters-interface element has the following attributes and sub-elements:
Sub-element or attribute What it does
root This attribute indicates if this usage parameters interface should be used as the root
usage parameter set type on page 95 . At most one usage parameters interface
may be declared as the root usage parameter set type.
description This is an optional informational element.
resource-adaptor-usage-parameters-interface-type
This element specifies the usage parameters interface type name. This type name
identifies the usage parameters interface when creating new child usage parameter
105
Rhino Extended APIs (V2.5.0)
sets. Each usage parameters interface declared in the deployment descriptor must
have a unique type name.
resource-adaptor-usage-parameters-interface-name
This element identifies the interface name of the usage parameters interface.
The resource-adaptor-usage-parameters-interface-type element has the following attribute:
Attribute What it does
extends This attribute indicates if the usage parameters interface type extends on page 95
another usage parameters interface type. The extends attribute contains the type
name of the usage parameters interface that this usage parameters interface type
extends.
6.11 Usage facility
The usage facility is used by SBBs and resource adaptors to obtain access to their root usage parameter set and to create and manage child
usage parameter sets. The usage facility is defined by the com.opencloud.rhino.facilities.usage.UsageFacility interface. An SBB
obtains access to a UsageFacility object using a JNDI name lookup. A resource adaptor obtains access to a UsageFacility object from the
ConfigProperties object passed to it by the SLEE.
A UsageFacility object is only made available to SLEE components that declare usage parameter interfaces using the Rhino usage extension
mechanism. A SLEE component that does not declare any usage parameters interface, or declares a usage parameters interface using the SLEE-
defined mechanism, will not be able to access the usage facility.
6.11.1 UsageFacility interface
The com.opencloud.rhino.facilities.usage.UsageFacility interface is shown below:
package com.opencloud.rhino.facilities.usage;
import java.util.Collection;
106
Rhino Extended APIs (V2.5.0)
import javax.slee.facilities.FacilityException;
public interface UsageFacility { public static final String JNDI_NAME = "java:comp/env/slee/facilities/usage"; public static final String CONFIG_PROPERTY_NAME = "slee-vendor:com.opencloud.rhino.facilities.usage";
public <T extends UsageParametersInterface> T getRootUsageParameterSet();
public <T extends UsageParametersInterface> T getUsageParameterSet(String key) throws NullPointerException, UnrecognizedUsageParameterSetException, FacilityException;
public <T extends UsageParametersInterface> T getOrCreateChild(UsageParametersInterface parent, String name) throws NullPointerException, IllegalArgumentException, UnrecognizedUsageParameterSetException, FacilityException;
public <T extends UsageParametersInterface> T getOrCreateChild(UsageParametersInterface parent, String name, String type) throws NullPointerException, IllegalArgumentException, UnrecognizedUsageParameterSetException, UnrecognizedUsageParameterSetTypeException, FacilityException;
public boolean hasChild(UsageParametersInterface parent, String name) throws NullPointerException, UnrecognizedUsageParameterSetException, FacilityException;
public Collection<? extends UsageParametersInterface> getChildren(UsageParametersInterface parent) throws NullPointerException, FacilityException;
public void removeUsageParameterSet(UsageParametersInterface paramSet) throws NullPointerException, UnrecognizedUsageParameterSetException, FacilityException;}
• The JNDI_NAME constant specifies the JNDI location where a UsageFacility object may be located by an SBB
component in its component environment.• The CONFIG_PROPERTY_NAME constant specifies the configuration property name where a UsageFacility object
may be located by a resource adaptor component in the ConfigProperties object passed to it in the raVerifyCo
nfiguration , raConfigure , and raConfigurationUpdate methods.
107
Rhino Extended APIs (V2.5.0)
• All methods of the UsageFacility interface are non-transactional methods.• The SLEE provides a concrete class implementing the UsageFacility interface.• The methods of this interface throw the javax.slee.facilities.FacilityException if the requested operation
cannot be completed because of a system-level failure.
6.11.2 UsageFacility interface getRootUsageParameterSet method
The getRootUsageParameterSet method returns the root usage parameter set for the SLEE component. If the SLEE component declares a
root usage parameter set type, then the object returned from this method will be castable to the corresponding usage parameters interface for that
type.
6.11.3 UsageFacility interface getUsageParameterSet method
The getUsageParameterSet method returns the usage parameter set with the key specified by the key argument. A usage parameter set’s
identifying key can be obtained using the key on page 99 method of the UsageParametersInterface interface.
The usage parameter set object returned from this method will be castable to the usage parameters interface corresponding with its type, as
returned by the type on page 99 method of the UsageParametersInterface interface.
This method throws a NullPointerException if the key argument is null . The method throws an
UnrecognizedUsageParameterSetException if no usage parameter set currently exists with the specified key.
6.11.4 UsageFacility interface getOrCreateChild methods
The getOrCreateChild methods return the child usage parameter set of the usage parameter set specified by the parent argument with the
name specified by the name argument. If the usage parameter set already exists, then the existing usage parameter set is returned; otherwise a
new usage parameter set is created. If a new usage parameter set is created, and the type argument is specified, then the child usage parameter
set is created with the specified type; otherwise it is created with the same type as the usage parameter set the method is invoked on.
These methods throw a NullPointerException if the name argument is null . The methods throw an
UnrecognizedUsageParameterSetException if the parent argument is not recognised by this usage facility object, for example if the
usage parameter set was created by some other usage facility object. The methods throw an IllegalArgumentException if the name
108
Rhino Extended APIs (V2.5.0)
argument is zero-length. If the type argument is specified and not null , but is not recognised as a defined usage parameters interface type, the
method throws an UnrecognizedUsageParameterSetTypeException .
6.11.5 UsageFacility interface hasChild method
The hasChild method returns a boolean value indicating if the usage parameter set identified by the parent argument contains a child usage
parameter set with a name equal to the name argument.
This method throws a NullPointerException if the name argument is null . This method throws an
UnrecognizedUsageParameterSetException if the parent argument is not recognised by this usage facility object, for example if the
usage parameter set was created by some other usage facility object.
6.11.6 UsageFacility interface getChildren method
The getChildren method returns a collection containing all the child usage parameter sets of the usage parameter set identified by the parent
argument.
This method throws a NullPointerException if the parent argument is null .
6.11.7 UsageFacility interface removeUsageParameterSet method
The getRootUsageParameterSet method removes the usage parameter set identified by the paramSet argument. All child usage parameter
sets are also removed, recursively.
This method throws a NullPointerException if the paramSet argument is null . This method throws an
UnrecognizedUsageParameterSetException if the paramSet argument is not recognised by this usage facility object, for example if the
usage parameter set was created by some other usage facility object.
6.12 Profile facility extensions
Rhino extends the standard javax.slee.facilities.ProfileFacility interface with the
com.opencloud.rhino.facilities.profile.ProfileFacility interface, which adds additional functionality over what the JAIN SLEE
specification provides.
109
Rhino Extended APIs (V2.5.0)
6.12.1 ProfileFacility interface
The com.opencloud.rhino.facilities.profile.ProfileFacility interface is shown below:
package com.opencloud.rhino.facilities.profile;
import javax.slee.facilities.FacilityException;import javax.slee.profile.UnrecognizedProfileTableNameException;
public interface ProfileFacility extends javax.slee.profile.ProfileFacility { public boolean profileTableExists(String profileTableName) throws NullPointerException, FacilityException;
public ProfileTableDescriptor getProfileTableDescriptor(String profileTableName) throws NullPointerException, UnrecognizedProfileTableNameException, FacilityException;
public Class<?> getProfileLocalInterface(String profileTableName) throws NullPointerException, UnrecognizedProfileTableNameException, FacilityException;}
The extended interface is implemented by all ProfileFacility objects provided by Rhino to SBBs and resource adaptors.
The extended interface adds two new methods to the profile facility. Both methods are non-transactional; that is, they do not require an active
transaction to return a successful result. The methods throw the javax.slee.facilities.FacilityException if the requested operation
cannot be completed because of a system-level failure.
6.12.2 ProfileFacility interface profileTableExists method
The profileTableExists method returns a boolean value that reports whether or not a profile table with the name specified by the
profileTableName argument currently exists in the SLEE.
This method throws a NullPointerException if the profileTableName argument is null .
6.12.3 ProfileFacility interface getProfileTableDescriptor method
The getProfileTableDescriptor method returns a metadata object that provides information about the profile table with the name specified
by the profileTableName argument. The ProfileTableDescriptor interface is described below.
110
Rhino Extended APIs (V2.5.0)
This method throws a NullPointerException if the profileTableName argument is null . The method throws an
UnrecognizedProfileTableNameException if no profile table exists with the name specified by the profileTableName argument.
6.12.4 ProfileFacility interface ProfileTableDescriptor interface
The ProfileTableDescriptor interface provides metadata information about a profile table. This information might be useful, for example, to
determine if a profile table contains profiles of an expected type before querying the profile table or retrieving profiles from it.
The ProfileTableDescriptor interface is shown below:
package com.opencloud.rhino.facilities.profile;
import javax.slee.profile.ProfileSpecificationID;import javax.slee.profile.ProfileTable;
public interface ProfileTableDescriptor { public ProfileSpecificationID getProfileSpecification();
public Class<? extends ProfileTable> getProfileTableInterface();
public Class<?> getProfileLocalInterface();}
All methods in the ProfileTableDescriptor interface are non-transactional methods.
6.12.5 ProfileFacility interface getProfileSpecification method
The getProfileSpecification method returns the component identifier of the profile specification of the profile table the metadata object
describes.
6.12.6 ProfileFacility interface getProfileTableInterface method
The getProfileTableInterface method returns the Class object of the profile table interface declared by the profile specification of the
profile table the metadata object describes. If the profile specification does not declare a profile table interface, then this method returns the Class
object for the default SLEE-defined javax.slee.profile.ProfileTable interface instead.
111
Rhino Extended APIs (V2.5.0)
6.12.7 ProfileFacility interface getProfileLocalInterface method
The getProfileLocalInterface method returns the Class object of the profile local interface declared by the profile specification of the
profile table the metadata object describes. If the profile specification does not declare a profile local interface, then this method returns the Class
object of the profile CMP interface instead.
6.13 Tracer extensions
Rhino extends the standard javax.slee.Tracer interface with the com.opencloud.rhino.facilities.Tracer interface, which adds
additional functionality over what the JAIN SLEE specification provides.
6.13.1 Tracer interface
The com.opencloud.rhino.facilities.Tracer interface is shown below:
package com.opencloud.rhino.facilities;
import javax.slee.facilities.FacilityException;
public interface Tracer extends javax.slee.facilities.Tracer { public Tracer getParentTracer();
public Tracer getChildTracer(String name) throws NullPointerException, IllegalArgumentException, FacilityException;}
The extended interface is implemented by all Tracer objects provided by Rhino to SBBs, profiles, and resource adaptors.
The extended interface adds two new methods to the standard tracer. Like all methods defined by the standard interface, both new methods are
non-transactional; that is, they do not require an active transaction to return a successful result.
6.13.2 Tracer interface getParentTracer method
The getParentTracer method returns a Tracer object for the tracer’s parent tracer. The parent tracer is the tracer with the name returned by
the getParentTracerName method defined in the standard Tracer interface.
112
Rhino Extended APIs (V2.5.0)
If this method is invoked on a Tracer object for a root tracer, then null is returned.
6.13.3 Tracer interface getChildTracer method
The getChildTracer method returns a Tracer object for a tracer that is a descendant (in terms of a parent-child relationship) of the invoked
tracer. The name argument specifies the name of the child tracer.
Formally:
• if the invoked tracer is a root tracer, then this method returns a tracer with the name specified by the name argument
• otherwise, this method returns a tracer with the name: invokedTracer.getName() + . + name .
The name argument must be a valid tracer name. Since any valid name can be specified, this method can be used to create any descendant
tracer — child, grandchild, and so on.
This method throws a NullPointerException if the name argument is null . It throws an IllegalArgumentException if the name
argument would result in an invalid tracer name. It throws a javax.slee.facilities.FacilityException if the child tracer cannot be
returned because of a system-level failure.
6.14 Lock Facility
The lock facility allows resource adaptors to obtain transaction-based distributed locks.
In order to use the lock facility, one must obtain:
• a reference to the LockFacility itself; and
• a reference to the SLEE Transaction Manager, as all locks must be obtained from within a transaction.
The following code fragment illustrates how you can obtain these references in a resource adaptor:
package ...
import javax.slee.resource.ConfigProperties;import javax.slee.resource.ResourceAdaptor;import javax.slee.resource.ResourceAdaptorContext;
113
Rhino Extended APIs (V2.5.0)
import javax.slee.transaction.SleeTransactionManager;import com.opencloud.rhino.facilities.lock.LockFacility;
public class FooResourceAdaptor implements ResourceAdaptor { @Override public void setResourceAdaptorContext(ResourceAdaptorContext context) { // save context ref this.context = context;
// ... }
@Override public void raConfigure(ConfigProperties configProps) { // get refs to transaction manager and lock facility txManager = context.getSleeTransactionManager(); lockFacility = (LockFacility)configProps.getProperty(LockFacility.CONFIG_PROPERTY_NAME).getValue();
// ... }
// ...
private ResourceAdaptorContext context; private SleeTransactionManager txManager; private LockFacility lockFacility;}
With these references, one can then proceed to acquire locks as necessary. For example:
private void doSomeWorkThatRequiresALock() { // start a transaction SleeTransaction tx = txManager.beginSleeTransaction(); try { // acquire exclusive lock lockFacility.acquireExclusive("SomeLock");
// do the work
114
Rhino Extended APIs (V2.5.0)
// ...
// successfully completed work - commit transaction // automatically causes the lock to be released tx = null; txManager.commit(); } catch (Exception e) { if (tx != null) { // failed to complete work - rollback transaction // automatically causes the lock to be released tx.rollback(); } }}
6.15 JNDI environment metadata
The JAIN SLEE specification defines that an SBB component has access to a JNDI API namespace where it may obtain access to various SLEE
facilities and factories. Using the JNDI API for name lookups in SBB code generally works when you know exactly what you’re looking for, but
an SBB that uses SBB parts on page 68 may have entries in its JNDI namespace introduced by those SBB parts that may not be known at SBB
compile time but are still of interest to the SBB. The JNDI API does not differentiate one binding from another; so it’s not easy for an SBB, for
example, to find all resource adaptor entity bindings.
As an extension, Rhino provides all JNDI environment bindings to an SBB or SBB part in a separate map structure. The map is keyed on the fully
qualified binding name, with map values containing metadata about the type of binding as well as the bound object itself.
An SBB obtains access to the JNDI bindings map from its RhinoSbbContext object (a Rhino extension of SbbContext ):
package com.opencloud.rhino.slee;
import java.util.Map;import javax.slee.SLEEException;import javax.slee.SbbContext;import com.opencloud.rhino.slee.environment.JndiBinding;
115
Rhino Extended APIs (V2.5.0)
public interface RhinoSbbContext extends SbbContext { public Map<String,JndiBinding> getJndiBindings() throws SLEEException;
...}
An SBB part obtains access to the JNDI bindings map from its SbbPartContext object:
package com.opencloud.rhino.slee.sbbpart;
import java.util.Map;import javax.slee.SLEEException;import javax.slee.SbbContext;import com.opencloud.rhino.slee.environment.JndiBinding;
public interface SbbPartContext extends SbbContext { public Map<String,JndiBinding> getJndiBindings() throws SLEEException;
...}
6.15.1 JndiBinding class
The com.opencloud.rhino.slee.environment.JndiBinding class is shown below:
package com.opencloud.rhino.slee.environment;
public abstract class JndiBinding { public abstract BindingType getType(); public String getJndiName() { ... } public Object getValue() { ... }
public boolean equals(Object o) { ... } public int hashCode() { ... }}
116
Rhino Extended APIs (V2.5.0)
6.15.2 JndiBinding class getType method
The getType method returns the type of the JNDI binding. The BindingType enumeration is shown below:
package com.opencloud.rhino.slee.environment;
public enum BindingType { ENV_ENTRY, ACTIVITY_CONTEXT_INTERFACE_FACTORY, RESOURCE_ADAPTOR_ENTITY, FACILITY, LIMITER_ENDPOINT}
A JNDI binding may be one of:
• an environment entry
• an activity context interface factory, such as the null activity context interface factory
• a resource adaptor entity link binding
• a SLEE facility, such as the timer facility and alarm facility
Activity factories, such as the null activity factory and service activity factory are considered to be SLEEfacilities for this purpose.
• a configured Rhino limiter endpoint.
6.15.3 JndiBindingclass getJndiName method
The getJndiName method returns the fully qualified name of the JNDI binding. This value is equal to the key that the JndiBinding object is
stored with in the map of bindings.
6.15.4 JndiBindingclass getValue method
The getValue method returns the object bound to the JNDI name. For example, this could be an environment entry value, a SLEE facility, and so
on.
117
Rhino Extended APIs (V2.5.0)
6.15.5 Subclasses of JndiBinding
The JndiBinding class is an abstract class. A subclass of JndiBinding exists for each different type of binding. Each of these is described
below.
6.15.6 EnvEntry class
The EnvEntry class is used to describe a JNDI binding for an environment entry. The EnvEntry class is shown below:
package com.opencloud.rhino.slee.environment;
public final class EnvEntry extends JndiBinding { public EnvEntry(String jndiName, Object value) { ... } public BindingType getType() { return BindingType.ENV_ENTRY; } public String toString() { ... }}
6.15.7 Facility class
The Facility class is used to describe a JNDI binding for a SLEE facility such as the timer facility as well as activity factories such as the null
activity factory. The Facility class is shown below:
package com.opencloud.rhino.slee.environment;
public final class Facility extends JndiBinding { public Facility(String jndiName, Object value) { ... } public BindingType getType() { return BindingType.FACILITY; } public String toString() { ... }}
6.15.8 LimiterEndpoint class
The LimiterEndpoint class is used to describe a JNDI binding for a configured limiter endpoint . The LimiterEndpoint class is shown
below:
package com.opencloud.rhino.slee.environment;
118
Rhino Extended APIs (V2.5.0)
public final class LimiterEndpoint extends JndiBinding { public LimiterEndpoint(String jndiName, Object value) { ... } public BindingType getType() { return BindingType.LIMITER_ENDPOINT; } public String toString() { ... }}
6.15.9 ResourceAdaptorTypeBinding class
The ResourceAdaptorTypeBinding class is the superclass for JNDI binding metadata classes related to resource adaptor types. The
ResourceAdaptorTypeBinding class is shown below:
package com.opencloud.rhino.slee.environment;
import javax.slee.resource.ResourceAdaptorTypeID;
public abstract class ResourceAdaptorTypeBinding extends JndiBinding { public ResourceAdaptorTypeID getResourceAdaptorType() { ... } public int hashCode() { ... }}
The getResourceAdaptorType method returns the component identifier of the resource adaptor type that the binding is associated with.
6.15.10 ActivityContextInterfaceFactoryBinding class
The ActivityContextInterfaceFactoryBinding class is used to describe a JNDI binding for an activity context interface factory. The
ActivityContextInterfaceFactoryBinding class is shown below:
package com.opencloud.rhino.slee.environment;
import javax.slee.resource.ResourceAdaptorTypeID;
public final class ActivityContextInterfaceFactoryBinding extends ResourceAdaptorTypeBinding { public ActivityContextInterfaceFactoryBinding(String jndiName, ResourceAdaptorTypeID raType, Object value) { ... } public BindingType getType() { return BindingType.ACTIVITY_CONTEXT_INTERFACE_FACTORY; } public String toString() { ... }}
119
Rhino Extended APIs (V2.5.0)
6.15.11 ResourceAdaptorEntityBinding class
The ResourceAdaptorEntityBinding class is used to describe a JNDI binding for a resource adaptor entity. The
ResourceAdaptorEntityBinding class is shown below:
package com.opencloud.rhino.slee.environment;
import javax.slee.resource.ResourceAdaptorTypeID;
public final class ResourceAdaptorEntityBinding extends ResourceAdaptorTypeBinding { public ResourceAdaptorEntityBinding(String jndiName, ResourceAdaptorTypeID raType, Object value) { ... } public BindingType getType() { return BindingType.RESOURCE_ADAPTOR_ENTITY; } public String toString() { ... }}
120