Java Dynamic Management Kit 4.1 Tutorial

The Synchronous Manager Example

The synchronous SNMP manager is the simplest to program: the manager sends a request to an agent (peer) and waits for the answer. During the wait, the manager is blocked until either a response is received or the timeout period expires.

The SNMP manager API allows two ways of referring to variables when issuing requests:

Referring directly to OIDs requires no setup but makes code less flexible. The advantages of using variable names are simplified coding and the independence of manager code when custom MIBs are modified. The SNMP manager API supports variable names by storing a description of the MIB it will access in the static SnmpOid object.

In order to refer to variable names, the manager needs to initialize this description with an OID table object. The OID table is instantiated from the SnmpOidTableSupport class generated by the mibgen tool when "compiling" the MIB. Since this support class is regenerated whenever the MIB is recompiled, the new MIB definition will be automatically loaded into the manager when it is launched (see the code example below).

The SNMP manager API specifies the SnmpPeer object for describing an agent, and the SnmpParameters object for describing its read-write communities and its protocol version (SNMPv1 or SNMPv2). The SnmpSession is an object for sending requests and we can associate a default peer to it. The session instance has an SnmpOptions field which we can use to set multiplexing and error fixing behavior.


Note -

The objects specified by the SNMP manager API are not MBeans and cannot be registered in an MBean server to create a manager that could be controlled remotely. However, you could write an MBean that uses these classes to retrieve and expose information from SNMP agents.


A manager can contain any number of peers, one for each agent it wishes to access, and any number of sessions, one for each type of behavior it wishes to implement. Once the peers and the sessions are initialized, the manager can build lists of variables and send session requests to operate on them. The session returns a request object, and the manager calls its waitForCompletion method with the desired timeout delay.

Finally, the manager analyzes the result of the request, first to see if there were any errors, then to extract the data returned by the request.

Here is the code of the main method of the SyncManager application. It applies all of the above steps to execute a very simple management operation.


Example 13-1 The SyncManager Example

// read the command line parameters
String host = argv[0];
String port = argv[1];

// Specify the OidTable containing all the MIB II knowledge
// Use the OidTable generated by mibgen when compiling MIB II
//
SnmpOidTableSupport oidTable = new RFC1213_MIBOidTable();
SnmpOid.setSnmpOidTable(oidTable);
       
SnmpPeer agent = new SnmpPeer(host, Integer.parseInt(port));
     
// When creating the parameter object, you can specify the
// read and write community to be used when querying the agent.
SnmpParameters params = new SnmpParameters("public", "private");
agent.setSnmpParam(params);

SnmpSession session = new SnmpSession("SyncManager session");

// When invoking a service provided by the SnmpSession, it
// will use the default peer if none is specified explicitly
session.setDefaultPeer(agent);

// Create a listener and dispatcher for SNMP traps:
// SnmpEventReportDispatcher will run as a thread and
// listens for traps in UDP port = agent port + 1
SnmpEventReportDispatcher trapAgent =
    new SnmpEventReportDispatcher(Integer.parseInt(port)+1);
// TrapListenerImpl will receive a callback
// when a valid trap PDU is received.
trapAgent.addTrapListener(new TrapListenerImpl()); 
new Thread(trapAgent).start();

// Build the list of variables you want to query.
// For debugging, you can associate a name to your list.
SnmpVarbindList list= new SnmpVarbindList(
    "SyncManager varbind list");
     
// We want to read the "sysDescr" variable.
list.addVariable("sysDescr.0");
    
// Make the SNMP get request and wait for the result.
SnmpRequest request = session.snmpGet(null, list);
boolean completed = request.waitForCompletion(10000);

// Check for a timeout of the request.
if (completed == false) {
    java.lang.System.out.println(
        "Request timed out. Check reachability of agent");
    java.lang.System.exit(0);
}

