In the previous section, we worked through a complete example of how to create an internal relation using an internal relation type. In this section, we will look at the same example, only we will see how to create the relation as an external relation using an external relation type. As we mentioned, the relation service provides a number of support classes that can be used for this purpose. At the risk of being a bit redundant, we will repeat the flow of the previous section as closely as possible so you can compare the internal and external relations and relation types.
Before we can create a relation, we have to create the MBean server and an instance of the relation service MBean, and then register the relation MBean with the MBean server:
try { MBeanServer server = MBeanServerFactory.createMBeanServer( ); boolean purgeImmediate = true; RelationService rs = new RelationService(purgeImmediate); ObjectName rsObjName = new ObjectName("AgentServices:name=Relation"); server.registerMBean(rs, rsObjName); // . . . } catch (Exception e) { // . . . }
As we saw with an internal relation type, we next describe the roles
in the relation using one or more RoleInfo
objects. However, to create an external relation type, we subclass
the RelationTypeSupport
class and add code to the
subclass constructor to create the
RoleInfo
objects:
public class ConsumerSupplierRelationType extends RelationTypeSupport { public ConsumerSupplierRelationType ( ) { super("ConsumerSupplierRelationType_External"); try { addRoleInfo(new RoleInfo("Consumer", "sample.standard.Consumer", true, false, 1, 2, "Consumer Role Information")); addRoleInfo(new RoleInfo("Supplier", "sample.standard.Supplier", true, false, 1, 1, "Supplier Role Information")); } catch (Exception e) { throw new RuntimeException(e.getMessage( )); } } }
The emphasized lines point out some of the things we have to do in
preparation for creating an external relation type. First, we
subclass RelationTypeSupport
with a class called
ConsumerSupplierRelationType
. In the subclass
constructor, we delegate to one of the constructors of
RelationTypeSupport
, passing the name of the
relation type. Then we call the addRoleInfo( )
method, passing in a new
RoleInfo
instance for each of the roles in the
relation type.
This time, instead of using the relation service to create the
relation type, we will do it explicitly by instantiating the
ConsumerSupplierRelationType
class. Once we
instantiate the class representing the external relation type, we add
the relation type to the relation service via the
addRelationType(
)
method:
try { MBeanServer server = MBeanServerFactory.createMBeanServer( ); boolean purgeImmediate = true; RelationService rs = new RelationService(purgeImmediate); ObjectName rsObjName = new ObjectName("AgentServices:name=Relation"); server.registerMBean(rs, rsObjName); ConsumerSupplierRelationType rt = new ConsumerSupplierRelationType( ); rs.addRelationType(rt); // . . . } catch (Exception e) { // . . . }
Before we continue, I should point out that you can use
RelationTypeSupport
on its own (i.e., without
subclassing it). You may have noticed in the example above that we
don’t do much with the relation type subclass, other
than delegate to the parent. Subclassing
RelationTypeSupport
is a way to encapsulate role
information inside a class, and it offers us a way to separate
concerns in the design of our agents. However, if this separation of
concerns is not strictly necessary, we can still create an external
relation type without using a subclass:
try { MBeanServer server = MBeanServerFactory.createMBeanServer( ); boolean purgeImmediate = true; RelationService rs = new RelationService(purgeImmediate); ObjectName rsObjName = new ObjectName("AgentServices:name=Relation"); server.registerMBean(rs, rsObjName); RoleInfo[] roleInfo = new RoleInfo[2]; roleInfo[0] = new RoleInfo( Consumer.ROLE, // role name "sample.standard.Consumer", // class name true, // role can be read true, // role can be modified 1, // must be at least one 2, // no more than two "Consumer Role Information" // description ); roleInfo[1] = new RoleInfo( Supplier.ROLE, // role name "sample.standard.Supplier", // class name true, // role can be read true, // role can be modified 1, // must be at least one 1, // no more than two "Supplier Role Information" // description ); RelationTypeSupport rt = new RelationTypeSupport( "ConsumerSupplierRelationType_External", roleInfo ); rs.addRelationType(rt); // . . . } catch (Exception e) { // . . . }
Once we create an array of the necessary RoleInfo
objects, we pass the array to the second constructor of
RelationTypeSupport
. Then we simply call the
addRelationType( ) method of the relation
service to add the standalone external relation type.
Once the relation type has been created, we instantiate the role by
creating a Role
object for each group of MBeans to
participate in the relation:
try { // . . . rs.addRelationType(rts); // Create and register a Consumer MBean ObjectName consumerObjName = createWorker("Consumer", 100); ArrayList consumerList = new ArrayList( ); consumerList.add(consumerObjName); Role consumerRole = new Role("Consumer", consumerList); // Create and register a Supplier MBean ObjectName supplierObjName = createWorker("Supplier", 100); ArrayList supplierList = new ArrayList( ); supplierList.add(supplierObjName); Role supplierRole = new Role("Supplier", supplierList); RoleList roles = new RoleList( ); roles.add(consumerRole); roles.add(supplierRole); // . . . } catch (Exception e) { // . . . }
Regardless of whether the relation type is internal or external, we
must still create Role
objects. The final steps in
creating the external relation are to instantiate and use the class
representing the external relation:
public class ConsumerSupplierRelation extends RelationSupport implements ConsumerSupplierRelationMBean { public static final String NAME = "ConsumerSupplierRelation_External"; public static final String OBJECT_NAME = "UserDomain:name=" + NAME; private String _relationTypeName; private String _relationServiceObjName; private List _roleList; // MBean interface public String getRelationTypeName ( ) { return _relationTypeName; } public String getRelationServiceObjName ( ) { return _relationServiceObjName; } public List retrieveRoleList ( ) { return _roleList; } public String getRelationId ( ) { return NAME; } public ConsumerSupplierRelation (ObjectName relationServiceObjName, String relationTypeName, RoleList roleList) throws Exception { super(NAME, relationServiceObjName, relationTypeName, roleList); _relationTypeName = relationTypeName; _relationServiceObjName = relationServiceObjName.toString( ); _roleList = new ArrayList(roleList.size( )); _roleList.addAll(roleList); } }
The external relation we are going to create is
ConsumerSupplierRelation
,
which is a subclass of RelationSupport
. One
immediately noticeable difference between an external relation type
and an external relation is that an external relation is an MBean.
Notice the MBean interface implemented by
ConsumerSupplerRelation
:
public interface ConsumerSupplierRelationMBean extends RelationSupportMBean { String getRelationTypeName ( ); String getRelationServiceObjName ( ); List retrieveRoleList ( ); }
Once our external relation class has been instantiated, it must be registered with the MBean server and added to the relation service:
try { // . . . Role supplierRole = new Role("Supplier", supplierList); RoleList roles = new RoleList( ); roles.add(consumerRole); roles.add(supplierRole); ConsumerSupplierRelation relation = new ConsumerSupplierRelation( rsObjName, rt.getRelationTypeName( ), roles); ObjectName relationObjName = new ObjectName("ConsumerSupplierRelation_External"); server.registerMBean(relation, relationObjName); rs.addRelation(relationObjName); } catch (Exception e) { // . . . }
When we create an external relation by subclassing
RelationSupport
, it is very important to remember
that the MBean interface of the subclass must extend
RelationSupportMBean
. Otherwise, when we attempt
to add the relation, the relation service will throw an exception.
Example 11-2 shows a complete source listing of how
to create the external
Consumer
/Supplier
relation we’ve been
studying.
Example 11-2. Creating an external relation
try { MBeanServer server = MBeanServerFactory.createMBeanServer( ); boolean purgeImmediate = true; RelationService rs = new RelationService(purgeImmediate); ObjectName rsObjName = new ObjectName("AgentServices:name=Relation"); server.registerMBean(rs, rsObjName); ConsumerSupplierRelationType rt = new ConsumerSupplierRelationType( ); rs.addRelationType(rt); // Create and register a Consumer MBean ObjectName consumerObjName = createWorker("Consumer", 100); ArrayList consumerList = new ArrayList( ); consumerList.add(consumerObjName); Role consumerRole = new Role("Consumer", consumerList); // Create and register a Supplier MBean ObjectName supplierObjName = createWorker("Supplier", 100); ArrayList supplierList = new ArrayList( ); supplierList.add(supplierObjName); Role supplierRole = new Role("Supplier", supplierList); RoleList roles = new RoleList( ); roles.add(consumerRole); roles.add(supplierRole); ConsumerSupplierRelation relation = new ConsumerSupplierRelation( rsObjName, rt.getRelationTypeName( ), roles); ObjectName relationObjName = new ObjectName("ConsumerSupplierRelation_External"); server.registerMBean(relation, relationObjName); rs.addRelation(relationObjName); } catch (Exception e) { // . . . }