SAS 9.1.3 Integration Technologies » Developer's Guide


Java Clients

Events and Connection Points

Some IOM objects support one or more event interfaces, which are interfaces that contain operations that are to be implemented by the client (in Java). The operations are called by the IOM object whenever some particular event occurs. For example, the SAS Language Component supports an event interface and calls operations on it whenever a SAS procedure or DATA step finishes execution, which allows you to check the progress of a submitted SAS program. To listen for events from an IOM object, you need to know how to use skeletons and connection points.

Extending Skeletons

A skeleton is the complement of a stub. While a stub is a Java class that repackages method calls into requests and forwards them to the IOM server, a skeleton is a Java class that accepts requests from the IOM server and repackages them into Java method calls. You provide the implementation of the method calls by extending the skeleton with implementations of all the methods in the event interface. When an event arrives, the IOM Bridge for Java provides a temporary thread of execution and calls the appropriate method through the skeleton.

The following example demonstrates how to extend the skeleton for the event interface supported by the SAS Language Component:

public class LanguageEventsListener extends 
  com.sas.iom.SASEvents._ILanguageEventsImplBase
{
  // implement declared methods in com.sas.iom.SASEvents.ILanguageEvents
  public void ProcStart(java.lang.String procname) {
    /* your implementation */ }
  public void SubmitComplete(int sasrc) { /* your implementation */ }
  public void ProcComplete(java.lang.String procname) {
    /* your implementation */ }
  public void DatastepStart() { /* your implementation */ }
  public void DatastepComplete() { /* your implementation */ }
  public void StepError() { /* your implementation */ }
}

Note that all the methods return void, have only input parameters, and declare no exceptions. By definition, events do not produce any output and throw no checked exceptions so, when an IOM object sends an event, it is not obligated to wait for a response. If your implementation of a method in an event interface throws an unchecked exception, the ORB catches it and ignores it. Furthermore, because no event requires output, you can provide trivial implementations for events that you are not interested in.

Finding a Connection Point

After you have written an event listener using the preceding example as a guide, you then make the listener known to the IOM object using a connection point. A connection point is, in effect, a child component of an IOM object that serves as a conduit for passing events from the IOM object to its listeners. IOM objects that support event interfaces implement an interface called com.sas.iom.SASIOMDefs.ConnectionPointContainer which includes a method called FindConnectionPoint(). To call the FindConnectionPoint() method, you must narrow your object reference to com.sas.iom.SASIOMDefs.ConnectionPointContainer, as discussed in Generic Object References and IOM Objects that Support More Than One Stub.

The FindConnectionPoint() method provides you with a reference to the correct connection point. Because IOM objects can support more than one event interface, you must identify which connection point you want when you call FindConnectionPoint() using the unique interface identifier of the event interface and the com.sas.iom.SASIOMDefs.CP_ID structure. The unique interface identifier for the event interface can be found by calling the id() method on the Helper class of the event interface.

The following example shows you how to get a unique interface identifier and use it to initialize the com.sas.iom.SASIOMDefs.CP_ID structure:

String cpidString = com.sas.iom.SASEvents.ILanguageEventsHelper.id();
int d1 = (int)java.lang.Long.parseLong(cpidString.substring(4,12),16);
short d2 = (short)java.lang.Integer.parseInt(cpidString.substring(13,17),16);
short d3 = (short)java.lang.Integer.parseInt(cpidString.substring(18,22),16);
byte[] d4 = new byte[8];

for (int i=0;i<2;i++)
{
  d4[i] = (byte)java.lang.Short.parseShort(
    cpidString.substring(23+(i*2),25+(i*2)),16);
}

for (int i=0;i<6;i++)
{
  d4[i+2] = (byte)java.lang.Short.parseShort(
    cpidString.substring(28+(i*2),30+(i*2)),16);
}

com.sas.iom.SASIOMDefs.CP_ID cpid=new com.sas.iom.SASIOMDefs.CP_ID(
  d1,d2,d3,d4);

After you have constructed the com.sas.iom.SASIOMDefs.CP_ID structure, you are ready to call FindConnectionPoint() and obtain a reference to the connection point component. Note that FindConnectionPoint() uses an output parameter to return a reference to the connection point, which means that you must use the Holder class com.sas.iom.SASIOMDefs.ConnectionPointHolder. Do not confuse that class with the com.sas.iom.SASIOMDefs.ConnectionPointContainer class.

The following example shows you how to find the connection point for the com.sas.iom.SASEvents.ILanguageEvents event interface:

com.sas.iom.SASIOMDefs.ConnectionPointContainer cpContainer = 
  com.sas.iom.SASIOMDefs.ConnectionPointContainerHelper.narrow(sasLanguage);
com.sas.iom.SASIOMDefs.ConnectionPointHolder cpHolder = 
  new com.sas.iom.SASIOMDefs.ConnectionPointHolder();
cpContainer.FindConnectionPoint(cpid,cpHolder);
com.sas.iom.SASIOMDefs.ConnectionPoint cp = cpHolder.value;

Using a Connection Point

After you have obtained a reference to a connection point, the final step is to make the connection point aware of your event listener. This step is done using the Advise() method. When you are no longer interested in receiving events, call the Unadvise() method.

The following example illustrates the use of a connection point:

org.omg.CORBA.IntHolder handleHolder = new org.omg.CORBA.IntHolder();
cp.Advise(sasLanguageEventsListener,handleHolder);
int handle = handleHolder.value;
/* event listener can now receive events */
cp.Unadvise(handle);