Broker events that are triggered by various transport protocols.

# EventBroker Service

Overview

Model

Event Message Specification

Configuration

- Defaults
- Resources
- Connections
- Remote Access
- Events
  - Naming Hierarchy
  - Security
  - Process Flows

Event Handling Agents

- Process Flow
- Dynamic Listener

Deployment

- Standalone Application
- Foundation Service Deployment

## Overview

The EventBroker Service provides the capability of receiving external events and then performing some desired action based on the information that is received. Currently, there are two ways that an event can be handled. The service may have statically defined process flows configured that should be instantiated to process the message. Alternatively, we allow other applications to register themselves with the EventBroker Service at runtime so that they can receive event notifications as well. When an event is received by the EventBroker Service, it will be delivered to one or more of these types of handlers to process the event.

Once the service has completed the necessary actions for this event, it has the capability of formatting a response and sending it back to the event originator. Whether or not a response is sent is determined by the event originator. The sender of the event can specify if no response is required (fire-and-forget), if an acknowledgement of receipt is required, or if a result set is expected (request/response).

In order for the EventBroker Service to receive external events, monitors or transports must be configured. Each transport runs in its own thread of execution. When it receives an event it will create an EventRequest (incoming message/ResponseAgent) and put it on the synchronized event queue. Any number of EventManager threads can be configured to act as workers and pull EventRequests off the event queue for processing. These worker threads are awakened when a monitor has placed an EventRequest on the event queue. At that time the EventManager parses the incoming XML message to determine the event name, its properties, and its body. It then looks in its shared configuration to determine what process flows should be instantiated and/or what listeners should be notified of the event. The EventManager utilizes a ThreadPool to efficiently start flowengines to run process flows and listener dispatchers to dispatch event notification to listener applications.

## Model

The basic model of the EventBroker Service is shown below.

The EventBroker Service's main thread of execution will parse the broker configuration to determine among other things what event monitors (transports) to start. Each of these monitors are started in their own thread of execution and wait for events to trigger them. The main thread will also parse the event flow configuration to determine the process flows that should be executed when incoming events are triggered.

Ultimately, triggered events are processed by EventManager thread(s). They are awakened when monitoring transports place event requests onto the event queue. The EventManager's job is to parse the incoming event request in order to create an event broker message that will be used by participating handling agents. This message will contain information that was parsed from the incoming event request. The body of the message will initially be saved as a DOM DocumentFragment.

Once an incoming event request has been parsed, EventManger(s) will then use the event thread pool to execute participating handling agents.

## Event Message Specification

All incoming events must be presented in well-formed XML format. The event message specification is as follows:

    <sas-event:Event xmlns:sas-event="http://www.sas.com/xml/namespace/services.events-1.1" sas-event:name="event_name">
       <sas-event:Header>
          <sas-event:Version>1.0</sas-event:Version>
          <sas-event:Identity>UID</sas-event:Identity>
          <sas-event:Credentials sas-event:name="userid" sas-event:password="password" sas-event:domain="domain" sas-event:sessionContextId="session_context_id" sas-event:sessionContextLockId="session_context_lock_id"/>
          <sas-event:Priority>Java thread priority</sas-event:Priority>
          <sas-event:SentFrom>sender description</sas-event:SentFrom>
          <sas-event:SentAt>UTC</sas-event:SentAt>
          <sas-event:Response sas-event:type="none|ack|result"/>
          <sas-event:Properties>
             <property_name>property_value</property_name>
                                   ....
          </sas-event:Properties>
       </sas-event:Header>
       <sas-event:Body>
          body content...
       </sas-event:Body>
    </sas-event:Event>

The namespace associated with an event is http://www.sas.com/xml/namespace/services.events-1.1. Individual properties and body content are application specific so their associated namespaces are application specific as well.

Explanations of the elements are in the following table:

