Navigating integration node and integration node resources in a custom integration application

Explore the status and attributes of the integration node that your custom integration application is connected to, and discover information about its resources.

Before you begin

You must have completed Connecting to an integration node from a custom integration application.

About this task

Each resource that the integration node can control is represented as a single object in the IBM Integration API. A custom integration application can request status and other information about the following objects:
  • Integration nodes
  • Integration servers
  • Deployed message flows
  • Administration log
  • Activity Logs
  • data capture stores

The IBM Integration API also handles deployed message sets; these resources are handled as attributes of deployed integration servers.

Collectively known as administered objects, these objects provide most of the interface to the integration node, and are therefore fundamental to an understanding of the IBM Integration API.

Each administered object is an instance of a Java™ class that describes the underlying type of object in the integration node. The main Java classes are shown in the following table.
Java class Class function
BrokerProxy Describes integration nodes.
ExecutionGroupProxy Describes integration servers.
MessageFlowProxy Describes message flows that have already been deployed to integration servers; does not describe message flows in the Integration Development perspective of the IBM Integration Toolkit.
LogProxy Represents the log of recent administrative activity on the integration node, for all users.
ActivityLogProxy Represents a log of recent message flow and resource activity.
DataCaptureProxy Represents data that is held in an integration node data store. Retrieved data is contained in DataCaptureEntry objects.
Each administered object describes a single object that can be controlled by the integration node. For example, every integration server within an integration node has one ExecutionGroupProxy instance that represents it within the application.

The LogProxy object includes messages, created as LogEntry objects, that record recent changes made to the administered objects. These messages include the following information:

  • Administration requests; for example, a request to deploy a BAR file
  • Results of administration requests
  • Changes that have been made to objects; for example, a change to a property value through an administration task
  • Changes that have been made to objects as a result of starting an integration node at a new fix pack level or version.

The ActivityLogProxy object includes messages, created as ActivityLogEntry objects, that record recent high-level activities involving message flows and their interactions with external resources. For more information about these messages, see Using Activity Logs. Activity Logs are generated for message flows and for specific resource types.

You can retrieve an ActivityLogProxy object for a message flow from a MessageFlowProxy object. To get an ActivityLogProxy object for a resource type, use the ResourceManagerProxy object. Invoke the method getActivityLog() on the MessageFlowProxy object or the ResourceManagerProxy object. For further information, see Viewing Activity Logs by using a custom integration application.

You can use the AdminQueueProxy object to examine what items of work are in progress or are waiting for processing by the integration node. The following code shows how you can access the queue:

BrokerConnectionParameters bcp =
		new IntegrationNodeConnectionParameters("localhost", 4414);
BrokerProxy b = BrokerProxy.getInstance(bcp);
AdminQueueProxy l = b.getAdministrationQueue();

A set of public methods is available for each administered object, which applications can use to inquire and manipulate properties of the underlying integration node to which the instance refers. To access an administered object through its API, your application must first request a handle to that object from the object that logically owns it.

For example, because integration node logically own integration servers, to gain a handle to integration server EG1 running on integration node B1, the application must ask the BrokerProxy object represented by B1 for a handle to the ExecutionGroupProxy object represented by EG1.

On a BrokerProxy object that refers to integration node B1, the application can call methods that cause the integration node to reveal its run-state, or cause it to start all its message flows. You can write applications to track the changes that are made to the integration node objects by reading the messages maintained as LogEntry objects.

In the following example, a handle is requested to the BrokerProxy object. The BrokerProxy is logically the root of the administered object tree, therefore your application can access all other objects in the integration node directly, or indirectly.

The integration node directly owns the integration servers, therefore applications can call a method on the BrokerProxy object to gain a handle to the ExecutionGroupProxy objects. Similarly, the integration server logically contains the set of all message flows, therefore the application can call methods on the ExecutionGroupProxy object to access the MessageFlowProxy objects.

The hierarchy of these access relationships is shown in the following diagram.
The diagram is described in the surrounding text.
Each object with an asterisk after its name inherits from the DeployedObjectGroupProxy class, and therefore has further child objects as shown in the following diagram.
The diagram is described in the surrounding text.

The following application traverses the administered object hierarchy to discover the run-state of a deployed message flow. The application assumes that message flow MF1 is deployed to EG1 on integration node B1; you can substitute these values in the code for other values that are valid in the integration node.

import com.ibm.broker.config.proxy.*;

public class GetMessageFlowRunState {

  public static void main(String[] args) {
        
    BrokerProxy b = null;
    try {
      BrokerConnectionParameters bcp =
         new IntegrationNodeConnectionParameters(
           "localhost",
           4414);
      b = BrokerProxy.getInstance(bcp);   
    } catch (ConfigManagerProxyException cmpex) {
      System.out.println("Error connecting: "+cmpex);
    }
        
    if (b != null) {
      System.out.println("Connected to integration node!");
      displayMessageFlowRunState(b, "EG1", "MF1");
      b.disconnect();
    }      
  }

