An API is defined by a module developer and contains a variety of components designed to accomplish a task. These components are:
Enums
Values
Structs
Fields
Interfaces
Properties
Methods
Events
These components are all defined in an ADR Interface Description Language document. The radadrgen utility is used to process the document to generate language specific components which facilitate client/server interactions within RAD. More details in the role of ADR and rad can be found in Abstract Data Representation. Brief descriptions of each component follows.
Enumerations are primarily used to offer a restricted range of choices for a property, an interface method parameter, result, or error.
To access an enumerated type, simply import the generated class and interact with the enumeration.
Example 3-24 Using Enumerationsimport com.oracle.solaris.rad.zonemgr.ErrorCode; System.out.println(ErrorCode.NONE); System.out.println(ErrorCode.COMMAND_ERROR);
Structs are used to define new types and are composed from existing built-in types and other user defined types. In essence, they are simple forms of interfaces. They do not have methods or events and are not present in the RAD namespace.
The zonemgr module defines a Property struct which represents an individual Zone configuration property. The structure has the following members name, type, value, listValue, and complexValue. Like enumerations, structures can be interacted with directly once the binding is imported.
Example 3-25 Using Structsimport com.oracle.solaris.rad.zonemgr.Property; Property prop = new Property(); prop.setName("my name"); prop.setValue("a value"); System.out.println(prop.getName()); System.out.println(prop.getValue());
Interfaces (also known as objects) are the entities which populate the RAD namespace. They must have a "name". An interface is composed of Events, Properties and Methods.
See the Rad Namespace section.
Once we have an object reference we can use this to interact with RAD in a very straightforward fashion. All attributes and methods defined in the IDL are accessible directly as attributes and methods of the Java objects which are returned by getObject(). Attributes are accessed using automatically generated getters/setters. For example, if the property is name, then you would use getname()/ setname(<value>). Here is an example which gets a reference to a zone and then boots the zone.
Example 3-26 Invoking a Remote Methodimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.ADRGlobPattern; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.Zone; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); String keys[] = { "name" }; String values[] = { "test-0" }; ADRGlobPattern pat = new ADRGlobPattern(keys, values); for (ADRName name: con.listObjects(new Zone(), pat)) { Zone z = (Zone) con.getObject(name); z.boot(null); }
In the above example we have connected to our RAD instance, created a search for a specific object, retrieved a reference to the object and invoked a remote method on it.
Accessing a remote property is just as simple as using a remote method.
Example 3-27 Accessing a Remote Propertyimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.ADRGlobPattern; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.*; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); String keys[] = { "name" }; String values[] = { "test-0" }; ADRGlobPattern pat = new ADRGlobPattern(keys, values); for (ADRName name: con.listObjects(new Zone(), pat)) { Zone z = (Zone) con.getObject(name); Resource filter = new Resource("global", null, null); List<Property> props = z.getResourceProperties(filter, null); System.out.println("Properties:"); for (Property prop: props) { System.out.printf("\t%s = %s\n",prop.getName(), prop.getValue()); } }
In this example, we accessed the list of Zone global resource properties and printed out the name and value of every Property.
In this next example we are going to look at events. The ZoneManager instance defines a "stateChange" event which clients can subscribe to for information about changes in the runtime state of a zone.
Example 3-28 Subscribing and Handling Eventsimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.RadEvent; import com.oracle.solaris.rad.client.RadEventHandler; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.*; ZoneManager zmgr = con.getObject(new ZoneManager()); con.subscribe(zmgr, "statechange", new StateChangeHandler()); Thread.currentThread().sleep(100000000); class StateChangeHandler extends RadEventHandler { public void handleEvent(RadEvent event, Object payload) { StateChange obj = (StateChange) payload; System.out.printf("Event: %s", event.toString()); System.out.printf("\tcode: %s\n", obj.getZone()); System.out.printf("\told: %s\n", obj.getOldstate()); System.out.printf("\tnew: %s\n", obj.getNewstate()); } }
To handle an event, implement the RadEventInterface. The com.oracle.solaris.rad.client package provides a default implementation (RadEventHandler) with limited functionality. This class may be extended to provide additional event handling logic as in example above.
In this simple example we subscribe to the single event and pass in a handler and a reference to our ZoneManager object. The handler will be invoked asynchronously by the framework with the various event details and the supplied user data.
Finally, a quick look at error handling when manipulating remote references. Python provides a rich exception handling mechanism and RAD errors are propagated using this mechanism. There are a variety of errors which can be delivered by RAD, but the main one which requires handling is RadObjectException. The following snippet, shows how it can be used:
Example 3-29 Handling RAD Errors<imports..> Connection con = Connection.connectUnix(); for (ADRName name: con.listObjects(new Zone())) { Zone zone = con.getObject(name); try { zone.boot(null); }catch (RadObjectException oe) { Result res = (Result) oe.getPayload(); System.out.println(res.getCode()); if (res.getStdout() != null) System.out.println(res.getStdout()); if (res.getStderr() != null) System.out.println(res.getStderr()); } }