Working with Events
- Events and the CASActionResults Class
- Log Events
- Performance Events
- Disposition Events
- Message Tag Events
- Server Events
- Socket Events
Events and the CASActionResults Class
By default, all server events are returned as part of the CASActionResults object that is returned by the invoke() method. This means that you have access to all events after the action is complete. Alternatively, you can register a listener for each type of event to receive the event as it is streamed from the server.
Log Events
Log events are generated by the server when information is sent to the log. A log event consists of a type (such as WARN or ERROR) and a message.
If you want to receive log events as they are streamed from the server, you need to register a CASLogEventListener on the action options object before you invoke the action:
// Set the log event listener. This handles the log events as they
// come from the server instead of accessing them from the results
// after the action is complete.
options.setLogEventListener(new CASLogEventListener() {
@Override
public boolean handleLogEvent(CASActionOptions options, CASLogEvent logEvent) {
System.out.println("# " + logEvent);
// Return the propagate flag. If true, the log event
// is propagated to the result object. Otherwise nothing
// else will be done with the log event.
return false;
}
});
Performance Events
Performance events are generated by the server when an action is designed to inform the caller about certain performance characteristics of the action. A performance event can include timings (elapsed time, CPU time, and so on), memory usage, node usage, and CPU core usage.
If you want to receive performance events as they are streamed from the server, you need to register a CASPerformanceEventListener on the action options object before you invoke the action:
// Set the performance event listener. This handles the performance events as they
// come from the server instead of accessing them from the results
// after the action is complete.
options.setPerformanceEventListener(new CASPerformanceEventListener() {
@Override
public boolean handlePerformanceEvent(CASActionOptions options, CASPerformanceEvent performanceEvent) {
System.out.println("# " + performanceEvent);
// Return the propagate flag. If true, the performance event
// is propagated to the result object. Otherwise nothing
// else will be done with the performance event.
return false;
}
});
Disposition Events
Disposition events are generated by the server when an action completes or fails. A disposition event contains a severity, reason, and message.
If you want to receive disposition events as they are streamed from the server, you need to register a CASDispositionEventListener on the action options object before you invoke the action:
// Set the disposition event listener. This handles the disposition events as they
// come from the server instead of acessing them from the results
// after the action is complete.
options.setDispositionEventListener(new CASDispositionEventListener() {
@Override
public boolean handleDispositionEvent(CASActionOptions options, CASDispositionEvent dispositionEvent) {
System.out.println("# " + dispositionEvent);
// Return the propagate flag. If true, the disposition event
// is propagated to the result object. Otherwise nothing
// else will be done with the disposition event.
return false;
}
});
Message Tag Events
A message tag event is different from the other event types. For a few actions, the action can send a message back to the client during the invocation of the action to request additional information. This is done with a message tag. See com.sas.cas.message.CASMessageHeader for the list of tags.
The addTable action in the table action set is an example of an action that uses message tag events. The addTable action sends a message back to the client so that the client can determine when to send data rows to the server and populate a table. In order to handle this message, which has a DATA tag, you must register a message tag handler (of type CASMessageTagHandler) on the action options.
The following code shows an example of CASMessageTagHandler, which simply returns no data:
@Override
public boolean handleMessageTag(CASMessageTagEvent event) throws CASException, IOException {
// Just create the table; don't send any rows
CASDataAppender.sendZeroRows(event);
// Do not propagate the response
return false;
}
To use this message tag handler, you must register the handler on the action options before you invoke the action:
options.setMessageTagHandler(CASMessageHeader.TAG_DATA, <the handler>);
To send data rows to the server (to append data to the table), use this message handler, which is more sophisticated than the first example:
@Override
public boolean handleMessageTag(CASMessageTagEvent event) throws CASException, IOException {
// Get the variable list
Addtablevariable[] vars = (Addtablevariable[]) event.getOptions().get(AddTableOptions.KEY_VARS);
Integer reclen = (Integer) event.getOptions().get(AddTableOptions.KEY_RECLEN);
if (reclen == null) {
// This shouldn't happen. The server should have verified.
throw new CASException("Missing reclen");
}
// Create our data appender
CASDataAppender appender = new CASDataAppender(event, vars, reclen, bufSize);
// Creates a new random generator with the given seed
Random r = new Random(0);
for (int i = 0; i < nrows; i++) {
appender.setDouble(0, i);
appender.setString(1, "Some String at " + i);
appender.setDouble(2, r.nextDouble());
appender.appendRecord();
}
appender.close();
// Do not propagate the response
return false;
}
The preceding code is suitable for handling message tag events from the addTable action (com.sas.actions.table.AddTableOptions class). Another action that uses message tag events, the upload action (a specialized com.sas.cas.io.UploadDataTagHandler class), is available. It accepts a filename or an InputStream as the input.
Server Events
You can register for a few types of events generated by the server. These events include:
- Caslib list has changed
- Table list has changed
- Action set has been added
- Data source list has changed
- Permissions have changed
To register for one or more of these events, add an event listener:
client.addEventListener(CASConstants.EVENT_FLAG_CASLIBS, new CASEventListener() {
@Override
public void handleCASEvent(long flag) {
// Do something with the event
}
});
You can register for multiple events:
client.addEventListener(
CASConstants.EVENT_FLAG_CASLIBS | CASConstants.EVENT_FLAG_TABLES,
new CASEventListener() {
@Override
public void handleCASEvent(long flag) {
// Do something with the event
if (flag == CASConstants.EVENT_FLAG_CASLIBS) {
// Do something - the caslibs have changed
}
else if (flag == CASConstants.EVENT_FLAG_TABLES) {
// Do something - the tables have changed
}
}
});
Server events are packaged as part of an action response, so these are not asynchronous events. Event notification occurs when an action completes. Some types of clients might desire to "poll" for events. This can be done simply by invoking any action, such as com.sas.cas.actions.builtins.PingOptions.
Socket Events
The CASSocketEventListener class provides callbacks for when a new socket connection is established and when a socket connection is closed. This enables you to customize socket settings, such as the time-out.
// Register our socket event listener
client.setSocketEventListener(new CASSocketEventListener() {
@Override
public void handleSocketConnectionEvent(CASClientInterface client, Socket socket) {
System.out.println("Socket opened");
}
@Override
public void handleSocketClosedEvent(CASClientInterface client, Socket socket) {
System.out.println("Socket closed");
}
});