$('a[name]').remove(); $('#ic-homepage__footer').before('

'); $("#tabs").tabs({ selected: 1 }); $("#ic-homepage__ic-tips").append( quickTipHTML() ); unhideOneProductTip(); $("#ic-homepage__product-tips").wrapInner('

'); $("#ic-homepage__feed-tips").wrapInner('

'); });

IBM Tivoli Monitoring > Version 6.3 > User's Guides > Agent Builder User's Guide > Use the Java API to monitor data. IBM Tivoli Monitoring, Version 6.3


Generated sample Java application

A reference that describes the code the Agent Builder generates and the code you must add or replace for the resources you want to monitor.

When you create an agent with one or more Java API data sources, the Agent Builder generates Java application source code. The code is generated in the agent project and follows the structure of your agent. You must add your own Java code to the generated application. Your code collects data for sampled attribute groups, handles events to be posted to event-based attribute groups, reports errors if problems are encountered, and runs tasks. The generated application supplies the agent with data, but it is sample data, to be replaced with data obtained from the resources you want to monitor.

A sample agent is assumed that has the following characteristics:


Class structure

The generated Java application separates, to a great degree, code that interfaces with the agent from code that interfaces with the resources you are monitoring. It contains files that you modify, and files that you do not modify.

The following Java classes are created by the Agent Builder:

MainClass (agent.client package)

The class that you specified on the Global Java API Data Source Information page. This class contains a main method and a method that handles take action requests. This class inherits from the helper class described next. You must modify this class to interface with resources you want to monitor and the actions you want to take.

MainClassBase (agent.client package)

A helper class which initializes the connection to the server, registers attribute groups, and waits for requests from the server. Do not modify this class.

Sampled_Data, Sampled_Subnode, Event_Data, and Event_Subnode classes (agent.client.attributeGroups package)

There is one class for each Java API attribute group which handles data collection requests for the attribute group or generates events for the attribute group. These classes each inherit from one of the helper classes described next. You must modify these classes to gather data from the resources you want to monitor.

Sampled_DataBase, Sampled_SubnodeBase, Event_DataBase, and Event_SubnodeBase classes (agent.client.attributeGroups package)

Helper classes, one for each Java API attribute group, which define the structure of the attributes of the group in an internal class. Do not modify these classes.

ICustomAttributeGroup interface (agent.client.attributeGroups package)

An interface that defines public methods in each attribute group class. Do not modify this interface.

The classes which you can modify are never overwritten by the Agent Builder. The Agent Builder creates them only if they do not exist.

The helper classes and the interface are overwritten each time the Agent Builder is saved. As you modify and save the agent, the helper classes are updated to reflect any structural changes to the Java API attribute groups. The interface and helper classes contain a warning in the header that reminds you not to modify the file.


Initialization and cleanup

The main method in MainClass is called when the agent is started. It creates a MainClass instance and then enters the long-running method to receive and handle agent requests.

Most of the initialization and cleanup code must be added to MainClass. In the constructor, add initialization that is needed to create or access your resources. You might want to open connections to remote resources, create handles, or initialize data structures.

Before the agent terminates, the stopDataCollection method is called. To close connections or cleanup before the Java application ends, add that code to the stopDataCollection method.

If initialization is needed only for a particular attribute group, that initialization can be added to the constructor of the attribute group class. Similarly, if any cleanup is needed only for a particular attribute group, that cleanup code can be added to the stopDataCollection method of the attribute group.

Any code in the Java application can use the logger object to write log entries. (The main helper class creates a protected logger object in its constructor. The attribute group helper objects create a protected reference to that logger in their constructors). The logger object uses the Java trace log utility. Errors and detailed trace information can be obtained from the trace log that is created by the logger. The trace information is important for troubleshooting problems with the provider.

When stopDataCollection is called, if you pass the cleanup work to another thread, wait for that thread to finish before you return from the stopDataCollection method. Otherwise, the cleanup work can be abruptly terminated when the process ends because the main thread completed.

One of the agent configuration settings is for the Java trace level. The following table shows the values that you can set in the JAVA_TRACE_LEVEL configuration property. If the API created the logger for you, the table shows the Level that is used by the logger.


Java trace level options

Configured trace level Java logging trace level Description
Off OFF No logging is done.
Error SEVERE Trace problems that occurred in the Java application.
Warning WARNING Trace errors and potential errors.
Information INFORMATION Trace important information about the Java application.
Minimum Debug FINE Trace high-level details necessary to analyze the behavior of the Java application.
Medium Debug FINER Trace details about the program flow of the Java application.
Maximum Debug FINEST Trace all details about the Java application.
All ALL Trace all messages.

The name of the log file that is created by the Java application in this example is k91_trace0.log. If the agent is a multiple instance agent, the instance name is included in the log file name.

Do not write messages to standard error or to standard out. On Windows systems, these messages are lost. On UNIX and Linux systems, this data is written to a file that does not wrap.


Collect sampled attribute group data

The class for a sampled attribute group (one that collects one or more data rows) contains a collectData method, for example, Sampled_Data.collectData. This method is called whenever data is requested by the agent.

The helper class of the attribute group defines an inner class that is called Attributes. This class has one field for each attribute that is defined in your attribute group. Derived attributes are not included since they are calculated by the agent. The data types of attribute fields are Java equivalents to the Tivoli Monitoring attribute types, as shown in (Table 2).


The data types of attribute fields and their IBM Tivoli Monitoring attribute type equivalents

Tivoli Monitoring type Data type of attribute field
String String
Numeric, 32 bit, no decimal adjustment int
Numeric, 64 bit, no decimal adjustment long
Numeric, non-zero decimal adjustment double
Time stamp Calendar

The collectData method must:

  1. Collect the appropriate data from the resource that is being monitored.

  2. Create an Attributes object.

  3. Add the data to the fields of the Attributes object.

  4. Call the Attributes.setAttributeValues method to copy the data to an internal buffer.

  5. Repeat steps 1 - 4 as necessary for each data row. (You can skip steps 1 - 4 altogether and return no rows. In this case, the Error Code column of the Performance Object Status table has a value of NO_INSTANCES_RETURNED. For more information about error codes, see (Error codes).

  6. Call AgentConnection.sendDatato send the data to the agent, or call sendError to discard data that is copied from calls to setAttributeValuesand send an error code instead.

You must collect the data from your resource (Step 1), replacing the sample data that is used in the generated application.

To populate the Attributes object, you can pass the data in using the Attributes constructor (as is done in the generated application). Alternatively use the zero-argument constructor to create an Attributes object and then assign the fields of the attributes object to the attribute values you collected. Fields have the same name as the attributes, though they start with a lowercase letter.


Collect sampled data for a subnode

If a sampled attribute group is in a subnode, there are presumably multiple resources that you are monitoring (a different one for each subnode). You must determine which resource to collect data from. There must be one or more configuration properties that identify which resource is being monitored.

For this example, it is assumed that one configuration property, K91_INSTANCE_KEY, contains a value that identifies the resource from which data must be collected.

Use the following steps to find the correct resource:

  1. Get the instance ID of all configured subnodes by calling AgentConnection.getConfiguredSubnodeInstanceIDs. Each subnode that is configured has a unique instance ID.

  2. For each instance ID, get the K91_INSTANCE_KEY configuration property by calling AgentConnection.getSubnodeConfigurationProperty.

  3. Find the resource that is represented by the value in K91_INSTANCE_KEY.

These steps might be done in the collectData method before the series of steps that are detailed in ( Collect sampled attribute group data).

Alternatively, you might want to do these steps in the attribute group class constructor and establish a direct mapping from instance ID to resource. An example attribute group class constructor is the Sampled_Subnode constructor. This procedure also gives you the opportunity to create handles or open connections that might be used through the life of the agent. Creating handles or open connections can make access to your resources more efficient.

The generated code creates sample resource objects of type MonitoredEntity in the constructor, and adds them to a configurationLookup map. You must remove the MonitoredEntity inner class, and replace the MonitoredEntity objects with objects that access your own resources. If you choose to do the entire lookup procedure in the collectData method, you can remove the configurationLookup map from the class.

If you choose to use the constructor, to map the subnode instance ID to your resource, the steps in the collectData method are:

  1. Retrieve the instance ID of the subnode from the request parameter, by calling Request.getSubnodeInstanceID.

  2. Retrieve the resource object from the map that is created in the constructor.

  3. Perform the series of steps that are detailed in Collect sampled attribute group data to send data to the agent.

An arbitrary subnode property is chosen in the Agent Builder example, in this case K91_INSTANCE_KEY. If not the correct property, or more than one property is needed to identify the correct resource, you must choose the properties to identify the resource.


Sending events

For attribute groups that generate events, there is no periodic call to a collectDatamethod. Events are sent by your application as your resource posts them.

As an example of producing events, the generated code for an event-based attribute group creates and starts a thread which runs from an internal class named SampleEventClass. The event-based attribute group that is used in the example is the Event_Dataclass. The thread periodically wakes up and sends an event. To periodically poll your resource for events, you can use the structure of the Event_Data class as it was generated:

  1. From the Event_Data constructor, create and start a thread.

  2. In the run method of the thread, loop until the agent terminates.

  3. Sleep for a time before you check for events. You might want to change the polling interval of 5000 milliseconds to a number that makes sense for your agent.

  4. Determine whether one or more events occurred. The generated application does not check, but always posts a single event.

  5. For each event that must be posted, get the event data to be posted.

  6. Create and populate the Attributes object (like the collectData method did for a sampled attribute group).

  7. Call the Attributes.sendEventData method. Events consist of a single row, so only a single event can be sent at a time.

Alternatively, if you are working with a Java API that reports events from its own thread, you can initialize that thread in the Event_Data constructor. You can also register your own event-handling object with the event-handling mechanism of your resource. In your event handler, use the following steps:

  1. Get the event data to be posted.

  2. Create and populate the Attributes object.

  3. Call the Attributes.sendEventData method.

In this case, you do not have to create your own thread in the Event_Data class nor would you need the SampleEventClass class.


Sending events in a subnode

When an event is detected for a subnode attribute group, the Java application must post the event to the correct subnode.

For this example, it is assumed that one configuration property, K91_INSTANCE_KEY, contains a value that identifies an instance of a resource which can produce events. It is also assumed that the value of the K91_INSTANCE_KEY property is retrieved along with data to be posted in the event. To do retrieve the property and data, the Java application does the following steps:

  1. Gets the event data to be posted, along with the “instance key”.

  2. Creates and populates the Attributes object.

  3. Gets a list of all configured subnode instance IDs by calling AgentConnection.getConfiguredSubnodeInstanceIDs.

  4. For each subnode instance, fetches the value of K91_INSTANCE_KEY by calling AgentConnection.getSubnodeConfigurationProperty.

  5. When the value of K91_INSTANCE_KEY is found which matches the value that is obtained with the event data, remembers the corresponding subnode instance ID.

  6. Calls Attributes.sendSubnodeEventData, passing the remembered subnode instance ID.

The generated application does not do the lookup described in steps 4 and 5, but instead posts an event to the attribute group of every subnode. This behavior is probably not the correct one for a production agent.


Take action commands

Take action commands are defined either in the Tivoli Enterprise Portal or using the tacmd createaction command. The actions can be imported into the agent's Agent Builder project so that they are created when the agent is installed. For more information about importing take action commands, see (Import application support files).

The generated Java application registers for any actions that begin with the product code of the agent, for example, K91Refresh. This registration is done in the main helper class (MainClassBase) from the registerActionPrefix method. To register other prefixes, or not register for actions at all, override the registerActionPrefix in (MainClassBase).

When the agent wants to run an action which starts with a prefix that your agent registered, the MainClass.takeAction method is called. You add code to call Request.getAction(), do the appropriate action, and then call AgentConnection.sendActionReturnCode to send the return code from your action. A return code of 0 means the action is successful, any other return code means the action failed.


Handling exceptions

The collectData and takeAction methods can throw any Java exception, so you can allow your collection code to throw exceptions without catching them. The handleException method (for collectData) or handleActionExceptionmethod (for takeAction) is called when the helper class gets the exception.

For collectData exceptions, you must call AgentConnection.sendError when an exception occurs or when there is a problem in data collection. The generated application passes an error code of GENERAL_ERROR. However, you must replace this error code with one defined by your agent that best describes the problem that was encountered. For more information about adding error codes, see Step (13).

For takeAction exceptions, you must call AgentConnection.sendActionReturnCode with a non-zero return code.

Some of the AgentConnection methods throw exceptions that are derived from com.ibm.tivoli.monitoring.agentFactory.customProvider.CpciException. The handleException method is not called if a CpciException is thrown during the collecting of data as the helper class handles the exception.

If you choose to catch your exceptions inside the collectData method rather than using the handleException method, ensure any CpciException is rethrown. You ensure CpciException is rethrown so it can be handled by the base class.


Error codes

A typical response to an exception or other resource error is to send an error code to the agent by calling the AgentConnection.sendError method. An error for an event-based attribute group can be sent at any time. An error for a sampled attribute group can be sent only in response to a collect data request, and in place of a sendData call.

If you send an error to the agent, the following happens:

  1. An error message is logged in the agent trace log. This error message includes the error code and the message that is defined for that error code.

  2. There is a Performance Object Status query that can be viewed to obtain status information about your attribute groups. The Error Code column is set to the Error Code type defined for the error you sent. The error status clears after data is successfully received by the agent for the attribute group. If you reply to a collect data request with a sendData call but you included no data rows, you get NO_INSTANCES_RETURNED in the Error Code column.

The following table describes some error codes that are internal to the agent that you can expect to see in certain situations:


Internal error codes for the agent

Error Code Description
NO_ERROR There are no problems with the attribute group currently.
NO_INSTANCES_RETURNED The Java application responded to a data collection request but provided no data. Not providing data is not an error. It generally indicates that there are no instances of the resource that are being monitored by the attribute group.
OBJECT_NOT_FOUND The agent tried to collect data for an attribute group that is not registered through the client API. This error can mean that the application failed to start or did not initiate the attribute group registration when the agent tried to collect data.
OBJECT_CURRENTLY_UNAVAILABLE The application sent the agent an error code that is not defined in the global list of error codes.
GENERAL_ERROR A problem occurred collecting data from the application, usually because the application did not reply to the request within the timeout interval. See the agent trace log for more details.

The application can also specify GENERAL_ERROR as an error code, but it is better if a more detailed error code is defined.


Changes to the agent

Certain changes to the agent require you to make corresponding changes to the Java application. If the structural changes are complex, you can delete any or all of the Java source files before you save the agent. You can also delete the files if you want to start over without the customizations you made,

The following table describes required modifications to the Java application source files after certain changes are made in the Agent Builder when the agent is saved.


Changes to an agent that require modifications to the Java source

Agent change What the Agent Builder does Manual changes that are needed in the Java source
Change of the main class package name

  • Generates all classes in the new package structure.

  • Removes all helper classes from the old package.

  • Port main and attribute group class content from the classes in the old package to the classes in the new package.

  • Remove the classes from the old package after migration is complete.

Change of the main class name

  • Creates new main classes.

  • Removes old main helper class.

  • Port main class content to the new class.

  • Update references to the class name from the attribute group classes.

Addition of a Java API attribute group

  • Creates classes for the new attribute group.

  • Adds registration for the new attribute group in the main helper class.

Overwrite sample code with custom logic in the attribute group class.
Removal of a Java API attribute group Removes registration from the main helper class.

  • Remove the attribute group class or port customized logic to some other class.

  • Remove the attribute group helper class.

Renaming of a Java API attribute group

  • Creates classes for the new name of the attribute group.

  • Updates registration for the renamed attribute group in the main helper class.

  • Port customized logic in the attribute group class with the old name to the attribute group class with the new name.

  • Remove the attribute group class with the old name.

  • Remove the attribute group helper class with the old name.

Addition of an attribute to a Java API attribute group Updates the Attributes inner class in the attribute group helper class. Collect data for the new attribute in the attribute group class.
Removal of an attribute from a Java API attribute group Updates the Attributes class in the attribute group helper class. Remove data collection for the former attribute in the attribute group class.
Renaming of an attribute in a Java API attribute group Updates the attribute name in the Attributes class in the attribute group helper class. Update any references to the attribute name in the Attributes class (often there are no references because the Attributes constructor, with positional arguments, is used).
Reordering of attributes in a Java API attribute group Updates the attribute order in the Attributes class in the attribute group helper class. Update the argument order in any calls to the Attributes constructor.

Some of the changes that are mentioned in the previous table can be streamlined if you use the Eclipse Refactor - Rename action. Use this action on all the affected names (including helper class names) before you save the changed agent.


Use of the Java API

The Java API is used throughout the generated Java application to communicate with the agent. Often your only direct interaction with the Java API is to modify a parameter of an existing method call. For example, changing a posted error code from GENERAL_ERROR to an error code defined in your agent.

To do more extensive coding with the Java API, you can view Javadoc from the Eclipse text editor. You can view Javadoc while you edit the Java code by doing the following steps:

  1. Highlight a package, class, or method name from the API.

  2. Press F1 to open the Eclipse Help view.

  3. Select the Javadoc link.

You can also see a brief description from the Javadoc by hovering over a class or method name. Javadoc for the API can also be found on the Tivoli Monitoring and OMEGAMON XE Information Center, see Javadoc.

The classes for the Java API are in cpci.jar. The cpci.jar file is automatically added to the Java Build Path of the project when an agent which contains a Java API attribute group is created. The file is also added when an agent that contains a Java API attribute group is imported. The file is also added when a Java API attribute group is added to an existing agent. Thecpci.jar is also automatically packaged with each agent that contains a Java API attribute group and added to the CLASSPATH of the Java application.


Parent topic:

Use the Java API to monitor data.

+

Search Tips   |   Advanced Search