  private static void displayMessageFlowRunState(
                                 BrokerProxy b,
                                 String egName,
                                 String flowName) {
    try {
      ExecutionGroupProxy eg =
        b.getExecutionGroupByName(egName);

      if (eg != null) {
        MessageFlowProxy mf = 
          eg.getMessageFlowByName(flowName);

        if (mf != null) {
          boolean isRunning = mf.isRunning();
          System.out.print("Flow "+flowName+" on " + 
            egName+" on "+b.getName()+" is ");

          if (isRunning) {
            System.out.println("running");
          } else {
            System.out.println("stopped");
          }
        } else {
          System.err.println("No such flow "+flowName);
        }
      } else {
        System.err.println("No such exegrp "+egName+"!");
      }
        
    } catch(ConfigManagerProxyPropertyNotInitializedException
                                                      ex) {
      System.err.println("Comms problem! "+ex);
    }
  }
}
The method displayMessageFlowRunState() does most of the work. This method takes the valid BrokerProxy handle gained previously, and discovers the run-state of the message flow in the following way:
  1. The BrokerProxy instance is used to gain a handle to the ExecutionGroupProxy object with the name described by the string egName
  2. If a valid integration server is returned, the ExecutionGroupProxy instance is used to gain a handle to the MessageFlowProxy object with the name described by the string flowName.
  3. If a valid message flow is returned, the run-state of the MessageFlowProxy object is queried, and the result is displayed.

The application does not have to know the names of objects that it can manipulate. Each administered object contains methods to return sets of objects that it logically owns. The following example demonstrates this technique by looking up the names of all integration servers within the integration node.

import java.util.Enumeration;
import com.ibm.broker.config.proxy.*;

public class DisplayExecutionGroupNames {

  public static void main(String[] args) {
        
    BrokerProxy b = null;
    try {
      BrokerConnectionParameters bcp =
         new IntegrationNodeConnectionParameters(
           "localhost",
           4414);
      b = BrokerProxy.getInstance(bcp);   
    } catch (ConfigManagerProxyException cmpex) {
      System.out.println("Error connecting: "+cmpex);
    }
        
    if (b != null) {
      System.out.println("Connected to integration node!");
      displayExecutionGroupNames(b);
      b.disconnect();
    }
  }

  private static void displayExecutionGroupNames(BrokerProxy b)
  {
    try {
      Enumeration<ExecutionGroupProxy> allEGs = b.getExecutionGroups(null);
        
      while (allEGs.hasMoreElements()) {
        ExecutionGroupProxy thisEG =
          allEGs.nextElement();
        System.out.println("Found EG: "+thisEG.getName());
      }
    } catch(ConfigManagerProxyPropertyNotInitializedException
                                                      ex) {
        System.err.println("Comms problem! "+ex);
    }
  }
}

The key method is BrokerProxy.getExecutionGroups(Properties). When supplied with a null argument, this method returns an enumeration of all the ExecutionGroupProxy objects in the integration node. The application uses this method to look at each ExecutionGroupProxy in turn, and display its name.

The Properties argument of the method BrokerProxy.getExecutionGroups(Properties) can be used to exactly specify the characteristics of the integration servers that are sought. The application can use this argument for nearly all the methods that return administered objects, and is a powerful way of filtering those objects with which the application needs to work.

Examples of the characteristics that can be used to filter object lookups are the run-state and short description, as well as more obvious properties such as the name and UUID. To write logic to achieve filtered lookups, you must understand how each administered object stores its information.

The properties of each administered object are stored locally inside the object by using a hash table, where each property is represented as a {key, value} tuple. Each key is the name of an attribute (for example, name) and each value is the value (for example, INODE1).

Each key name must be expressed by using a constant from the AttributeConstants class (com.ibm.broker.config.proxy). A complete set of keys and possible values for each administered object is described in the Java documentation for the AttributesConstant class, or by using the Show raw property table for this object function in the IBM Integration API Exerciser sample application. The latter displays the complete list of {key, value} pairs for each administered object.

The Properties argument that is supplied to the lookup methods is a set of those {key, value} pairs that must exist in each administered object in the returned enumeration. Consider the following code fragment:

Properties p = new Properties();
        
p.setProperty(AttributeConstants.OBJECT_RUNSTATE_PROPERTY,
              AttributeConstants.OBJECT_RUNSTATE_RUNNING);

Enumeration<MessageFlowProxy> mf = executionGroup.getMessageFlows(p);

Providing that the variable executionGroup is a valid ExecutionGroupProxy object, the returned enumeration contains only active message flows (that is, OBJECT_RUN_STATE_PROPERTY equal to OBJECT_RUNSTATE_RUNNING).

When property filtering is applied to a method that returns a single administered object rather than an enumeration of objects, only the first result is returned (which is non-deterministic if more than one match applies). Therefore the following code:
Properties p = new Properties();
p.setProperty(AttributeConstants.NAME_PROPERTY,
              "EG1");
ExecutionGroupProxy eg1 = brokerProxy.getExecutionGroup(p);
is an alternative to the following statement:
ExecutionGroupProxy eg1 = brokerProxy.getTopicByName("EG1");

If multiple {key, value} pairs are added to a property filter, all properties must be present in the child object for an object to match. If you want a method to perform a logical OR, or a logical NOT, on a filter, you must write specific application code for this purpose.

When AdministeredObjects are first instantiated in an application, the IBM Integration API asks the integration node for the current set of properties for that object. This action happens asynchronously, therefore the first time a property is requested, the IBM Integration API might pause while it waits for the information to be supplied by the integration node. If the information does not arrive within a certain time (for example, if the integration node is not running), a ConfigManagerProxyPropertyNotInitializedException is thrown. Your application can control the maximum time that the IBM Integration API waits by using the BrokerProxy.setRetryCharacteristics() method.