Skip navigation.

Extension SDK for BEA WebLogic Network Gatekeeper

  Previous Next vertical dots separating previous/next from contents/index/pdf Contents View as PDF   Get Adobe Reader

Interacting with the SLEE and the SLEE Utility Services

This chapter describes how to interact with the SLEE and the utilities that the SLEE offers when creating applications.

These utilities can only be used when the applications are executing internally in the SLEE.

For a detailed description of all SLEE utility classes and methods, see the JavaDoc for the SLEE.

The following sections describe the SLEE and SLEE utility services:

 


Basic SLEE interfaces

All services must implement the basic SLEE interfaces in order for them to executed in the SLEE, and being SLEE services.

ServiceAccessible

All accessible services running within the SLEE must have a class that implements this interface. The ServiceAccessible interface represents the object that will be installed in the SLEE service ORB as a service that can be accessed by other services. The class implementing this interface MUST also have an empty public constructor.

The ServiceContext object is provided by the SLEE using the ServiceAccessible interface.

The CORBA POA is supplied by the SLEE in setPOA(...), and the SLEE service must implement and return the same POA using the method public org.omg.PortableServer.POA _default_POA().

The SLEE service shall use this POA, or a child POA, when creating new CORBA objects.

The SLEE will call the following method on the object implementing this interface:

ServiceDeployable

All services running within the SLEE must implement this interface, otherwise they can not be deployed. The SLEE will use the ServiceDeployable interface to notify the service of the current service deployment status.

The SLEE will call the following methods on the object implementing this interface:

ServiceDeployableExt

Extension of ServiceDeployable interface that a service can implement if supporting suspend/resume for a service.

Extends the ServiceDeployable interface with the following operations:

ServiceManageable

All services running within the SLEE may have a class that implements this interface. The interface is used for providing extra management capabilities for a service. The ServiceManageable interface represents the object that will be installed in the name service as the OAM (Operation Administration and Management) object for a service. Note that the ServiceManageable interface extends ServiceCORBAServant. See OAM.

The SLEE will call the following method on the object implementing this interface:

ServiceContext

The ServiceContext represents the context of a service. All service interfaces have a setServiceContext method that will be called from the SLEE before calling the method started() on the object implementing ServiceDeployable interface.

It is possible to get a handle to the following services through this interface:

It is also possible to get references to the objects in the SLEE service implementing the following interfaces:

It is also possible to get a handle to the SLEE Context service, which is used to get other utility services. See Services fetched from the SLEEContext.

Via the ServiceContext it is also possible to:

SLEEContext

SLEEContext represents the SLEE context for a service. It provides an initial object for retrieving other services. A SLEE Context object is provided by the SLEE via the Service Context object. A service can use the SLEE Context to retrieve handles to utility services provided by the SLEE.

It is possible to get a handle to the following classes through this interface:

 


SLEE utility interfaces

A software module that executes in the SLEE utilizes a set of operations offered by the SLEE and the SLEE Utility services. Which SLEE utility interfaces to use depends on which SLEE utility services the software module needs.

Some services are available using the SLEE Context interface, see Services fetched from the SLEEContext, others via the Services fetched from the SLEEContext interface. There are also a set of classes that can be used directly, see SLEE utility classes.

Services fetched from the ServiceContext

ChargingService

The charging service provides methods for creating CDRs in the Network Gatekeeper database.

See Using the charging service.

PolicyManager

The Policy Manager service provides methods for implementing a policy enforcement point.

See Implement the Policy Enforcement Point.

SLEEEventChannel

Interface for broadcasting events and for register listeners of events originating from other SLEE services. Used for sending events (data) from a SLEE service to another, convenient when for example propagating changes of cached data to other instances of a service.

Below is pseudo code for broadcasting an event via the SLEEEventChannel.

Listing 3-1 Broadcasting an event

//m_sc holds the ServiceContext
String eventId = "eventID";
EventData eventData = new EventData();
org.omg.CORBA.Any event;
event = eventData;
m_sc.getSleeEventChannel().generateEvent(eventId, event);

Below is pseudo code for receiving the event.

Listing 3-2 Receiving an event -class that implements SLEEEventChannelListener

