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.
- Product code:
K91 - Java API Main class: agent.client.MainClass
- Agent data source structure as shown in (Figure 1):
Figure 1. Sample agent structure 
- Some subnode configuration property:
K91_INSTANCE_KEY
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.
- 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. If you want 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.
JAVA_TRACE_LEVEL configuration
property. If the API created the logger for you, the table shows the
Level that is used by the logger.
| 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. |
k91_trace0.log.
If the agent is a multiple instance agent, the instance name is included
in the log file name. Collecting 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.
| 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 |
- Collect the appropriate data from the resource that is being monitored.
- Create an Attributes object.
- Add the data to the fields of the Attributes object.
- Call the Attributes.setAttributeValues method to copy the data to an internal buffer.
- 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).
- 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.
Collecting 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.
- Get the instance ID of all configured subnodes by calling AgentConnection.getConfiguredSubnodeInstanceIDs. Each subnode that is configured has a unique instance ID.
- For each instance ID, get the
K91_INSTANCE_KEYconfiguration property by calling AgentConnection.getSubnodeConfigurationProperty. - Find the resource that is represented by the value in
K91_INSTANCE_KEY.
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.
- Retrieve the instance ID of the subnode from the request parameter, by calling Request.getSubnodeInstanceID.
- Retrieve the resource object from the map that is created in the constructor.
- Perform the series of steps that are detailed in Collecting 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.
- From the Event_Data constructor, create and start a thread.
- In the run method of the thread, loop until the agent terminates.
- 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.
- Determine whether one or more events occurred. The generated application does not check, but always posts a single event.
- For each event that must be posted, get the event data to be posted.
- Create and populate the Attributes object (like the collectData method did for a sampled attribute group).
- Call the Attributes.sendEventData method. Events consist of a single row, so only a single event can be sent at a time.
- Get the event data to be posted.
- Create and populate the Attributes object.
- Call the Attributes.sendEventData method.
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.
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: - Gets the event data to be posted, along with the “instance key”.
- Creates and populates the Attributes object.
- Gets a list of all configured subnode instance IDs by calling AgentConnection.getConfiguredSubnodeInstanceIDs.
- For each subnode instance, fetches the value of
K91_INSTANCE_KEYby calling AgentConnection.getSubnodeConfigurationProperty. - When the value of
K91_INSTANCE_KEYis found which matches the value that is obtained with the event data, remembers the corresponding subnode instance ID. - Calls Attributes.sendSubnodeEventData, passing the remembered subnode instance ID.
Take action commands
Take
action commands are defined either in the Tivoli Enterprise Portal or by 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 (Importing 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. If you want
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.
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.
- 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.
- 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_RETURNEDin the Error Code column.
| 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 |
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,
| Agent change | What Agent Builder does | Manual changes that are needed in the Java source |
|---|---|---|
| Change of the main class package name |
|
|
| Change of the main class name |
|
|
| Addition of a Java API attribute group |
|
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. |
|
| Renaming of a Java API attribute group |
|
|
| 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. |
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.
- Highlight a package, class, or method name from the API.
- Press F1 to open the Eclipse Help view.
- Select the Javadoc link.
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.