Element | Description
Event | Root element that names the event.
Header | Begins the event header properties.
Version | Version of the event message must be 1.0. Other versions may be added in the future to support additional fields.
Identity | Unique identifier. This identifier will be included in a response sent from a broker so that a sender can use it to correlate a request that it has sent. You can use a VMID generator for this purpose.
Credentials | Credentials that are used for authentication and authorization checks. Events defined at a broker can be configured so that the sender of the event must be authenticated and authorized to run the event. An event can also be configured to run under a particular security context. It is expected that the underlying transport that is used to send an event will perform the necessary encryption to hide credentials. As an alternative to passing in userid, password, and domain, you can pass in a session_context_id and optional session_context_lock_id. In this case the authenticated user context that is associated with the session context obtained from the passed in session context id will be used as the security context. The broker will also maintain a usage count for this session context so that it will be destroyed only after all handling agents have completed execution. If a session context lock object has been saved with the session context lock id as an attribute in the session context, the broker will also unlock the session context before destroying it.
Priority | Priority is mapped to a Java thread priority so that process flows and/or listener dispatchers can be run at different priority levels.
SentFrom | Description of the event sender that is used for logging purposes only.
SentAt | Time the event was sent. This information is echoed to the sender along with completion times. All times should be formatted according to the International Standard ISO 8601. A brief summary is available as a W3C tech report on ISO8601.
Response | The sender of an event can specify the type of response it wants. The supported types are no response (none), acknowledgement (ack), and request/response (result). Both none and acknowledgement type of responses act as broadcast event requests. That is, they are broadcasted to all handling agents configured/registered at the broker service. A handling agent can be a configured process flow or a registered event listener. An acknowledgement request causes the broker to send an acknowledgement of receipt. To request the broker to send the results of event execution, a response type of result would need to be requested. A response type of result acts as a request/response event request. That is, it is sent to one and only one handling agent and the broker will always send a result response back to the sender of the event.
Properties | The sender can also send user-defined properties that can be utilized during event execution.
Body | The actual message content.

If an incoming event request cannot be parsed according to the above specification, the request is deemd as unstructured. If the broker or transport that received the incoming message has a default event name configured, the entire request will be treated as the body and the resulting message will be routed to all handling agents configured/registered for the default event.

## Configuration

The SAS Management Console is an application used to configure SAS resources. In particular, the Foundation Services Manager Plug-in component of the SAS Management Console is used to manage business intelligence foundation services. The following configuration items apply to an EventBroker service.

- Defaults
- Resources
  - Event Manager definitions
  - Thread Pool definitions
- Connections
- Remote Access
- Events
- Process flows

### Defaults

Allows an administrator to associate a default event name to incoming event requests that cannot be parsed according to the published event message specification. This association allows all unstructured events to be handled by the service in a consistent manner. Unstructured requests have an implicit response type of none; thus, events that are designated to handle unstructured requests must be configured/registered as broadcast types of events. Refer to events configuration for details about broadcast events.

### Resources

An administrator can configure the following resources:

- The number of threads to start in order to process incoming events.
- The maximum number of events that can be queued (waiting to be processed). When this threshold is hit, all transport monitors are prevented from adding additional events to the event queue. Transport monitors are resumed when the number of queued events falls below this threshold.
- Thread pool used to run process flows and dispatch listener applications.

### Connections

An administrator port must be defined so that administrative commands can be issued to the service. The EventBrokerServiceAdminClient application can be used for this purpose. This application can be used to shutdown or quiesce a broker as well as perform other operations. However, it is not recommended to shutdown or quiesce a broker in this manner when it has been deployed by the Foundation Services. Instead, use normal service destroy mechanisms in this case.

Transport monitors must be defined to trigger event processing. The following transports are supported:

- HTTP (Post) supports SOAP, SSL
- Mail (IMAP,POP3,SMTP)
- JMS (provider-independent) Uses JNDI to lookup administered JMS objects in LDAP or on the local file-system.
- MQJMS (WebsphereMQ JMS-provider, formerly MQSeries)
- JMQ (SunONEMQ JMS-provider, formerly iPlanetMQ)
- IOM (Java ORB)

SOAP clients must set the event within the SOAP body. The broker will return responses within the SOAP body as well.

Java clients can also use RMI (remote method invocation) to send events to a broker. However, the service must be enabled for remote access. Java clients will use the EventBrokerServiceInterface to send events.

### Remote Access

Enabling remote access causes the service to register itself to the RMI Registry. Remote access must be enabled if the service is to be used in the following capacities:

- Allow listener applications to lookup the service in the RMI Registry in order to register interest in particular events.
- Allow Java clients to lookup the service in the RMI Registry in order to send events.

A codebase can be specified either through configuration or by specifying the java.rmi.server.codebase property. For example, -Djava.rmi.server.codebase="file:/c:/path_to_jars/sas.svc.events.jar file:/c:/path_to_jars/sas.svc.core.jar".