// Check if the response contains an error.
int errorStatus = request.getErrorStatus();
if (errorStatus != SnmpDefinitions.snmpRspNoError) {
    java.lang.System.out.println("Error status = " + 
        SnmpRequest.snmpErrorToString(errorStatus));
    java.lang.System.out.println("Error index = " +
        request.getErrorIndex());
    java.lang.System.exit(0);
}

// Now we can extract the content of the result.
SnmpVarbindList result = request.getResponseVbList();
java.lang.System.out.println("Result: \n" + result);

[...] // Wait for user to type enter. Traps will be handled.

// End the session properly and we're done
session.destroySession();
java.lang.System.exit(0);

In this SNMP manager application, we demonstrate how to implement and enable a trap listener for the traps sent by the agent. First we need to instantiate an SnmpEventReportDispatcher object. Then we add our listener implementation through its addTrapListener method, and finally we start its thread. Trap listeners can be implemented in any manager using the SNMP manager API, not only synchronous managers.

SNMP Trap Handler

A trap handler for the SNMP manager is an object that implements the SnmpTrapListener interface in the javax.management.snmp.manager package. When this object is bound as a listener of an SnmpEventReportDispatcher object, its methods will be called to handle trap PDUs.

A trap listener is not a notification listener because the dispatcher is not a notification broadcaster. The listener has callback methods that the work in the same manner, but they are given objects that represent traps, not instances of the Notification class.

The interface defines two methods, one for processing SNMPv1 traps and the other for SNMPv2 traps. Trap PDU packets have already been decoded by the dispatcher, and these methods handle an object representation of the trap: SnmpPduTrap objects for v1 and SnmpPduRequest objects for v2. In our implementation, we are only interested in v1 traps, and we just print out the trap information fields.


Example 13-2 The SnmpTrapListener Implementation

public class TrapListenerImpl implements SnmpTrapListener {

    public void processSnmpTrapV1(SnmpPduTrap trap) {
        java.lang.System.out.println(
            "NOTE: TrapListenerImpl received trap :");
        java.lang.System.out.println(
            "\tGeneric " + trap.genericTrap);
        java.lang.System.out.println(
            "\tSpecific " + trap.specificTrap);
        java.lang.System.out.println(
            "\tTimeStamp " + trap.timeStamp);
        java.lang.System.out.println(
            "\tAgent address " + trap.agentAddr.stringValue());
    }

    public void processSnmpTrapV2(SnmpPduRequest trap) {
        java.lang.System.out.println("NOTE: Trap V2 ignored");
    }
}

Running the SyncManager Example

In the examplesDir/Snmp/Manager directory, we first need to generate the OID table description of MIB-II that our manager will access. Then we compile the example classes. To set up your environment, see "Directories and Classpath" in the preface.


$ mibgen -mo mib_II.txt
[output omitted]
$ javac -classpath classpath -d . *.java

Make sure that no other agent is running on port 8085, and launch the simple SNMP agent in examplesDir/Snmp/Agent. See "MIB Development Process" if you have not already built and run this example.

Here we give commands for launching the applications from different Unix terminal windows running the Korn shell. In the first window, enter the following commands:


$ cd examplesDir/Snmp/Agent
$ java -classpath classpath Agent nbTraps

If you will also be running the asynchronous manager example with this agent, omit the nbTraps parameter. The agent will then send traps continuously and they can be seen in both managers. Otherwise, specify the number of traps to be sent to the manager. Wait until the manager is started to send the traps.

Now we can launch the manager application in another window to connect to this agent. If you wish to run the manager on a different host, replace localhost with the name of the machine where you launched the agent.


$ cd examplesDir/Snmp/Manager
$ java -classpath classpath SyncManager localhost 8085
SyncManager::main: Send get request to SNMP agent on localhost at port 8085
Result: 
[Object ID : 1.3.6.1.2.1.1.1.0  (Syntax : String)
Value : SunOS sparc 5.7]

Here we see the output of the SNMP request, it is the value of the sysDescr variable on the agent.

Now press <Enter> in the agent's window: you should see the manager receiving the traps it sends. Leave the agent running if you are going on to the next example, otherwise remember to stop it by typing <Control-C>.