7.3 Relation Service

MBeans seldom exist in isolation. They are usually clustered together in small groups of interrelated MBeans. For example, the MBean representing a managed device is related to the monitors that observe its attributes and perhaps to a timer service instance. A managed application provides a more complex example. In that case we have relationships between the application's managed components and between the monitors and services associated with each of those components.

Management applications need a simple, efficient way to access related sets of MBeans. One possible solution would be to use the MBeanServer's query methods to look up all the monitors for a device or to find an application's managed components. To be successful, this approach requires that every MBean consistently follow a specific object-naming convention. Defining such a convention is problematic under the best of circumstances; in the dynamic management environment supported by JMX, where MBeans and management applications from multiple vendors come together, it rapidly becomes unworkable. The JMX relation service addresses this requirement by explicitly modeling the relationships between MBeans.

The relation service implements a dynamic object model that allows management applications to define and instantiate new types of relations ” associations between multiple MBeans in named roles ”at runtime. Once a relation has been defined and one or more instances have been created, other management applications use the relation service to find related sets of MBeans. The relation service is also responsible for monitoring the consistency of each relation under its control. Finally, it is possible, with a little programming, to use relation service facilities to create and manage compound MBeans.

7.3.1 A Simple Example: The SessionPool Relation

Before we jump into the details of the relation service API, let's look at a simple example to make things more concrete.

Resource pooling is a common server-side technique for meeting performance and scalability requirements. Most application servers pool all kinds of things ”threads, database connections, even whole JVMs. You may recall that the "time of day daemon," todd, developed in Chapter 2's Quick Tour section (Section 2.6) pooled todd sessions. In the managed version of todd we created the SessionPoolMBean interface. In this section we'll demonstrate how to use the relation service to explicitly model the relationships between the SessionPool class and its associated JMX components.

Every relation managed by the relation service is an instance of a particular relation type. A relation type describes a relation's roles. Each role has a name and indicates the class and multiplicity of the MBeans that satisfy that role. For this example we'll define a relation type named SessionPool with three roles:

  1. gauges contains at least one but no more than two instances of GaugeMonitor; these will be the monitors that observe how many sessions are available and, optionally , the size of the pool.

  2. timer contains at most one instance of the Timer class that SessionPool uses to send epoch notifications.

  3. pool is the SessionPoolMBean itself.

Before we do anything else, we need to instantiate the relation service. Because it is an MBean, we can instantiate it via the MBeanServer:

 ObjectName rson = new ObjectName("todd:id=RelationService");  mbs.createMBean("javax.management.relation.RelationService",                 rson,                 new Object[] {new Boolean(true) },                 new String[] {"boolean" }); 

The RelationService constructor takes a single Boolean argument that determines whether or not relations are purged from the service immediately. The alternative is to leave them in place until they are explicitly purged by a call to purgeRelations() . The trade-off here is similar to the trade-off between automatic garbage collection and explicit memory deallocation: The former is safer but less efficient than the latter. In this example we go with safety over efficiency.

To create our new relation type, we use the RelationService 's createRelationType() method. The createRelationType() method takes a name and an array of RoleInfo instances as arguments. Each element of the RoleInfo array provides a description of one of the new relation type's roles. The following code sets up the RoleInfo array for our SessionPool relation type:

 RoleInfo[] sproles = new RoleInfo[3];  sproles[0] = new RoleInfo("pool", "net.jnjmx.ch3.todd.SessionPool"); sproles[1] = new RoleInfo("gauges",                           "javax.management.monitor.GaugeMonitor",                           true, false, 1, 2, null); sproles[2] = new RoleInfo("timer",                           "javax.management.timer.Timer",                           true, false, 0, 1, null); 

The RoleInfo constructor requires the role name and MBean class parameters. The remaining, optional, parameters are

  • Readable , which indicates whether the role is readable; it defaults to true .

  • Writeable , which indicates whether the role is writable; it defaults to true .

  • MinimumDegree , which specifies the minimum number of MBeans that may be provided for the role; it defaults to 1 .

  • MaximumDegree , which specifies the maximum number of MBeans that may be provided for the role; it defaults to 1 .

  • Description , which is a text description of the role; it defaults to null .

