Java Dynamic Management Kit 5.1 Tutorial

13.3.2 RelationSupport Class

The external class representation of a relation instance must implement the Relation interface so that it can be handled by the relation service. The RelationSupport class is the implementation provided which is also used internally by the service.

The methods of the relation interface expose all of the information needed to operate on a relation instance: the getters and setters for roles and the defining relation type. Because the relation support class must represent any possible relation type, it has a constructor that takes a relation type and a role list, and it uses a generic mechanism internally to represent any roles.

You could implement a simpler relation class that implements a specific relation type, in which case it would know and initialize its own roles. The class could also interact with the relation service to create its specific relation type before adding itself as a relation.

However, the simplest way to define a relation object is to extend the RelationSupport class and provide any additional functionality you require. In doing so, you can rely on the relation support class's own methods for getting and setting roles, thereby taking advantage of their built-in consistency mechanisms.


Example 13–8 Extending the RelationSupport Class

import javax.management.ObjectName;
import javax.management.relation.*;

public class SimpleRelation extends RelationSupport
    implements SimpleRelationMBean {

    // Constructor
    public SimpleRelation(String theRelId,
                          ObjectName theRelServiceName,
                          String theRelTypeName,
                          RoleList theRoleList)
        throws InvalidRoleValueException,
               IllegalArgumentException {

        super(theRelId, theRelServiceName, theRelTypeName, theRoleList);
    }

    [...] // Implementation of the SimpleRelationMBean interface
}

Our MBean's SimpleRelationMBean interface extends the RelationSupportMBean in order to expose its operations for management. In order to represent a relation, the class must be an MBean registered in the MBean server. This allows the relation service to rely on unregistration notifications in order to find out if the object name is no longer valid.

When instantiating our SimpleRelation MBean, we use the relation type defined in Example 13–3. We also reuse the role list from Example 13–5 that contains a single MBean in each of two roles. Before adding the relation to the relation service, we must create it as an MBean in the MBean server. We then call the addRelation operation of the relation service with our relation's object name.


Example 13–9 Creating an External Relation MBean

// Using relTypeName="myRelationType"
// and roleList1={container,contained}

String relMBeanClassName = "SimpleRelation";
String relId2 = relTypeName + "_relMBean_2";
ObjectName relMBeanObjName1 = createMBeanName(relMBeanClassName, 2);
createRelationMBean(relMBeanObjName1,
                    relMBeanClassName,
                    relId2,
                    relTypeName,
                    roleList1,
                    relServObjName);
try {
    Object[] params1 = new Object[4];
    params1[0] = theRelId2;
    params1[1] = theRelServObjName;
    params1[2] = theRelTypeName;
    params1[3] = roleList1;
    String[] signature1 = new String[4];
    signature1[0] = "java.lang.String";
    signature1[1] = "javax.management.ObjectName";
    signature1[2] = "java.lang.String";
    signature1[3] = "javax.management.relation.RoleList";
    server.createMBean(theRelMBeanClassName, theRelMBeanObjName,
                       params1, signature1);

    addRelation(theRelMBeanObjName, theRelServObjName);

} catch(Exception e) {
    echo("\t Could not create relation MBean for relation " + relId2);
    printException(e);
}

// Add our new MBean as a relation to the relation service
try {
    Object[] params2 = new Object[1];
    params2[0] = theRelMBeanObjName;
    String[] signature2 = new String[1];
    signature2[0] = "javax.management.ObjectName";
    server.invoke(theRelServObjName, "addRelation",
                  params2, signature2);
} catch(Exception e) {
    echo("\t Could not add relation MBean " + relMBeanObjName);
    printException(e);
}

After a relation instance is added to the relation service, it can be accessed normally like other relations. Management operations can either operate on the MBean directly or access it through its identifier in the relation service. Two methods of the service are specific to external relation MBeans:

In our example, our MBean does not expose any functionality that interacts with the relation service. It relies fully on the support class and only adds the implementation of its own simple MBean interface. In a more realistic example, the MBean would expose attributes or operations related to its role values.

For example, Personal Library could be a unary relation type containing the Books role. We could then design an Owner MBean to be a relation of this type. In addition to exposing attributes about the owner, the MBean would give the number of books in the library, return an alphabetized list of book titles, and provide an operation for selling a book. All of these would need to access the role list, and the sale operation would need to modify the role to remove a book MBean.

All of these operations would need to keep the consistency of the relation. To do this, the relation service exposes several methods that relation MBeans must call: