This page details the following enhancements to SLEE APIs, which Rhino provides for SLEE applications:
- SbbContext interface extensions
- RhinoSbbContext interface getConvergenceName method
- RhinoSbbContext interface getTracer method
- RhinoSbbContext interface getActivities methods
- RhinoSbbContext interface getChildRelationFacility method
- RhinoSbbContext interface getCMPFields method
- RhinoSbbContext interface getJndiBindings method
- RhinoSbbContext interface setServiceContext and getServiceContext methods
- RhinoSbbContext interface setEncodableContext method
- Activity context Suspend/Resume Delivery extensions
- SBB local home interface
- How to get an SBB local home object
- The RhinoSbbLocalHome interface
- SBB service lifecycle callbacks
- RhinoSbbLocalHome interface verifyConfiguration method
- RhinoSbbLocalHome interface serviceActivating method
- RhinoSbbLocalHome interface serviceDeactivating method
- Lifecycle callback method invocation cascade
- Per-Node Service Activity and Lifecycle Events
- Unchecked throwable propagation
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;
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;
}
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.
RhinoSbbContext interface getTracer method
The getTracer
method overrides the same method from SbbContext
to return a Rhino-specific extension of the Tracer
interface.
For more about this Tracer extension, please see Tracer extensions.
|
RhinoSbbContext interface getActivities methods
The RhinoSbbContext
interface defines two getActivities
methods:
-
getActivities()
— This method overrides the same method fromSbbContext
to return a Rhino-specific extension of theActivityContextInterface
interface. ThisActivityContextInterface
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 withNullActivity.class
as an argument, then only activity context objects for the null activities the SBB entity is attached to would be returned.
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 |
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.
|
RhinoSbbContext interface getJndiBindings method
The getJndiBindings
method returns a map describing the JNDI bindings available to the SBB.
For more about this method, please see JNDI environment |
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 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.
RhinoSbbContext interface setEncodableContext method
The setEncodableContext
method sets the encodable context for the SBB.
For more about encodable contexts, please see Encodable context. |
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;
}
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 may be declared as extending RhinoActivityContextInterface
rather than ActivityContextInterface
if desired.
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 |
---|---|
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 |
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. |
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. |
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. |
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.
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.
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.
The getChildSbbLocalHome
method defined by the ChildRelationFacility
interface returns an SBB local home object for the specified child SBB relation.
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;
}
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.
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.
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 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. -
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.
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 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.
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 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.
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.
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.
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.
Per-Node Service Activity and Lifecycle Events
This feature is available in Rhino 2.6.0 from version 2.6.0.2 |
Service Node Activities can be used by SBBs to monitor the managed lifecycle of the service they are a part of on their individual cluster node. Service Node Activities perform the same function as SLEE 1.1 Service Activities, but for each node in a Rhino cluster instead of only once for the whole cluster. This is useful when a service needs to initialise local state on each node in a cluster or perform shutdown tasks without storing replicated SBB state.
When a service is started on a node, a Service Node Activity
is created on that node and a com.opencloud.rhino.slee.servicenodeactivity.ServiceNodeStartedEvent
is fired on the activity to the service.
When the service is stopped on a node, the service node activity on that node is ended and a javax.slee.ActivityEndEvent
is fired on the activity.
A service starts on a node when either of the following occurs on that node:
-
the SLEE is in the Running state and the service is activated via the
ServiceManagementMBean
; or -
the persistent state of the service says that the service should be active, and a previously stopped SLEE transitions to the Running state.
The event type name of Service Node Started events is com.opencloud.rhino.slee.servicenodeactivity.ServiceNodeStartedEvent
, the vendor is com.opencloud
, and the version is 1.0
.
The event, when fired by the SLEE, will only be delivered to SBBs in the service that is starting, and not any other service.
Service Node Activities are never replicated. Each node has their own Service Node Activity that does not share state with any other node.
The Service Node Activity allows the SBBs making up the service to identify the service.
The Service Node Activity for an SBB entity can be obtained by looking it up using the ServiceNodeActivityFactory
class, an instance of which can be obtained by JNDI lookup using the name java:comp/env/rhino/servicenodeactivity/factory
.
An SBB can create an Activity Context Interface for the Service Node Activity using the ServiceNodeActivityContextInterfaceFactory
class.
An instance of this can be looked up using the JNDI name java:comp/env/rhino/servicenodeactivity/activitycontextinterfacefactory
.
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
.