4.2. The Breakdown of Agent Plug-in Configuration
Agents do not have a fixed functionality; their functions, from monitoring to the resources they can inventory, are defined by their plug-ins.
At its core, an agent plug-in consists of a single JAR file and an XML plug-in descriptor file (
rhq-plugin.xml
inside the META-INF/
directory).
Along with the plug-in descriptor, an agent plug-in has up to three different types of Java files for each plug-in defined in the JAR file package:
- A plug-in component file that contains all of the code for the plug-in functionality
- A
*Discovery.java
file that configures the discovery process for the resources defined in the plug-in - A
*EventPoller.java
that defines the events that can be collected by the resource
The definitions in the Java files closely track the configuration for the plug-in in the
rhq-plugin.xml
plug-in descriptor.
TIP
Generating an agent plug-in template with the plug-in generator creates files with TODO markers to help guide writing the plug-in.
4.2.1. Schema Files
The agent plug-in is defined through its metadata and configuration in its XML plug-in descriptor file. The configuration elements that are available to the descriptor are defined in the XML schema definition (XSD) files for agent plug-ins.
All JBoss ON plug-ins — both agent plug-ins and server-side plug-ins — uses the
rhq-configuration.xsd
file to define the basic configuration options available.
Agents also use the
rhq-plugin.xsd
file, which extends the rhq-configuration.xsd
schema and adds additional elements specifically for resource-related plug-ins.
Note
More information about specific elements within both XSD files is available through the comments (in <xs:annotation> items) in the XSD files themselves.
The
rhq-configuration.xsd
file provides schema which is available for all JBoss ON plug-ins. The rhq-configuration.xsd
file is in source/modules/core/client-api/src/main/resources
.
The most commonly used elements defined in the
rhq-configuration
schema relate to setting configuration values for a plug-in, like <simple-property> and <map-property>.
Element | Description |
---|---|
configuration-property | For adding a configuration attribute to a plug-in for user-defined settings. |
simple-property | For setting a default configuration value. |
option | For setting whether a property's values come from an enumerated list (false) or can be anything defined by the user (true). |
The
rhq-configuration.xsd file
also defines the most common flags that can be used for the plug-in descriptor, including the required name
and optional displayName
attributes.
Attribute | Description |
---|---|
name | Required. Gives a unique name for the plug-in. |
displayName | Gives the name to use for the plug-in in the GUI. If this isn't given, then the name value is used. |
description | Gives a short description of the plug-in. |
The
rhq-plugin.xsd
provides all of the schema elements specifically for agent plug-ins. The rhq-plugin.xsd
file is in the source/modules/core/client-api/src/main/resources
directory.
The most common elements in the
rhq-plugin.xsd
file are listed in Table 4.3, “rhq-plugin.xsd Schema Elements”.
Element | Description |
---|---|
plugin | Contains the root element for the plug-in descriptor. |
depends | Identifies any other plug-ins which this plug-in requires or extends. |
platforms, servers, services | Identifies the type for a resource defined within the agent plug-in. <platforms> are top-level elements, but <servers> and <services> are added as children of platforms or other server and service resources. |
metric |
An element within a platform, server, or service which defines metrics which can be collected for that resource type.
Child elements and attributes for this resource element are listed in the
rhq-plugin.xsd file.
Values that form part of a larger data structure, such as an array of values, need to be deconstructed into individual values before they can be monitored.
|
event | An element within a platform, server, or service which defines whether that resource supports events. There are no other configuration properties with events; the events themselves are culled from the resource's log files. |
bundle-target |
Configures whether and how bundles can be deployed to a resource.
Child elements and attributes for this resource element are listed in the
rhq-plugin.xsd file.
|
drift-definition |
Configures whether and how drift monitoring can be performed for a resource.
Child elements and attributes for this resource element are listed in the
rhq-plugin.xsd file.
|
resource-configuration |
Defines a configuration property for a resource type.
Child elements and attributes for this resource element are listed in the
rhq-plugin.xsd file.
|
operation |
Defines an operation that can be performed on that resource type.
Child elements and attributes for this resource element are listed in the
rhq-plugin.xsd file.
|
content |
Configures what types of packages can be uploaded or deployed on a resource type.
Child elements and attributes for this resource element are listed in the
rhq-plugin.xsd file.
|
Most of the attributes defined within the
rhq-plugin.xsd
contain flags that are used within the root element of the plug-in descriptor. These add additional management attributes for controlling the release and updates of agent plug-ins.
Attribute | Description |
---|---|
package | For setting the plug-in package name. |
version | For setting the version of the plug-in. This must be in an OSGi-compatible format. |
ampsVersion | For the agent plug-in system version that this plug-in requires. This must be in an OSGi-compatible format. |
pluginLifecycleListener | For the listener which initializes and shuts down the plug-in. |
discovery | Sets whether a resource type is detected by discovery scans. This flag may not be necessary for child resources that will be discovered by the parent resource. |
There are many other elements and attributes set in the
rhq-plugin.xsd
file. Each one is described by the text in the <xs:annotation> tags for the item.
4.2.2. Descriptor and Configuration
A plug-in descriptor contains the metadata that described everything about the plug-in and the resource it configured. The descriptor describes the type and interactions of the resource type the agent plug-in defines.
The plug-in descriptor contains the information about name of the resource, the supported resource versions, the total resource hierarchy (meaning parents or children of the resource), configuration properties that the agent uses to connect to the resource, and all of the monitoring metrics, operations, and events related to the resource that can be managed by the agent.
The plug-in descriptor also contains information about the plug-in itself.
A resource definition in a plug-in descriptor can be a platform, server, or service. Multiple resources can be defined in a single plug-in descriptor; one resource is the root (parent) element, and the rest of the resources defines are its children.
Because the plug-in descriptor is an XML file, it follows a clear and structured schema definition. The schema definitions are what allow the plug-in descriptor to expose the resource's management interfaces to JBoss ON.
The plug-in descriptor, at a minimum, defines the resource type. Past that, it defines the different aspects of the resource that JBoss ON can manage:
- The names of the resource types (servers and services) supported by the plug-in
- Any configuration settings that the agent's plug-in components use to connect to the resource
- Any metrics (measurement definitions) to use to monitor the resource; this depends on the type of data issued by the resource itself.
- A set of operations that can be invoked on the resource. This is commonly start and stop operations, but it can include application-specific operations or other actions, like running a script.
- Resource configuration values that can be edited in the actual configuration of the resource.The plug-in configuration tells the components how to connect to the resource. The resource configuration, on the other hand, are settings in the resource itself that can be edited externally.
- Any child resources that are part of the resource hierarchy. For example, a JBoss server has data source services running within them, so the data source services are defined in the JBoss server resource plug-in, as a child resource of the JBoss server.
4.2.2.1. Resource Type, Metadata, and Plug-in Configuration
The top element in an agent plug-in is the <plugin> element.
<plugin name="JMX" displayName="Generic JMX" package="org.rhq.plugins.jmx" description="Supports management of JMX MBean Servers via various remoting systems." ampsVersion="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
Several attributes on this element are important:
name
anddisplayName
give the internal and GUI name of the plug-in.ampsVersion
gives the version number of the plug-in itself.package
gives the name of the classes used by the components in the plug-in.
The next element in the plug-in descriptor defines the root resource that is defined by the plug-in. This can be <platform>, <server>, or <service>.
One or multiple resources can be defined in a plug-in descriptor. The plug-in descriptor not only defines those resource types, but it organizes those types in a parent-child hierarchy. For example, a JBoss EJB service only runs inside of a JBoss server, so the EJB service resource type should logically be a child type of the JBoss server resource type.
The hierarchy is defined by nesting <service> resource definitions inside <server> (or other <service>) resource definitions.
<server name="JMX Server" discovery="JMXDiscoveryComponent" class="JMXServerComponent" description="Generic JMX Server" supportsManualAdd="true" createDeletePolicy="neither">
IMPORTANT
Do not rename resource types when you edit the resource plug-in. This breaks backward compatibility with any resource that was inventoried using the older version of the plug-in.
Two of the attributes are related to the Java resource files associated with the plug-in:
discovery
identifies the discovery component used to identify the resource type.class
identifies the plug-in component which contains the actual code of the plug-in.
Two of the attributes define how resources of that type are added to the inventory:
supportsManualAdd
allows resources to be added to the inventory by administrators.createDeletePolicy
sets whether children can be added or removed manually from inventory.
The last part that relates to configuring the plug-in is setting (optional) plug-in configuration properties. These are flexible and can define anything related to the information required to identify or set up a resource which matches the resource type in the plug-in, even setting constraints on allowed values or templates to define default settings.
<plugin-configuration> <c:list-property name="Servers"> <c:map-property name="OneServer"> <c:simple-property name="host"/> <c:simple-property name="port"> <c:integer-constraint minimum="0" maximum="65535"/> </c:simple-property> <c:simple-property name="protocol"> <c:property-options> <c:option value="http" default="true"/> <c:option value="https"/> </c:property-options> </c:simple-property> </c:map-property> </c:list-property> </plugin-configuration>
The port has a constraint so, the GUI can validate the input being between 0 and 65535. The protocol can be selected from a list of drop-down menu items, with a default value of HTTP.
There are three types of properties:
- <simple-property>, which defines a one key-value pair
- <map-property>, which defines multiple key-value pairs related to a single entity, following the
java.util.Map
concept - <list-property>, which contains a list of properties
Both <map-property> and <list-property> define groups of <simple-property> element. Additionally, these properties can be formally grouped together under <group> element. Using a <group> element creates a collapsible configuration ares in the UI.
Templates can preset some configuration properties.
<c:template name="JDK 5" description="Connect to JDK 5"> <c:simple-property name="type" default="org.mc4j.ems.connection.support.metadata.J2SE5ConnectionTypeDescriptor"/> <c:simple-property name="connectorAddress" default="service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi"/> </c:template>
4.2.2.2. Discovery and Process Scans
The central functionality of JBoss ON is the inventory. Each resource must be present in that inventory, so the plug-in descriptor has to define how resources are detected and how they are added to inventory. This is done through the discovery component.
The <plugin> element has a
discovery
attribute which identifies the discovery Java file for the resource plug-in. (If there are multiple resources defined in the plug-in, then there will be multiple discovery components.)
When the agent plug-in is generated using the plug-in generator, it creates the appropriate template to add the discovery requirements. The discovery component has to have the information to find a resource instance and to assign a unique identifier to that resource.
/** * Discovery class */ public class testDiscovery implements ResourceDiscoveryComponent ,ManualAddFacet { private final Log log = LogFactory.getLog(this.getClass()); /** * Do the manual add of this one resource */ public DiscoveredResourceDetails discoverResource(Configuration pluginConfiguration, ResourceDiscoveryContext context) throws InvalidPluginConfigurationException { // TODO implement this DiscoveredResourceDetails detail = null; // new DiscoveredResourceDetails( // context.getResourceType(), // ResourceType // ); return detail; } }
Identifying resource instances is a critical part of maintaining the inventory. Any resource must be unique and must be consistently identified between discovery scans . Agents identify resources by constructing a unique resource key. A resource key varies by resource type. Whatever the key is, it has to intrinsic to the resources and detectable for the agent. Keys do not have to be globally unique, but they must be unique beneath a parent resource. For a JMX server, the resource key is its connector address, which is unique to the instance.
public DiscoveredResourceDetails discoverResource(Configuration pluginConfig, ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException { // TODO: Connect to the remote JVM to verify the user-specified conn props are valid, and if connecting // fails, throw an exception. String resourceKey = pluginConfig.getSimpleValue(CONNECTOR_ADDRESS_CONFIG_PROPERTY, null); String connectionType = pluginConfig.getSimpleValue(CONNECTION_TYPE, null); // TODO (ips, 09/04/09): We should connect to the remote JVM in order to obtain its version. String version = null; DiscoveredResourceDetails resourceDetails = new DiscoveredResourceDetails(discoveryContext.getResourceType(), resourceKey, "Java VM", version, connectionType + " [" + resourceKey + "]", pluginConfig, null); return resourceDetails; }
Optional dependencies can affect discovery. Embedded plug-ins copy the child type from the source plug-in, and then use the embedded plug-in's discovery component to run the discovery. Injected plug-ins take a parent resource and cycle through all potential children resource types and run a discovery for each type, injecting the parent component into each child type's discovery method.
Often, resources are processes running on the local machine. The JBoss ON agent can query the process table to detect those local processes. This is first defined in the plug-in descriptor using a <process-scan> element and then implemented in the discovery component.
Each resource type defined in the plug-in descriptor can have a <process-scan> child element. The <process-scan> element itself is empty, but has two required attributes:
name
and query
. name
identifies the specific scan method. query
is the attribute that does something. The query
is a string written in Process Info Query Language (PIQL). This value is used to search for the process.
The sourceforge PIQL API docs provide much more information on the syntax of PIQL queries.
The basic format of a PIQL process scan query is a three-part term which looks for the process, some kind of identifying marker, and then the value to match.
process|attribute|match=value,arg|attribute|match=value
For a process scan for discovery, the scan will usually look for a process name or a PID file.
Looking for a process by name can require additional attributes to help narrow the search down to a specific type of resource or even a specific instance. For example, a JBoss AS instance has a process name that starts with java and an argument with the value org.jboss.Main. The ps information contains both of those attributes.
jsmith 2035 0.0 -1.5 724712 30616 p7 S+ 9:49PM 0:01.61java
-Dprogram.name=run.sh -Xms128m -Xmx512m -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djboss.platform.mbeanserver -Djava.endorsed.dirs=/devel/jboss-4.0.5.GA/lib/endorsed -classpath /devel/jboss-4.0.5.GA/bin/run.jar:/lib/tools.jarorg.jboss.Main
-c minimal
The PIQL query, then attempts to match the process name, using the basename query attribute, with a matching argument, defined in the arg query attribute.
process|attribute|match=value,arg|attribute|match=value | | |____ |_ |____ |______ | | | | | | | | | | | | | | | | | | | | | | | | process|basename|match=^java.*,arg|org.jboss.Main|match=.*
Alternatively, the process scan query can match a pid file, which is a simple way to identify processes. A PID-based PIQL query has a slightly simpler format:
process|attribute|match=value
For example:
process|pidfile|match=/etc/product/lock.pid
After defining the scan query in the
rhq-plugin.xml
descriptor file, then the discovery component must be written to implement the scan and process results.
Example 4.1. Process Scan Method in the Discovery Component
List<ProcessScanResult< autoDiscoveryResults = context.getAutoDiscoveredProcesses(); for (ProcessScanResult result : autoDiscoveryResults) { ProcessInfo procInfo = result.getProcessInfo(); .... // as before DiscoveredResourceDetails detail = new DiscoveredResourceDetails( resourceType, key, name, null, description, childConfig, procInfo ); result.add(detail); }
The agent manages resources by gathering metrics (for monitoring) and by launching scheduled operations, or tasks, on the resource. These two areas are configured similarly in the plug-in.
Monitoring areas are configured through <metric> elements in the plug-in descriptor.
<metric displayName="Bytes Sent" description="Shows the rate that data bytes are sent by the Web service." property="Bytes Sent/sec" defaultOn="true" displayType="summary" measurementType="trendsup" units="bytes"/>
The most relevant attributes on that attribute relate to the monitoring property (which is partially defined by the resource itself).
property
identifies the resource monitoring property.measurementType
sets the data type being collected.units
sets the units of the thing being monitored.
In the plug-in Java component, the metric is first set up by pulling in the MeasurementFacet.
public class testComponent implements ResourceComponent , MeasurementFacet , OperationFacet
Then, there is an entry for monitoring in a MeasurementReport, with a MeasurementScheduleRequest entity for each type of monitoring data.
public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception { String propertyBase = "\\Web Service(_Total)\\"; Pdh pdh = new Pdh(); for (MeasurementScheduleRequest request : metrics) { double value = pdh.getRawValue(propertyBase + request.getName()); report.addData(new MeasurementDataNumeric(request, value)); } }
Important
When defining metrics, values that form part of a larger data structure, such as an array of values, need to be deconstructed into individual values before they can be monitored.
Similarly, operations are configured in the plug-in descriptor in an <operation> element, implemented in the plug-in Java component through an OperationFacet, and then invoked in a OperationResult method.
4.2.2.3. Events
Events for resources are essentially types of log messages that are recognized by the agent.
In the plug-in descriptor, an event is configured by a simple <event> element, no children, that identifies the logging area by name.
<event name="errorLogEntry" description="an entry in the error log file"/>
The event handling is handled through an
EventPoller
component. This can be in the larger plug-in Java component, but it is usually broken into a separate *EventPoller.java
component. The way to implement event polling depends on the resource and the nature of its logging. One of the simplest ways is to call the EventPoller()
, then define the event type and set how the event is polled.
public PerfTestEventPoller(ResourceContext resourceContext) { this.resourceContext = resourceContext; } public String getEventType() { return PERFTEST_EVENT_TYPE; } public Set<Event> poll() { int count = Integer.parseInt(System.getProperty(SYSPROP_EVENTS_COUNT, "1")); String severityString = System.getProperty(SYSPROP_EVENTS_SEVERITY, EventSeverity.INFO.name()); EventSeverity severity = EventSeverity.valueOf(severityString); Set<Event> events = new HashSet<Event>(count); for (int i = 0; i < count; i++) { Event event = new Event(PERFTEST_EVENT_TYPE, "source.loc", System.currentTimeMillis(), severity, "event #" + i); events.add(event); } return events; }
4.2.2.4. Resource Configuration
Resources can have parameters or settings changed through the JBoss ON GUI, managed by the agent. Those properties that can be edited are defined in the plug-in descriptor in <resource-configuration> elements. These configuration elements follow the same conventions as the <plugin-configuration> elements. The properties are defined as <simple-property> elements and can be listed (for options), mapped, or organized into groups that are collapsible sections in the UI.
<resource-configuration> <c:group name="Attributes"> <c:simple-property name="appBase" required="true" readOnly="true" description="The Application Base directory for this virtual host." /> <c:simple-property name="autoDeploy" type="boolean" description="Does this host deploy new applications dropped in appBase at runtime?" /> <c:simple-property name="deployOnStartup" type="boolean" description="Does this host deploy applications in appBase at startup?" /> <c:simple-property name="deployXML" displayName="Deploy XML" type="boolean" description="deploy Context XML config files?" /> <c:simple-property name="unpackWARs" displayName="Unpack WARs" type="boolean" description="Does this Host automatically unpack deployed WAR files?" /> <c:simple-property name="aliases" required="false" type="longString" description="Aliases assigned to the Host. When editing, each alias must be on a new line. Aliases are automatically lowercased." /> </c:group> </resource-configuration>
The first thing that is defined in the plug-in Java component is the ability to load the current configuration.
public Configuration loadResourceConfiguration() { Configuration configuration = super.loadResourceConfiguration(); try { resetConfig(CONFIG_ALIASES, configuration); } catch (Exception e) { log.error("Failed to reset role property value", e); } return configuration; }
The second part in the plug-in component allows the agent to change the configuration properties.
public void updateResourceConfiguration(ConfigurationUpdateReport report) { Configuration reportConfiguration = report.getConfiguration(); // reserve the new alias settings PropertySimple newAliases = reportConfiguration.getSimple(CONFIG_ALIASES); // get the current alias settings resetConfig(CONFIG_ALIASES, reportConfiguration); PropertySimple currentAliases = reportConfiguration.getSimple(CONFIG_ALIASES); // remove the aliases config from the report so they are ignored by the mbean config processing reportConfiguration.remove(CONFIG_ALIASES); // perform standard processing on remaining config super.updateResourceConfiguration(report); // add back the aliases config so the report is complete reportConfiguration.put(newAliases); // if the mbean update failed, return now if (ConfigurationUpdateStatus.SUCCESS != report.getStatus()) { return; } // try updating the alias settings try { consolidateSettings(newAliases, currentAliases, "addAlias", "removeAlias", "alias"); } catch (Exception e) { newAliases.setErrorMessage(ThrowableUtil.getStackAsString(e)); report.setErrorMessage("Failed setting resource configuration - see property error messages for details"); log.info("Failure setting Tomcat VHost aliases configuration value", e); } // If all went well, persist the changes to the Tomcat server.xml try { storeConfig(); } catch (Exception e) { report .setErrorMessage("Failed to persist configuration change. Changes will not survive Tomcat restart unless a successful Store Configuration operation is performed."); } }
4.2.3. Lifecycle Listeners
Some plug-ins need to perform some initialization immediately when they load and some cleanup when they unload. Global initialization and shutdown of a plug-in is performed by its lifecycle listener.
The
org.rhq.core.pluginapi.plugin.PluginLifecycleListener
class allocates global resources needed by plug-in components and cleans up those resources.
Each plug-in can optionally define one lifecycle listener by specifying a
pluginLifecycleListener
attribute in the top-level <plugin> element.
<plugin name="Apache" displayName="Apache HTTP Server" description="Management of Apache web servers" package="org.rhq.plugins.apache" pluginLifecycleListener="ApachePluginLifecycleListener" ...
4.2.4. Plug-in Dependencies: Defining Relationships Between Plug-ins
Agent plug-ins can have relationships with other agent plug-ins. These relationships created dependencies between plug-ins, where plug-ins are only operable when other plug-ins are loaded, that allow plug-ins to share classes, or that extend the resource hierarchy by adding additional parent or child resources to an existing resource definition.
A parent plug-in is one that has another plug-in depending on it. A child plug-in is a plug-in that depends on another plug-in.
Agent plug-ins have three ways of defining dependencies:
- Required dependencies are set using the <depends> element. Just using <depends> means that the required plug-in must be loaded or the other plug-in will fail to load. Adding the
useClasses
attribute makes the classes and JAR files for the parent plug-in available to the child plug-in. - An injection plug-in dependency means that a root-level resource runs inside another resource type, and that parent resource is defined as a parent plug-in. This essentially adds a new child to an existing resource type.
- An embedded plug-in dependency means that a new parent resource type is added for an existing child. This can allow the child to be extended to share the new parent's classloader (depending on both plug-ins' configuration) or simply expand discovery.
IMPORTANT
Embedded and injection plug-in dependencies are mutually exclusive. They cannot be used in the same plug-in definition.
There is one interesting similarity in all of these plug-in dependency models: Metadata and class definitions flow in only one direction, from a parent plug-in to its dependent plug-in. Information cannot flow in the other direction.
4.2.4.1. Required Plug-in Dependencies
The <depends> element directly under the <plug-in> element defines a parent plug-in that the plug-in depends on and required to be loaded. The <depends> element is what specifies a required dependency. The plug-in will not deploy successfully, unless all <depends> plug-ins are also successfully deployed.
The <depends> element can pull in JARs from the parent plug-in by specifying the
useClasses
attribute. The useClasses
option can be set for only one required dependency in a single plug-in descriptor. If no <depends> element has a useClasses
attribute, the last <depends> element specified in the plug-in descriptor, by default, has its useClasses attribute to true.
The <depends> element is used if the plug-in needs access to another plug-in's classes or if the plug-in should only be deployed when another plug-in is also deployed.
TIP
The embedded and injection plug-in dependencies are optional dependencies. If the specified plug-in isn't loaded, then the plug-in simply runs without loading those dependencies. To make an embedded or injection plug-in a required dependency, then set the embedded or injection plug-in as a required plug-in using the <depends> element, as well as the other configuration.
4.2.4.2. Embedded Plug-in Dependencies
An embedded plug-in dependency adds a new parent resource for an existing child resource. The dependent plug-in (for the new parent resource) depends on the child.
With an embedded plug-in dependency, the server or service definition can be a copy of a source resource type found in another plug-in. That copy is defined in the plug-in descriptor by setting the
sourcePlugin
and sourceType
attributes on the resource elements. When a plug-in source is specified, the server or service is copied from the source resource type, which means it has the same metadata as the source, with the exception that the embedded server or service can override the discovery and resource classes and, potentially, have a different name.
An embedded plug-in is an optional dependency.
4.2.4.3. Injection Plug-in Dependencies
A root-level resource type in an agent plug-in can define parent resource types that it can run inside of. This essentially injects the resource type as a child type to another, existing resource. This is an injection plug-in dependency.
The injection plug-in dependency illustrates that a child resource type knows about its parent resource types, but the parents do not know about the child. Knowledge of plug-ins flow down, not up. A parent plug-in's type information is known to its child plug-in, but a parent plug-in does not know anything about the child plug-ins that depend on it.
An injection dependency is a list of allowed parents, within a <runs-inside> element. Each parent is an optional dependency.
<runs-inside> <parent-resource-type name="JMX Server" plugin="JMX" /> <parent-resource-type name="JBoss Server" plugin="JBoss AS" /> </runs-inside>
4.2.5. Class Sharing Between Plug-ins
All agent plug-ins have their own classloader while running in the plug-in container. Each resource in inventory will be assigned a classloader, which can be the same as its plug-in classloader.
Figure 4.1. Agent Components, Together
All plug-in classloaders are isolated from one another, unless the <depends useClasses=""> attribute is set to true. If a plug-in is a direct dependent of another plug-in, and that dependency is defined with <depends useClasses="true">, then that parent plug-in's JAR classes (and all of its parent JARs) are available to the dependent plug-in's classloader.
The most common reason to create that kind of dependency, and share JARs and classes between plug-ins, is because one resource defined in one plug-in is deployed and running in another resource defined in another plug-in. The child plug-in needs a way to connect to its parent resource to perform things like discovery and management of the child resource. By default, all managed resources are assigned a resource classloader that is shared. This classloader can belong to the plug-in or to the parent resource.
When a resource component needs to create a connection to its actual managed resource, that resource's classloader must be different than the normal, shared plug-in classloader. The resource usually needs to have the client JARs necessary to connect to the managed resource within its own classloader, and those client JARs are usually very specific to the version of the resource being managed. The connecting resource should be in charge of creating the connection, since it knows how to do it. When a resource requires its own connection classloader, specify the attribute
classLoader="instance"
on the resource type and make sure the resource type's discovery component implements the ClassLoaderFacet
so it tells the plug-in container where any additional connection classes can be found for the specific version of the specific resource being managed.
In Example 4.2, “classLoader for Plug-in Z”, the Z1.server has a
classLoader
option set to shared. This means that Z1.server resources share their classloaders with their parent resources, and that classloader may be a resource classloader or a plug-in classloader. Every Z1.server resource uses the same classloader.
Example 4.2. classLoader for Plug-in Z
<plug-in name="Z"> <depends plugin="A" /> <server name="Z1.server" classLoader="shared"> <runs-inside> <parent-resource-type name="B1.server" plugin="B"/> <parent-resource-type name="C1.server" plugin="C"/> </runs-inside> </server> <server name="Z2.server" sourcePlugin="D" sourceType="D1" classLoader="instance"> </server> <server name="Z3.server" classLoader="instance"> </server> </plugin>
Normally, setting a
classLoader
option to instance means that each resource uses its own resource plug-in. However, for Z2.server, the Z2.server plug-in is extended by embedding the values for Plug-in D, so Z2.server resources share their classloaders with their parent plug-in.
Z3.server simply uses its own resource classloader because its
classLoader
option is set to instance and it has no injected or embedded dependencies. When the classLoader
option is set to instance, the ResourceDiscoveryComponent
implementation can optionally define a ClassLoaderFacet
with a method (getAdditionalClasspathUrls) that returns a List<URL> pointing to additional JARs that should be placed in the resource's classloader. When the plug-in container needs to create a classloader for a resource, it checks if the resource's discovery component implements this facet, and, if so, it gets the additional classpath URLs and adds them to the resource classloader when it creates it.
If a resource type is defined with either an injection or embedded dependency, then its classloader depends on both its
classLoader
attribute value and its parent's classLoader
attribute value.
Resource ClassLoader | Parent ClassLoader | ClassLoader Description |
---|---|---|
shared | shared | The useClasses value must be set to true so that the resource can access both its classes and the parent classes. |
instance | shared | The resource primarily needs its own classes, but it may be beneficial for useclasses to be set to true to so that the child can use parent classes. |
shared | instance | The resource uses only its own classloader. |
instance | instance | The resource uses only its own classloader. |