public void processEvent(String eventId,
                         org.omg.CORBA.Any event,
                         String source) {
   if (eventId == "eventID") { // Check the event ID
      EventData eventData = (EventData)event; //Cast to proper class
   }
   // source contains the instance ID of the SLEE service. 
   // m_sc holds holds the ServiceContext
   if (source.equals(m_sc.getInstanceName()) {
      // The event originated from this instance.
   }
}

TraceLogService

Interface for the trace log service. A service can use the trace service to write service tracing information to a service specific trace file. Although the trace service can be disabled and enabled it is recommended that each service performs a check on the trace active flag before calling the logTrace method for performance reasons (reduces the number of allocated String objects at runtime). See Using the trace service.

ServiceInstanceHandler

The Service instance handler can be used to locate multiple instances of a service. It provides IORs to other SLEE Services ServiceAccessible interface.

PolicyManager

The Policy Manager is used for retrieving the Policy service in order to create a Policy Enforcement Point. The policy manager is normally used in the ESPA SC Layer.

Below is an outline of how a Policy Enforcement Point is implemented. See MyServiceCapabilityManager_impl.java in module_templates\espa_sc_impl\src\com\acompany\espa\mysctype\ for details on how it is implemented.

The PolicyManager is fetched from the ServiceContext.

Listing 3-3 Fetching the PolicyManager

policyManager = MyServiceCapabilityContext.getServiceContext().getPolicyManager();

Then a PolicyRequest object, that holds the data to be forwarded to the Policy Decision Point, is created. Among the data is application and service provider IDs for the application that the requests originates from.

Listing 3-4 Creating a PolicyRequest object

MyServiceCapabilityContext.getServiceContext().getSLEEContext().getTimeManager().getTime();
     PolicyRequest policyRequest = new PolicyRequest_impl(
     MyServiceCapabilityContext.getServiceContext().getSLEEContext().getORB(),
     timeStamp); 
            try {
                policyRequest.applicationID = m_ApplicationID;
                policyRequest.serviceProviderID = m_ServiceProviderID;
            } catch (com.incomit.espa.access.AccessException e) {
                ...
           }
            policyRequest.serviceName =
            MyServiceCapabilityContext.POLICY_SERVICE_NAME;
            policyRequest.serviceGroup =
            MyServiceCapabilityContext.POLICY_SERVICE_GROUP;
            policyRequest.methodName = "myMethod";
            policyRequest.serviceCode = serviceCode;
            policyRequest.requesterID = requesterID;
            policyRequest.transactionID = -1;
            policyRequest.noOfActiveSessions = -1; 
            policyRequest.reqCounter = 0;
            AdditionalData adArray[] = new AdditionalData[2];
            AdditionalDataValue targetAddressValue = new AdditionalDataValue();
            AdditionalData adTargetAddressString = new AdditionalData();
            targetAddressValue.stringValue(address);
            adTargetAddressString.dataName = "targetAddress";
            adTargetAddressString.dataValue = targetAddressValue;
            adArray[0] = adTargetAddressString;
            AdditionalDataValue dataValue = new AdditionalDataValue();
            AdditionalData adDataString = new AdditionalData();
            dataValue.stringValue(data);
            adDataString.dataName = "data";
            adDataString.dataValue = dataValue;
            adArray[1] = adDataString;
            policyRequest.additionalParameters = adArray;

Then the PolicyRequest data is evaluated by the Policy decision Point.

Listing 3-5 Evaluate the Policy data

PolicyRequest modifiedRequest = (PolicyRequest)policyManager.evaluate((PolicyRequest) policyRequest);

If the request is denied, a DenyException is thrown. If the request was accepted, the request data may have been modified, so the modified data is used when propagating the request instead of the original data.

Listing 3-6 Use the request data returned from the PolicyRequest

requestContext = new RequestContext(modifiedRequest.requesterID, 
                                    modifiedRequest.serviceCode);
address = modifiedRequest.getAdditionalDataStringValue("targetAddress");
data = modifiedRequest.getAdditionalDataStringValue("data");

If the request was denied, a CDR shall be created with completion status Policy Rejected.

Services fetched from the SLEEContext

SLEEDBManager

Database manager for SLEE. The DB manager controls connections to the database. A SLEE service can use the DB manager to retrieve a DB connection. By default all users/slee services share the same database and database user identity. See Using the database.

All SLEE services that use JDBC shall retrieve connections using the SLEEDBManager instead of using the driver directly

SLEELoadManager

Used to query the load of a SLEE. It reports the load as a number between 0 and 100. It is also possible to register listeners that report when the load has reach a certain level. Note that the load is reported to listener only every 5th second. It is recommended to use the synchronous method instead of registering listeners.

Listing 3-7 Getting the load on a SLEE Service

//m_sc holds the ServiceContext
int loadValue _= m_sc.getSLEEContext().getLoadManager().getLoadValue();

SLEELoadManagerListener

Load events are reported using this interface, when subscribed to using the SLEE LoadManager.

Events related to the load has reached a load level are reported via the SLEELoadManagerListener interface via the method processLoadEvent(LoadEvent loadEvent). The LoadEvent class holds information on which load level that was reached:

The registration of the SLEELoadManagerListener interface is performed via the method addListener(...) in the SLEELoadManager interface.

SLEEResourceListener

When plug-ins are added, it is reported on this interface.

SLEEResourceManager

The Plug-in manager interface. See Plug-in manager interfaces.

SLEEResourceTask

This interface must be implemented by users of the SLEEResourceManager.scheduleResourceTask method. A resource task is scheduled by calling scheduleResourceTask with an instance to the class implementing SLEEResourceTask as an argument to the SLEEResourceManager.

This SLEEResourceTask interface is implemented by ESPA SCs, and the SLEE calls the method doTask(...) on the implementation of the interface. A reference to the allocated plug-in is provided as an argument to doTask(...).

SLEEStatisticsManager

This interface is used to add transaction statistics to the Statistics SLEE service. There are a set of pre-defined statistic types, and new ones can be added using this interface or by using OAM in the SLEE Statistics Service. All new Service Capabilities shall generate transaction statistics to allow for a transaction based price model. Examples on how to generate transactions statistics are provided in the template source code.

For extensions the statistics transaction type range must be: 1000 to 10 000.

Transaction statistics can be added for all traffic generated by all applications, or per service provider or per service provider and application.

serviceProviderID is put in the sourceEntity parameter and applicationID is put in the sourceApplication parameter.

Below is an example on how to generate statistics.

Listing 3-8 Update statistics counter

// m_sc holds the SLEEContext
// serviceProviderID contains the service provider ID that performed the request
// applicationID contains the application ID that performed the request
int transactionType = TRANSACTION_TYPE_NETWORK_TRIGGERED_EVENT_SUCCESS;
int transactions = 1; //number of transactions to add to the statistics counter
m_sc.getStatisticsManager().addTransactionStatistics(transactionType,
                                                     transactions,
                                                     serviceProviderID,
                                                     applicationID);

The transactionType must be added to the SLEE Statistics service using the Management Tool. That is, the value representing transactionType must be added using the Management method addStatisticType in the SLEE_statistics service.

SLEETask

SLEETasks shall be used instead of using Java threads directly. Java threads must never be created directly, they should always be created via SLEETasks. Since asynchronous communication between the software modules always is preferred, SLEETasks shall be used for remote procedure calls via CORBA.

The SLEETask interface should be implemented by users of the SLEETaskManager. A task is scheduled by calling scheduleSLEETask in the SLEETaskManager. As soon as one of the threads managed by SLEETaskManager becomes available doTask in SLEETask will be called.

SLEETasks shall be used instead of pure Java tasks. The SLEETaskManager provides mechanisms for pooling of threads. Use SLEETasks for processing of tasks that risks blocking of resources.

Listing 3-9 Pseudo code for a SLEETask

public class MyTask implements SLEETask {
   public MyTask() {
   }
   // Will be called by the SLEETaskManager
   public void doTask() {
            // Perform the task.
   }
}

SLEETaskManager

SLEE task manager should be used for scheduling a task by using a thread from the thread pool managed by the SLEETaskManager.

Listing 3-10 Pseudo code for scheduling a SLEETask

// m_sc holds the ServiceContext
m_taskMgr = m_sc.getSLEEContext().getTaskManager();
m_taskMgr.scheduleSLEETask(new MyTask)

SLEETimeManager

SLEE Time manager is responsible for managing system time and timer handling. Its possible to schedule timers and get system time.

SLEEZombieObjectListener

Listener interface for handling state changes of zombie objects. When the zombie object is reachable again the client listener will be notified. If the supervised object is not alive within AssumedDeadTimeout the listener will also be notified.

Instead of using this interface, use the SuperVisedListListener interface, see SupervisedListListener.

SLEEZombieObjectSupervisor

Class for supervising CORBA objects that are currently not reachable but may become available in the future. Clients can use this utility class to handle the checking of when such an object becomes active/reachable again. When the object is reachable the client listener will be notified. If the supervised object is not alive within the specified time-out (or getAssumeDeadTimeout() if time-out is not specified) the listener will also be notified.

Instead of using this class, use the SupervisedList class, see SupervisedList.

TaskChain

Used when tasks need to be executed in a given order.

This interface is returned when scheduling the first task in a task chain using SLEETaskManager.scheduleTaskChain. It can be used to add new tasks to the end of the chain.

 


SLEE utility classes

In com.incomit.slee there is a set of classes available. Below is a summary of the available classes. Refer to the Javadoc for the SLEE for detailed information.

Alarm

See Using the alarm service.

LoadEvent

Definition of a load level event.

SLEECyclicIDManager

ID manager for retrieving a unique ID. The IDs will be unique for all SLEE instances using the same database.

IDs will be reused when IDs of an int minus the most significant byte has been exceeded.

Listing 3-11 Below is pseudo code for how to get a unique ID

//m_sc holds the ServiceContext
int ID = m_sc.getSLEEContext().getCyclicIDManager().getID()

SLEEDBTable

Database table class. Can be used to check if table exists and that it has the desired format and to create or replace the table. Used also for creating temporary tables.

SLEE services using the SLEE DB Manager to retrieve JDBC connections must use this class to create its tables, to get privileges to use the table. See Using the database.

SLEECyclicIDManager

ID manager for retrieving a unique ID. The IDs will be unique for all SLEE instances using the same database. The IDs are of type int.

IDs will be reused when IDs of a int minus the most significant byte has been exceeded.

SLEEIDManager

ID manager for retrieving a unique ID. The IDs will be unique for all SLEE instances using the same database. The IDs are of type long.

IDs will be reused when IDs of a long minus the most significant byte has been exceeded.

SLEEGlobalCounterManager

The SLEE global counter manager provides an interface for maintaining global counters. A global counter will be automatically updated across all SLEE instances in a system.

SLEEGlobalCounter

The SLEE global counter interface provides methods for incrementing and managing a global counter. Note that increments of a counter may not be distributed to all instances immediately. Updates will be performed globally every 10th increment of a specific counter or every 5th second for all counters that have been updated less than 10 times during the last 5 second period.

SupervisedList

List holding supervised CORBA objects, that if they are unreachable is moved to a zombie object supervisor list where they are "pinged" for a certain time before they are considered dead and entirely removed from the list.

Listing 3-12 Pseudo code for creating a supervised list.

// m_sc holds the ServiceContext.
//listener implements the SupervisedListListener interface
SupervisedList m_supervisedList;
long timeBeforeDead = 10000; // Time given in millseconds
m_supervisedList = new SupervisedList(m_sc.getSLEEContext(), timeBeforeDead);
m_supervisedList.addListener(listener); 

SupervisedListListener

Interface for receiving events about objects removed from a SupervisedList.

Listing 3-13 Pseudo code for listening to events from object s in a supervised list.

public class MyClass implements SupervisedListListener {
   MyClass() {
   }
   public void objectDead(SupervisedCorbaObject o) {
      // Object was removed due to zombie timeout.
      // Remove any references to the object.
   }
   public void objectZombie(SupervisedCorbaObject o) {
      // Object was declared a zombie and moved to zombie list.
   }
   public void objectLive(SupervisedCorbaObject o) {
      // Object was declared alive and put back into the list again
   }
}

 


OAM

All SLEE services that has parameters that needs to be configured in runtime must implement the ServiceManageable interface.

The OAM operations are defined in IDL, and Java stubs are generated from this interface. This means that the class that implements the OAM operations must extend the abstract class generated from the IDL definition. This class is named <name of interface in IDL>POA.

For example if the interface is named AServiceOAM, the implementation must extend AServiceOAMPOA. In the example below the implementation of the interface is in the class AServiceOAM_impl.

Listing 3-14 Example of declaration of the OAM class

public class AServiceOAM_impl extends AServiceOAMPOA implements ServiceManageable 

Also, the IDL file defining the OAM interface must be packaged into the jar file for the software module, in the root. There is a deployment descriptor in JAR file, which states the name of the IDL file for the OAM interface and the class that implements the interface.

Listing 3-15 Part of the Example of deployment descriptor

...
<SERVICE_MANAGEABLE>
        com.my_company.my_plugin.AServiceOAM_impl
        <SERVICE_MANAGEABLE_IDL>
            AServiceOAM.idl
        </SERVICE_MANAGEABLE_IDL>
</SERVICE_MANAGEABLE>
...

Additional information is also defined in the deployment descriptor. The build files in the templates are used for creating the deployment descriptors and to package them into the deployable Jar file.

Implementing OAM access control

To implement access control for OAM, there must be two methods for each OAM method. One that is exposed in the OAM interface, and another one that checks if the OAM user has appropriate privileges. The two methods are correlated by their name. So an OAM method with the signature <method name>, must have a corresponding method with the signature <method name>Allowed(...). In the latter method the privilege is checked. See example below.

Listing 3-16 Checking of an OAM method is permitted

public void setOverloadPercentage(int percentage) 
....
public boolean setOverloadPercentageAllowed(int userLevel) {
        return(userLevel >= SLEEOAM.SEC_LEVEL_READ_WRITE);
    }

 


Using the database

The SLEE uses a DBMS that can be used by the application programmer. Support is built into the framework for accessing the database using JDBC.

The SLEE allocates database connections that can be accessed from the SLEE Context. From the SLEE Context you can retrieve a handle to the Database Manager, which is a singleton class that controls access to the database. By default all users and SLEE services share the same database. To get access to own tables, the tables must be created using the createSLEEDBTable() method. That is, the tables cannot be created using SQL syntax.

This example shows how to create a temporary table, called mobile_users, with two columns containing a user identity and its corresponding mobile subscription number. The table can be used to, for example, sending SMS messages to a group of registered users. The createTemporaryTable() method is called on service activation. The insertion of data through the register() method can be done from a class implementing the ServiceAccessible interface. To retrieve a list of all users that are currently registered, a convenience method called getSubscribers() is used. Finally, when the service is deactivated, the table is removed from the database by calling the removeTemporaryTable() method.

For the purpose of the example, we will create a class called DbRegister.java, that takes one argument in its constructor, a reference to the SLEE Service Context. The database manipulation is done through the database manager, SLEEDBManager.

Listing 3-17 DbRegister.java -initiation and constructor

package example.helloslee;
import com.incomit.slee.*;
import java.sql.*;
import java.sql.*;
public class DbRegister {
private ServiceContext itsServiceContext = null;
  private SLEEDBManager itsDbManager = null;
// Constructor
  public DbRegister (ServiceContext aServiceContext) {
    itsServiceContext = aServiceContext;
    SLEEContext sc = itsServiceContext.getSLEEContext();
    itsDbManager = sc.getDBManager();
}

To create the temporary table, we will use the method createTemporaryTable(), that takes no arguments. It uses the utility method createSLEEDBTable() that returns a SLEEDBTable, which then is used to add the necessary columns, before physically creating the table in the database. The arguments to addColumn specifies the column name, the data type, if the column is used in the primary key, and if null values are allowed.

Listing 3-18 DbRegister.java -method: createTemporaryTable

  public void createTemporaryTable () {
    try {
	Connection conn =
		itsDbManager.getConnection();
	try {
		SLEEDBTable table = 
		itsDbManager.createSLEEDBTable("mobile_users");
		table.addColumn("userName", "VARCHAR(20)", true, false);
		table.addColumn("msisdn", "VARCHAR(28)", false, true);
		if (!table.exists(conn)) {
			table.create(conn);
		}
	}
	catch(Exception e){
		// Handle exception
	}
	finally {
		if (conn!=null) {
			conn.close();
		}
	}
    } catch (SQLException e) {
      // Handle exception
    }
  }

To insert a new row in the table, we use the method register(), that takes a user name and a mobile subscription number as arguments. It uses JDBC methods to create a statement and execute the update towards the database. It is working towards a pre-allocated connection resource that is served by the SLEE Database Manager.

Listing 3-19 DbRegister.java -method: register

  public void register(String user, String msisdn) {
   try {
	Connection conn =
	itsDbManager.getConnection();
	try {
		Statement stmt = conn.createStatement();
		try {
			stmt.executeUpdate("INSERT INTO " + 
					     "mobile_users VALUES ('" + 
					      user + "', '" + msisdn + "')");
		catch (Exception e) {
			//Handle exception
		}
		finally {
			stmt.close();
		}
	catch (Exception e) {
			//Handle exception
	}
	finally {
		if (conn!=null) {
			conn.close();
		}
	}
   } catch (SQLException ex) {
      // Handle exception 
    }
 }

As a convenience service, we provide a method that return all registered subscribers. The getSubscribers() methods takes no arguments, and executes a SQL SELECT query towards the database. The Result Set is converted to a Hashtable and returned to the calling method.

Listing 3-20 DbRegister.java -method: getSubscribers

  public Hashtable getSubscribers () {
      Connection conn = itsDbManager.getConnection();
      Statement stmt;
      ResultSet rs;
	try {
		stmt = conn.createStatement();
		Hashtable table = new Hashtable();
		String query = "SELECT userName, msisdn " + 
				"FROM mobile_users";
		rs = stmt.executeQuery(query);
		while (rs.next()) {
			table.put(rs.getString(1), rs.getString(2));
		}
		return table;
	}
	catch (SQLException e) {
	// Handle exception
	}
	finally {
	if (rs!=null) {
		rs.close();
	}
	if (stmt!=null){
		stmt.close();
	}
	if (conn!=null) {
		conn.close();
	}
   }
  }

Finally, when the table is no longer needed, it is removed from the database. For this the method removeTemporaryTable() is used. It also uses a connection resource from the SLEE Database Manager, and a SQL DROP TABLE command in its JDBC execute update statement.

Listing 3-21 DbRegister.java -method: removeTemporaryTable

  public void removeTemporaryTable () {
    try {
	Connection conn =
	itsDbManager.getConnection();
	Statement stmt;
	try {
		stmt = conn.createStatement();
		stmt.executeUpdate("DROP TABLE mobile_users");
	}
	catch (Exeption e) {
		// Handle exception
	}
	finally {
		if (stmt!=null) {
			stmt.close();
		}
		if (conn!=null) {
			conn.close();
		}
	}
    } catch (SQLException e) {
      // Handle exception
    }
  }
}

 


Using the alarm service

Alarms in the SLEE are handled by a dedicated alarm service. All alarms reported from an application will be reported to an alarm log in the database. There is only one table in the database for logging alarms, which means that all applications using the alarm service share the same table in the database.

Alarms are critical events that need corrective action. If an application raises too many alarms, it is taken out of service. The maximum number of allowed critical alarms for an application can be configured in the deployment descriptor.

In this example we will explore how to set up a reference to the alarm service, and how to generate alarms that will be stored in the alarm log.

An alarm record contains the following information:

Field

Description

Alarm Number

An alarm identifier, for example the type of the alarm.

For extensions, the alarm number range must be:

500 000 to 999 999.

Severity

The severity of the alarm. Pre-defined constants are defined in the AlarmService interface, and should be used:

AlarmService.MINOR

AlarmService.WARNING

AlarmService.MAJOR

AlarmService.CRITICAL

Service Instance Name

The source of the alarm, that is, the unique name for this service. Retrieved by using getInstanceName() on the ServiceContext object.

Time and Date

The time-stamp will be generated by the system when receiving an alarm

Additional Information

Any other information that can be used to inform about the alarm. For example the stack trace can be included, if available.

The method fireAlarm() is used to report an alarm, and has the following signature:

public void fireAlarm(byte[] source, int severity, int identifier, byte[] info)

The following code shows an example how to set up and use the alarm service. It is in the form of an utility class that uses the Service Context to retrieve a handle to the alarm service. The method raiseAlarm() fires a simple alarm that will be written to the system alarm table in the database. The method takes one argument of the type Throwable, and will include the stringified error message in the alarm log.

Listing 3-22 Alarm.java

package example.helloslee;
import com.incomit.slee.*;
import com.incomit.slee.alarm.*;
public class Alarm {
  private ServiceContext itsServiceContext;
  private AlarmService itsAlarmService;
  private int alarmNumber = 4711;
  public Alarm (ServiceContext aServiceContext) {
    itsServiceContext = aServiceContext;
    SLEEContext sc = itsServiceContext.getSLEEContext();
    itsAlarmService =  sc.getAlarmService();     
  }
  public void raiseAlarm (Throwable e) {
    itsAlarmService.fireAlarm(itsServiceContext
                               .getInstanceName().getBytes(),
                              AlarmService.MAJOR,
                              alarmNumber,
                              e.toString().getBytes());
  }
}

 


Using the event service

Events in the SLEE are handled by a dedicated Event Log service. All events generated by an application will be logged to an event log in the database. There is only one table in the database for logging events, which means that all applications using the Event Log Service share the same table in the database.

Events are expected events of importance to the operator.

In this example we will explore how to set up a reference to the Event Log Service, and how to generate events that will be stored in the event log.

An event record contains the following information:

Field

Description

Event Number

An event identifier, for example the type of the event

For extensions, the event number range must be:

500 000 to 999 999.

Level

The level of the event. Pre-defined constants are defined in the EventLogService interface, and should be used:

EventLogService.LOW

EventLogService.MEDIUM

EventLogService.HIGH

Service Instance Name

The source of the event, that is, the unique name for this service. Retrieved by using getInstanceName() on the ServiceContext object.

Time and Date

The time-stamp will be generated by the system when receiving an event

Additional Information

Any other information that can be used to inform about the event.

The method logEvent() is used to report an event, and has the following signature:

public void logEvent(byte[] source,int identifier,int level,byte[] info)

The following code shows an example how to set up and use the Event Log Service. It is in the form of an utility class that uses the Service Context to retrieve a handle to the Event Log Service. The method storeEvent() logs a simple event that will be written to the system event log table in the database.

Listing 3-23 Event.java

package example.helloslee;
import com.incomit.slee.*;
import com.incomit.slee.event.*;
public class Event {
  private ServiceContext itsServiceContext;
  private EventLogService itsEventService;
  private int eventNumber = 42;
  private String message = "Logged message";
  public Event (ServiceContext aServiceContext) {
    itsServiceContext = aServiceContext;
    SLEEContext sc = itsServiceContext.getSLEEContext();
    itsEventService =  sc.getEventLogService();     
  }
  public void storeEvent () {
    itsEventService.logEvent(itsServiceContext
                              .getInstanceName().getBytes(),
                             EventLogService.MEDIUM,
                             eventNumber,
                             message.getBytes());
  }
}

 


Using the charging service

The charging service works in a similar way as the event service, the difference is the information that will be stored in the database. Each SLEE service will have a dedicated instance of the charging service. The charging service is retrieved via the Service Context.

The signature of the logChargingInfo() method looks like this:

public void logChargingInfo(ChargingInfo info)

The ChargingInfo class is a container with fields and corresponding set-methods for all charging-specific data. Before applying the logChargingInfo() method, all mandatory parameters must be set. Parameters that are not set will cause a null value to be written to the Charging Log. The methods available for the ChargingInfo class are shown in the table below. All fields of type long that represents a time is in milliseconds. A start or stop time is represented as the number of milliseconds since January 1, 1970 00:00:00.000 GMT.

Method

Parameter

Description

addAdditionalInfo

(String xmlTag,
String xmlValue)

Adds user defined additional charging parameters. These parameters will be saved in the additional_info field of the charging database as XML elements. This method can be called more than once to add more parameters.

clear

()

Clears all data and restores the default values in the ChargingInfo instance

setAmountOfUsage

(long amountOfUsage)

Sets the used amount. Used when the charging is not time dependent, for example, flat rate services.

setCompletionStatus

(int status)

Sets transaction completion status. Indicates if the transaction was completed or not. If the transaction is divided into parts, the completion status also indicates if all transaction parts have been sent.The class defines constants that should be used:

ChargingInfo. COMPLETION_STATUS_COMPLETED

ChargingInfo. COMPLETION_STATUS_PARTIAL

ChargingInfo. COMPLETION_STATUS_FAILED

ChargingInfo.COMPLETION_STATUS_POLICY_REJECTED

setConnectTime

(long connectTime)

Sets a timestamp telling when the destination party responded

setDestinationParty

(String
destinationParty)

Sets the destination party's address

setDurationOfUsage

(long
durationOfUsage)

Sets the total time the service used network resources

setEndOfUsage

(long endOfUsage)

Sets a timestamp telling when the service stopped using network resources

setOriginatingParty

(String originatingParty)

Sets the originating party's address

setServiceName

(String serviceName)

Sets the name of the used service

setSessionID

(long sessionId)

Sets the session ID. The session ID is the connection between related charging transactions.

setTransactionPart
Number

(int transactionPartNumber)

Sets the transaction part number. Used if the transaction is divided into different parts. Increment the number by one for each transaction part.

setStartOfUsage

(long
startOfUsage)


Sets a timestamp telling when the service started using network resources

setUserID

(String
userId)


Sets the ID of the application that has used the service

The following example will show how to obtain a reference to the charging service and create a Charging Data Record in the charging table in the database. The class is in the form of a helper, that is created at the start of service usage for a specific subscriber. When the subscriber stops using the service, the createChargingRecord() method is called to produce the charging record. The class uses the timeManager utility service from the com.incomit.time package to retrieve the system time at start and stop of service usage.

Listing 3-24 ChargingHelper.java

package example.helloslee;
import com.incomit.slee.*;
import com.incomit.slee.time.*;
import com.incomit.slee.charging.*;
public class ChargingHelper {
  private ServiceContext itsServiceContext = null;
  private ChargingService itsChargingService = null;
  private SLEETimeManager itsTimeManager = null;
  private ChargingInfo itsInfo;
  
  public ChargingHelper (ServiceContext aServiceContext,
                         int aSessionId,
                         String aUserId) {
    itsServiceContext = aServiceContext;
    itsChargingService = itsServiceContext.getChargingService();
    SLEEContext sc = itsServiceContext.getSLEEContext();
    itsTimeManager = sc.getTimeManager();
    itsInfo = itsChargingService.createChargingInfo();
    itsInfo.setSessionID(aSessionId);
    itsInfo.setServiceName(itsServiceContext.getName());
    itsInfo.setUserID(aUserId);
    itsInfo.setStartOfUsage(itsTimeManager.getTime());
    itsInfo.addAdditionalInfo("additionalinfo", "testvalue");
  }
  public void createChargingRecord () {
    itsInfo.setEndOfUsage(itsTimeManager.getTime());
    itsInfo.setCompletionStatus(ChargingInfo
                             .COMPLETION_STATUS_COMPLETED);
    itsInfo.addAdditionalInfo("moreinfo", "someothervalue");
    
    try {
      itsChargingService.logChargingInfo(info);
    } catch(ChargingException ce) {
      //Handle Exception
    }
  }
}

Fields in the ChargingInfo object that is not set will use default or null values. The call to setCompletionStatus() is not necessary, since status COMPLETED will be used by default.

 


Using the time service

The time service was introduced in the previous section. Except from using the Time Manager class to retrieve the system time, it also contains functionality to handle timers.

With the use of timers, the application programmer can protect programs from hanging and avoid dead-lock situations. For example, when requesting resource over a high latency network, the programmer can include a timer with a certain treshold value. If the network resource is unavailable, the timer will expire, and the program can continue, taking any actions necessary to report the faulty resource etc. If the resource is available, the timer is reset and execution continues normally.

With periodic timers, events can be generated repeatedly, with regular intervals. For example, an application can read the contents of a database table containing subscription numbers, and use the result to submit a group SMS.

Also, it is recommended to create a new object reference for each timer to be used. If the same reference is used and you want to cancel a timer, any of the timers using the same object reference could be cancelled.

Listing 3-25 Timer.java

package example.helloslee;
import com.incomit.slee.*;
import com.incomit.slee.time.*;
public class Timer {
  private ServiceContext itsServiceContext = null;
  private SLEETimeManager itsTimeManager = null;
  private String timerRef;
  
Object synchObject = new Object();
  
  public Timer (ServiceContext aServiceContext, 
                String reference)
  {
    itsServiceContext = aServiceContext;
    SLEEContext sc = itsServiceContext.getSLEEContext();
    itsTimeManager = sc.getTimeManager();
    timerRef = reference;
  }
  
  public void removeTimer () {
    itsTimeManager.cancelTimer(timerRef);
  }
  public void startTimer () {
    itsTimeManager.scheduleTimer(false, 
                                 10 * 1000, // 10 seconds
                                 new MyTimerListener(this),
                                 timerRef);
  }
}

Listing 3-26 Timer.java -method: MyTimerListener

class MyTimerListener implements SLEETimerListener {
  private Timer timer = null;
 
  MyTimerListener(Timer timer) {
    this.timer = timer;
  }
  public void processTimer(Object reference) {
    synchronized (timer.synchObject) {
    timer.synchObject.notify();
    }
  }
}

Listing 3-27 PeriodicTimer.java

package example.helloslee;
import com.incomit.slee.*;
import com.incomit.slee.time.*;
import com.incomit.slee.event.*;
public class PeriodicTimer {
  private ServiceContext itsServiceContext = null;
  private SLEETimeManager itsTimeManager = null;
  private EventLogService itsEventService;
  private String timerRef = "periodic timer";
  public static final long PERIOD = 2000;
  
  Object synchObject = new Object();

Listing 3-28 PeriodicTimer.java (continued)

 public PeriodicTimer (ServiceContext aServiceContext) {
    itsServiceContext = aServiceContext;
    SLEEContext sc = itsServiceContext.getSLEEContext();
    itsEventService =  sc.getEventLogService();     
    itsTimeManager = sc.getTimeManager();
  }
  public void doPeriodicTask (int cnt) {
    String message = "This is periodic task " + cnt;
    itsEventService.logEvent(itsServiceContext
                             .getInstanceName().getBytes(),
                             EventLogService.LOW,
                             cnt,
                             message.getBytes());
  }
  
  public void removeTimer () {
    itsTimeManager.cancelTimer(timerRef);
  }
  public void startTimer () {
    itsTimeManager.scheduleTimer(true,
                                 period,
                                 new MyTimerListener(this, 10),
                                 timerRef);
    try {
      synchronized (synchObject) {
        synchObject.wait();
      }
    }
    catch (java.lang.InterruptedException ie) {
      // Handle exception
    }
  }
}

Listing 3-29 PeriodicTimer.java (continued)

public class MyTimerListener implements SLEETimerListener {
private int counter = 0;
private int noOfEvents;
private PeriodicTimer timer;
 
  MyTimerListener(PeriodicTimer timer, int noOfEvents) {
    this.timer = timer;
    this.noOfEvents = noOfEvents;
  }
  public void processTimer(Object reference) {
    if (counter < noOfEvents) {
      timer.doPeriodicTask(counter);
      counter++;
      }
    else {
      synchronized (timer.synchObject) {
        timer.synchObject.notify();
        //do stuff
      }
    }
  }
}

 


Using the trace service

The trace service enables to trace execution of a program. It can be used, for example, when a service is suspected to be erroneous. The trace output is written to file. For performance reasons it is recommended that the application performs a check on the trace active flag before calling the logTrace method. The trace file that is generated is service specific.

All services using the trace service will have an associated buffer class. This class will buffer all trace messages from the service until the size of the buffer reach the specified size setting and then flush the buffer to a file.

The information that gets written to the trace log is controlled by using trace filter groups. It is possible to turn on and off different pre-defined trace groups at runtime by supplying a new filter value. The following filters are available:

Filter

Description

Value

METHOD_IN

Log trace at entry of method.

1

METHOD_OUT

Log trace at exit of method.

2

USERDEF_1

User defined trace (DEBUG)

4

USERDEF_2

User defined trace (INFO)

8

USERDEF_3

User defined trace (WARNING)

16

USERDEF_4

User defined trace (ERROR)

32

USERDEF_5

User defined trace

64

USERDEF_6

User defined trace (RACE)

This trace level shall be used for measuring the time from when entering a certain code segment to a existing ac certain code segment. Normally a code segment is from when entering a module to exiting a module. The elapsed time shall be provided in the trace.

128

RAW_DATA

Log any data

256

EXCEPTION_LOG

Writes trace information at exceptions that breaks the execution flow.

512

TRAFFIC FLOW

Writes trace information when traffic related requests (both application and network initiated) are received by and sent from the service.

1024

To specify which groups to include in the trace log, the values for the different filters are added. For example, if you want to include the entry and exit of a method, as well as information in user defined trace group 4, you should specify a filter value of 35:

1 + 2 + 32, or METHOD_IN + METHOD_OUT + USERDEF_4

It is not recommended, for performance reasons, to enter a filter value equal to 0 to disable trace logging. Instead the trace for that service should be deactivated.

The code example below shows how to set up a reference to the trace service. It then defines a set of methods that shows how to use the trace methods available in the API. The methods, along with initializations, will be executed from the trace() method, which is defined at the end of the example.

Listing 3-30 Tracer.java

package example.helloslee;
import com.incomit.slee.*;
import com.incomit.slee.trace.*;
public class Tracer {
  private ServiceContext itsServiceContext;
  private TraceLogService itsTraceService;
  public Tracer (ServiceContext aServiceContext) {
    itsServiceContext = aServiceContext;
    itsTraceService = itsServiceContext.getTraceService();     
  }

The call to the ordinaryTrace() method will cause the trace to attempt a trace of the method entry and exit. It uses the API methods logTraceIntoMethod() and logTraceOutOfMethod() with the following signatures:

public void logTraceIntoMethod(java.lang.String className,
                               java.lang.String methodName)
public void logTraceOutOfMethod(java.lang.String className,
                                java.lang.String methodName)

The parameter className denotes the current, defining class, and methodName is the name of the method in which the statement is included. The calls to logTraceIntoMethod() and logTraceOutOfMethod() will always cause its information to be included in its corresponding trace group.

Listing 3-31 Tracer.java (continued) -Example of method in and method out trace

public void methodInmethodOut() {
      if (itsTraceService.isGroupTraceActive(TraceLogService.METHOD_IN)) {
		itsTraceService.logTraceIntoMethod("Tracer", 
						"methodInmethodOut");
	}
	// Perform method-specific functionality
     if (itsTraceService.isGroupTraceActive(TraceLogService.METHOD_OUT)) {
		itsTraceService.logTraceOutOfMethod("Tracer", 
						"methodInmethodOut");
	}
 }

The call to the userdef1Trace() method will cause the trace to attempt a trace on user defined level 1. It uses the API methods logTrace() with the following signature:

public void logTrace(java.lang.String className,
			java.lang.String methodName,
			int traceGroup,
			java.lang.String info)

The information from logTrace() can be included in any trace group (the value of traceGroup). logTrace() also allows the inclusion of an arbitrary string in the generated trace log message.

Listing 3-32 Tracer.java (continued) -Example of userdef 1 trace

public void userdef1Trace () {
	if (itsTraceService.isGroupTraceActive(TraceLogService.USERDEF_1)) {
		for (int i = 0; i < 10; i++) {
			itsTraceService.logTrace("Tracer", 
					"userdef1Trace", 
					TraceLogService.USERDEF_1, 
					"Trace Log Record " + i);
		}
	}
}

The call to the traceFaultyMethod() will generate an arithmetic exception, which will be logged in the trace log. To facilitate the tracing of exceptions, the API offers the logTraceException() method. It has the following signature:

public void logTraceException(java.lang.String className,
                              java.lang.String methodName,
                              int traceGroup,
                              java.lang.String info,
                              java.lang.Throwable exception)

The className and methodName are the same as for the logTrace() method. The trace log message will be included in the trace group corresponding to the value of the traceGroup parameter. Information about the exception, the exception stack trace from the exception object, will also be included in the trace log message, along with an arbitrary string (info).

Listing 3-33 Tracer.java (continued) -example of exception trace

 public void traceFaultyMethod () {
      try {
        int a = 42;
        int b = 0;
        int c = a / b;
      } catch(ArithmeticException ae) {
	if (itsTraceService.isExceptionTraceActive()) {
		itsTraceService.logTraceException("Tracer", 
 						"traceFaultyMethod", 
						TraceLogService.EXCEPTION_LOG,
						Division by zero!",
						ae);
	}
      }
    }
  }

The traceRawData() method below shows how to trace any data in the form of a byte array. For this, the API offers the logTrace() method with the following signature:

public void logTrace(byte[] buf,
                     int off,
                     int len)

The buf parameter is a byte array, off indicates the starting position in this buffer, and len how many bytes from the buffer that will be included in the trace log message. The call to logTrace below will cause a byte array representing the string "rawdata 1 2 3" being included in the trace log.

Listing 3-34 Trace.java (continued) -example of using raw data trace

 public void traceRawData () {
    if (itsTraceService.isGroupTraceActive(TraceLogService.RAW_DATA)) {
	String rawData = "Testing rawdata 1 2 3";
	itsTraceService.logTrace(rawData.getBytes(), 
                               8, 
                               rawData.length());
    }
  }

When exceptions occur, but there are alternative execution paths can be used, so the request still can be executed, the method logTraceException(...) should be used according to the example below. itsTraceService is the trace service.

Listing 3-35 Example of use of logTraceException

if (itsTraceService.isExceptionTraceActive()) {
                m_ts.logTraceException(CLASSNAME,
                                       METHODNAME,
                                       TraceLogService.EXCEPTION_LOG,
                                       e.getMessage(),
                                       e);
            }

To trace the traffic execution flow, the method logTrafficFlowTrace(...) shall be used. It shall only be used for the traffic interfaces. A traffic flow context should be provided, with information on which Service Provider and application that performed the request. In the example below, m_trafficFlowContext contains the Service Provider ID and application ID of the requester in the format m_trafficFlowContext = applicationId + "\\" + serviceProviderId;

Listing 3-36 .Example of use of logTrafficFlowTrace

if (m_ts.isTrafficFlowTraceActive()) {
	Object[] params = {listener, data, address, 
				serviceCode, 
				requesterID};
	m_ts.logTrafficFlowTrace(CLASSNAME, 
					METHODNAME,
					m_trafficFlowContext, 
					params);

}

 

Skip navigation bar  Back to Top Previous Next