Now we have the necessary raw materials to create our SessionPool relation type:

 mbs.invoke(rson,             "createRelationType",            new Object[] {"SessionPool", sproles },            new String[] {"java.lang.String", "[Ljavax.management.relation.RoleInfo)" }); 

The only tricky part in the MBeanServer invocation of createRelationType() is the description of the RoleInfo[] parameter in the signature array. You have to use a JNI-style signature string ”that is, "[L<fully qualified classname>)" [http://java.sun.com/products/jdk/1.2/docs/guide/jni/spec/jniTOC.doc.html].

We instantiate the SessionPool relation type via the RelationService 's createRelation() method. The createRelation() signature is

 public void createRelation(String id, String relname,      RoleList roles) {} 

The id parameter is a unique identifier for this instance of RelationService . The relname parameter designates the relation type being instantiated . The final parameter is a list of Role values that meet the relation type's RoleInfo specifications.

Each Role value consists of a role name and a list of object names that play that role in this instance of the relation type. We build up the role list by creating instances of Role and then adding them to RoleList using the add() method:

 RoleList sprl = new RoleList();  ArrayList poolval = new ArrayList(); poolval.add(new ObjectName("todd:id=SessionPool")); sprl.add(new Role("pool", poolval)); ArrayList gaugesval = new ArrayList(); gaugesval.add(new ObjectName("todd:id=SessionPoolMonitor")); sprl.add(new Role("gauges", gaugesval)); 

Finally, we can invoke createRelation() to instantiate a SessionPool relation type:

 mbs.invoke(rson, "createRelation",         new Object[] { "todd.sessionpool", "SessionPool", sprl },        new String[] { "java.lang.String",                       "java.lang.String",                       "javax.management.relation.RoleList" }); 

What's the payoff for all this work? The RelationService class has a suite of get methods that provide lots of useful information about the relations under its control. In addition, it has a couple of useful query methods. For example, RelationService 's AllRelationIds attribute holds a list of the unique IDs associated with its relations. Given a relation ID, we can retrieve the relation's RoleList , which we can then iterate over to get the object names of the MBeans in each of the roles. Alternatively, we can start with an object name and use the findReferencingRelations() method to determine which relations an MBean is part of. We'll look at the methods of RelationService in more detail in the next section.

In the interest of full disclosure, we should point out that using the relation service in todd is overkill. There are only a handful of MBeans in todd, so it is easy to keep track of them. We used todd here because it provided a simple, familiar environment for our sample code. In general the relation service's utility grows as the number of MBeans in a system and the number of management applications that deal with that system increase.

7.3.2 The RelationService Class

The javax.management.relation package contains four interfaces and a dozen classes. The RelationService class is the core of the package. All of the other classes and interfaces come together in the RelationService class, and RelationService is the class that users of the package interact with most. Therefore, we will describe many of the package's classes and interfaces in the context of RelationService .

The fact that the RelationService class implements the RelationServiceMBean interface makes it a standard MBean. This also means that from a JMX perspective, RelationService has a well-defined management interface consisting of constructors, attributes, operations, and notifications.

7.3.2.1 RelationService Attributes

The RelationService 's management interface defines four attributes, which are listed in Table 7.5.

Because RelationService is an MBean, the values of each of these attributes can be retrieved via one of the MBeanServer's getAttribute() methods.

7.3.2.2 RelationType Operations

Two RelationService methods support the creation of new relation types:

 public void addRelationType(RelationType reltype)  public void createRelationType(String typename, RoleInfo[] roles) 

We used the createRelationType() method in the SessionPool example. Because the relation type it creates exists only within the confines of the relation service, it is known as an internal relation type. The addRelationType() method is used to create external relation types ”that is, relation types that exist outside the relation service itself. External relations are represented by the RelationType interface, which defines methods for accessing the relation type's name and role information.

Table 7.5. RelationService Attributes

Attribute

Type

Description

AllRelationIds

Read-only

A List -valued attribute containing the unique identifier for each relation under RelationService 's control.

AllRelationTypeNames

Read-only

A List -valued attribute containing the unique identifier for each relation type defined in RelationService .

PurgeFlag

Read/write

A boolean -valued attribute indicating whether or not a relation should be purged from RelationService as soon as it becomes invalid.

Active

Read-only

A boolean -valued attribute indicating whether or not the relation service is active. A RelationService instance is considered active if it is registered with the MBeanServer.

The relation service provides a couple of methods for retrieving information about defined relation types:

 public RoleInfo getRoleInfo(String typename, String rolename)  public List getRoleInfo(String typename) 

The former method returns a RoleInfo instance that describes the specified role in the relation type indicated by the typename parameter. The latter method returns a java.util.List object of RoleInfo instances that describes all of the specified relation type's roles.

When a relation type is no longer needed, it can be removed by the removeRelationType() method:

 public void removeRelationType(String typename) 

Any relations of the relation type will be removed from the relation service when the relation type is removed.

7.3.2.3 Relation Operations

Two RelationService methods support the creation of new relations:

 public void addRelation(ObjectName objname)  public void createRelation(String relid, String typename,      RoleList roles) 

Like relation types, relations may be internal or external. Internal relations are created via createRelation() as we saw in the SessionPool example. External relations are instantiated with the addRelation() method.

The RoleList class extends the java.util.ArrayList class and contains the Role values that will be used to instantiate the relation type. Each Role instance consists of a name, which must match one of the roles defined by the relation type, and a list of object names that play that role in this instance.

When a relation is no longer needed, it can be removed by the removeRelation() method:

 public void removeRelation(String relid)  public void purgeRelations() 

Removing a relation has no effect on any of the MBeans it references. When MBeans are removed from the MBeanServer, the relations they belong to may become invalid; for example, a role is no longer filled, or a cardinality constraint is no longer met. The purgeRelations() method checks all the data structures in the relation service and removes all relations that are no longer valid. When the value of the relation service's PurgeFlag attribute is true , purgeRelations() is called automatically whenever a deregistration notification is received from the MBeanServerDelegate MBean.

RelationService provides a set of three get methods that retrieve information about a particular relation:

 public RoleResult getAllRoles(String relid)  public String getRelationTypeName(String relid) public Integer getRoleCardinality(String relid, String rolename) 

As the name implies, the getRelationTypeName() operation returns the name of the given relation ID's relation type. The remaining operations return information about the relation ID's roles. The getAllRoles() method returns a RoleResult object that contains all of the RelationService instance's roles.

What is a RoleResult object? It is an object that provides access to several roles of a relation for reading and/or writing. Here is its class skeleton:

 public class RoleResult {    public RoleList getRoles() {}   public RoleUnresolvedList getRolesUnresolved() {}   public void setRoles(RoleList roles) {}   public void setRolesUnresolved(RoleUnresolvedList unroles) {} } 

In addition to getting a RoleList instance, via getRoles() , that we could iterate over to extract the object names of the MBeans in that role, we can use the setRoles() method to change the role's members , provided that the role in question is writable. The getRolesUnresolved() method returns a list of roles that the relation service was not able to resolve; generally roles are not resolved because either they are not readable or the referenced relation doesn't have a role with the given name. The setRolesUnresolved() method is used by code that needs to return a RoleResult object ”for example, the RelationSupport class.

Finally, getRoleCardinality() returns the number of MBeans that the specified relation currently has in the specified role.

7.3.2.4 Query Operations

RelationService provides four query operations:

 public List findRelationsOfType(String typename)  public Map getReferencedMBeans(String relid) public Map findAssociatedMBeans(ObjectName objname, String      typename, String rolename) public Map findReferencingRelations(ObjectName objname, String      typename, String rolename) 

The first two are straightforward. The findRelationsOfType() method does just that: It finds all the relations of the specified type and returns their relation IDs in a List object. The getReferencedMBeans() method returns a Map object of the MBeans that the given relation ID currently references; the Map keys are the object names of the MBeans, and the corresponding values are lists of the names of the roles that those MBeans play.

The findAssociatedMBeans() and findReferencingRelations() methods differ only in the Map instance that they return. The former returns a Map instance whose keys are the object names of MBeans associated with the given MBean. The values that correspond to those keys are lists of the relation IDs in which the association exists. The latter returns a Map instance whose keys are the relation IDs of the relations that reference the given MBean. The values that correspond to those keys are lists of the names of the roles played in those relations.



Java and JMX. Building Manageable Systems
Javaв„ў and JMX: Building Manageable Systems
ISBN: 0672324083
EAN: 2147483647
Year: 2000
Pages: 115

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net