### Events

Any number of events can be configured for an EventBroker service. An event is configured or registered as one of the following types:

- Broadcast (Unidirectional, no response is sent to originating client)
- Request/Response (Bidirection, response is sent to originating client)

The following table shows the mapping of event request response types to configured/registered event types:

Response Type | Configured/Registered Type
none | Broadcast
ack | Broadcast
result | Request/Response

Refer to the event message specification for details about how to format an event request.

An event can be configured to run one or more process flows. An event can be registered by a listener application as well. The broker learns about these events dynamically. That is, no prior event configuration must be done before a listener registers with the broker.

The expected behavior of the broker is to deliver broadcast events to all handling agents. In contrast, the broker will deliver a request/response event to a single handling agent. Making this type of event associated to a single handling agent is accomplished by:

- Configuration enforces that a request/response event cannot have more than one process flow defined.
- The broker allows only one listener to register for a particular request/response event.

If both a process flow is configured and a listener is registered for a particular request/response event, the registered listener will be given precedence so it becomes the single handling agent in this case.

#### Naming Hierarchy

Events can be named such that they are part of a naming hierarchy. Names in a hierarchy are separated by a period. For instance consider the following simple naming hierarchy: Animals, Animals.Dogs, and Animals.Dogs.Retriever If a broadcast event is triggered for Animals.Dogs.Lab, it will be delivered to all handling agents configured/registered for Animals.Dogs.Lab as well as any configured/registered for Animals.Dogs and Dogs. So therefore in this case, even though we did not have a Animals.Dogs.Lab event defined, it would have been handled by the handling agents of the more general Animals.Dogs and Dogs events assuming that these events are broadcast events for this illustration.

Request/Response type of events are handled a little differently. They are delivered to a single handling agent for processing. If there is not a configured/registered event that matches the exact name of the incoming event request, the naming hierarchy will be searched to find the best possible match. For example consider the previous simple naming hierarchy. If a request/response event is triggered for Animals.Dogs.Lab, the naming hierarchy would resolve Animals.Dogs as the best match assuming for illustration purposes that Animals.Dogs is configured/registered as a request/response event.

#### Security

Events can be configured so that its associated process flows will not be run unless the sender of an event has the appropriate authorization. User authorizations are configurable for each event. You must first define each user or group and then give them Execute permission to run a particular event. You will use the SAS Management Console User Manager plug-in to define groups and users. You will use the SAS Management Console Authorization Manager plug-in to define Execute permisson. Once these have been defined, you can edit the event's Authorization tab by either granting or denying a user or group Execute permission to run this event's process flows.

There are several runtime requirements needed in order for this authentication and authorization process to work properly. First, the User Service along with its dependent services must be available (deployed) so that it can be used by this service. The User Service coupled with the Security Service provides the mechanism of authenticating a particular user to a SAS Metadata Repository. The following configuration files are required:

- LoginModule configuration

  This file must contain a PFS application name with a com.sas.services.security.login.OMILoginModule login module defined.

- Java2 policy configuration

  You must grant the appropriate codebase permissions.

- PermissionFactory configuration

  Currently, this configuration file must exist even if its empty.

Events can also be configured to run their associated process flows under a particular security context.

Additionally, you will need to setup subject based security with JAAS policy configuration file to restrict access to resources from process flows running under particular security contexts.

The following table shows how to set the location of the various configuration files:

configuration file | location
LoginModule configuration file | java.security.auth.login.config property
Java2 policy file | java.security.policy property
JAAS policy file | java.security.auth.policy property
PermissionFactory configuration file | com.sas.security.PermissionFactory.config.file property, or explicitly at the following location: c:\PermissionFactory.config, or by the java.home property concatenated with the following path: /lib/security/PermissionFactory.config

You must run with a java security manager. To run with the default security manager, use the java.security.manager property.

The sender of an event will use the Credentials element of the event message specification to send an event with security credentials. You can set a default domain in the User Service configuration so that domain is not a required attribute.

#### Process Flows

A broadcast event can have more than one process flow configured as handling agents, while a request/response event can only have one process flow configured.

A process flow is configured using a PFD (Process Flow Diagram). You define a process flow by configuring process node dependencies. A process node is represented as a Java class and it can have one or more inputs and outputs. Inputs can be further distinquished as required or optional. The process flow designer is responsible for providing the code behind each process node. The configuration process gives the designer the ability to create code templates.

During broker execution the runtime flowengine is responsible for firing (executing) the process nodes in a prescribed order based on dependencies and feedback propagated from individual nodes within the process flow.

## Event Handling Agents

There are two types of event handling agents:

- Process Flow
- Dynamic Listener

### Process Flow

A runtime flowengine is instantiated when a process flow needs to be run in order to process an event. The flowengine is responsible for firing nodes in a process flow in a prescribed order based on dependencies and feedback propagated from individual nodes within the process flow. The flowengine calls a process node (or plug-in node) by instantiating the Java class associated with that node. Refer to the ProcessNodeInterface for details about implementing a process node.

Once a process node is executing, it can operate on its input messages, perform any desired logic, propagate output messages to downstream process nodes, and set responses that will ultimately be sent to the event originator. Refer to the ProcessNodeHandlerInterface for details on how process nodes correspond with the flowengine. Also, refer to the MessageInterface on how to manipulate messages sent to and from nodes.

Currently all nodes in a process flow are executed synchronously. That is, nodes within a process flow cannot execute concurrently.

### Dynamic Listener

Applications can also register themselves to an EventBroker service for event notification at runtime. An application basically looks up the broker service at a designated RMI Registry in which the application is returned a ListenerRegisterInterface. With this interface the application can add itself as a listener for one or more events. This event is dynamically added to the broker so that when an event associated with a listener is triggered, it is presented to the listener. Refer to the ListenerInterface for details about implementing a dynamic listener.

The listener application basically acts like a process flow with a single node. It can extract and manipulate the input message as well as set responses to send to the event originator. Refer to the MessageInterface on how to manipulate a message that is received by a listener.

## Deployment

There are two ways to deploy the EventBroker Service:

- As a standalone application
- Using Foundation Service deployment utilities

### Standalone Application

You can deploy an EventBroker service from the command-line or by executing the sas.svc.events.jar jar file.

A console application will be displayed that will allow you to specify a metadata source configuration which can then be used to deploy an EventBroker service and its dependent Foundation services. A metadata source configuration consists of the following information:

- Metadata source (SAS Metadata Repository or URL-accessible file)
- Service deployment name
- Optional, retrictive service deployment group names

Once an EventBroker service has been successfully deployed, it can then be used to process incoming events that are received on its configured tranports.

### Foundation Service Deployment

You can deploy the EventBroker Service using Foundation Service deployment utilities. Once an EventBroker service has been deployed in this manner, it can be discovered by the Discovery Service upon demand.

#### Using the Discovery Service

An EventBroker service can be discovered just like any other service.

    final Class[] desiredServiceCapabilities = new Class[] {
        com.sas.services.events.broker.EventBrokerServiceInterface.class};

    _eventBrokerService = (EventBrokerServiceInterface)
        DiscoveryService.defaultInstance().findService(
           new ServiceTemplate(
              desiredServiceCapabilities,
              null);//no additional filter criteria

    // send an event to be processed synchronously
    _eventBrokerService.sendSyncEvent(event);

You can also use the value-add EventBrokerDiscovery Service to locate EventBroker services based on whether or not a broker can process a particular event.

    final Class[] desiredServiceCapabilities = new Class[] {
        com.sas.services.events.discovery.EventBrokerDiscoveryServiceInterface.class};

    _eventBrokerDiscoveryService = (EventBrokerDiscoveryServiceInterface)
        DiscoveryService.defaultInstance().findService(
           new ServiceTemplate(
              desiredServiceCapabilities,
              null);//no additional filter criteria

    // locate brokers that can process "myEvent"
    Set brokers = _eventBrokerDiscoveryService.locateBrokers("myEvent",
                                                             EventBrokerDiscoveryServiceInterface.LOCATE_ALL)

    // iterate over brokers
    Iterator iterator = brokers.iterator();
    while( iterator.hasNext() )
    {
       EventBrokerServiceInterface _eventBrokerService =
           (EventBrokerServiceInterface) iterator.next();

       // send an event to be processed synchronously
       _eventBrokerService.sendSyncEvent(event);
    }

Refer to the EventBrokerServiceInterface for details about interacting with this service to send synchronous and asynchronous events.