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

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)

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

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

SBB part objects

An SBB part may optionally declare an SBB part class. 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.

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.

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

Warning
  • 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.

  • 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 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 section.

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 for various types of fields.

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.

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

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.

Warning
  • 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.

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.

Warning
  • 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.

Warning
  • 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 @InitialValueFields, 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.

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

Warning
  • 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.

Warning
  • 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.

Warning
  • 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.

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

Warning
  • 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.

Warning
  • 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.

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);
Warning
  • 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.

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

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);
Warning
  • 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.

  • It is only invoked on SBB part objects in the Pooled state.

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.

Warning
  • 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 RuntimeException.

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

Tip A well-written SBB part should not throw any RuntimeExceptions from any of its SLEE invoked methods. Instead, the SBB part should place the exception handling logic inside a try { } catch (Throwable) clause and handle RuntimeExceptions within each 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.

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.

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.

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

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

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. An SBB part can also define its per-instance state using CMP extension interfaces. The SBB part obtains 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 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 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.

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.

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.

SbbPartContext interface getSbbPart method

The getSbbPart method returns an SbbPartID object that encapsulates the component identity of the SBB part.

SbbPartContext interface getTracer method

The getTracer method overrides the same method from SbbContext to return a Rhino-specific extension of the Tracer interface.

Tip For more about this Tracer extension, please see SLEE Facilities.

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.

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.

Tip For more about this ActivityContextInterface extension, please see Miscellaneous SLEE API Enhancements.
  • 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.

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.

SbbPartContext interface getCMPFields method

The getCMPFields method provides the SBB part with access to its per-instance state.

SbbPartContext interface getJndiBindings method

The getJndiBindings method returns a map describing the JNDI bindings available to the SBB part.

Tip For more about this method, please see SLEE Facilities.

SbbPartContext interface enableEntityTreePersistence method

The enableEntityTreePersistence method enables persistence of application state to external replicated storage resources such as a key/value store. Initial replicated persistence of application state can be disabled using the service-properties element in the extension service deployment descriptor, then enabled using this method when the SBB entity has reached a stable state.

Tip For more about application initiated persistence, please see Application initiated persistence.

SbbPartContext interface getConvergenceNameSessionOwnershipRecord methods

These methods obtain a reference to the convergence name session ownership record for the SBB entity tree.

Tip For more about convergence name session ownership records, please see Convergence name session ownership record.

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.

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;
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 {
    @PostCreate
    public void onCreate() throws CreateException {
        rootTracer.info("SBB part created");
    }

    public void onTimerEvent(TimerEvent event, ExampleSbbPartActivityContextInterface aci) {
        // get CMP counter
        int count = cmpFields.getCounter() + 1;

        // log event
        timerTracer.info("received timer event: " + count);

        // increment CMP counter
        cmpFields.setCounter(count);

        // record usage stats
        rootUsage.incrementTimerEvents(1);

        ...
    }


    @Inject
    private Tracer rootTracer;

    @Inject @Named("timer")
    private Tracer timerTracer;

    @Inject
    private ExampleSbbPartCMPInterface cmpFields;

    @Inject
    private ExampleSbbPartUsageInterface rootUsage;
}
Previous page Next page