Red Hat Training

A Red Hat training course is available for Red Hat JBoss Operations Network

2. Writing Server-Side Plug-ins: Background

All JBoss ON plug-ins have a similar configuration and deployment style, with minor differences in what is required for the plug-ins to access the systems. Server-side plug-ins refer to any plug-in which accesses the core JBoss ON server to perform its actions; essentially, these are global plug-ins used for the central server behavior.

2.1. An Intro to Server-Side Plug-ins

Server-side plug-ins extend the functionality of the JBoss ON server. JBoss ON comes with several categories of server-side plug-ins already:
  • Alert sender plug-ins for methods to send alert notifications for resources
  • Bundle plug-ins for deploying files and application
  • Drift plug-ins for monitoring resource or filesystem configuration and files
  • Content plug-ins for managing resource configurations
  • Generic plug-ins for everything else
Server-side plug-ins are not limited to those three categories; the server-side plug-in framework allows substantial access to the server itself. Server-side plug-ins can be used to run remote scripts in response to monitoring events or to provision systems in a custom work flow — anything that is within the purview of the JBoss ON server.
This is a much more casual approach to implementing plug-ins than the more structured, formal agent plug-in system. This allows much more latitude in what plug-in developers are able to accomplish.

Important

All server-side plug-ins have full access to the server's stateless session beans (SLSBs). This allows a lot of latitude and versatility in the functionality of server-side plug-ins and allows access to any server subsystem. However, this also makes server-side plug-ins extremely powerful. Be cautious in writing and deploying server-side plug-ins.
Server-side plug-ins have a different framework for writing and deploying plug-ins than the framework for agent plug-ins. Here are some general bits of information that are useful as you begin writing server-side plug-ins:
  • Once the server-side plug-in is built and deployed, the plug-in is a JAR file with a META-INF/ directory which contains the rhq-serverplugin.xml plug-in descriptor.
  • Each plug-in is independent of every other plug-in. Unlike agent plug-ins, server-side plug-ins do not interact with each other. There are no plug-in dependencies for server-side plug-ins.
Server-side plug-ins are organized according to their type, and the type corresponds to the subsystem or functional area which the plug-in extends. Each type of plug-in is contained within a defined plug-in container.
Server-side plug-ins are managed in the JBoss ON server within a plug-in container that relates to the function of the plug-in, and the plug-in container handles general tasks like starting and stopping plug-ins and providing general configuration settings for that type of plug-in. (All plug-in containers are, themselves, members of a single master plug-in container.)
Server-Side Plug-in Containers

Figure 2. Server-Side Plug-in Containers

There is only one plug-in container for each type of plug-in, but there can be an unlimited number of server-side plug-ins within each plug-in container.

Note

A plug-in container defines what type a plug-in is. A plug-in, then, can only be in one plug-in container because it can only be of one type.
Table 1, “Available Plug-in Containers” summarizes the available plug-in containers with JBoss ON.

Table 1. Available Plug-in Containers

Plug-in Type Description Container Name
Generic Catch-all type for any custom plug-ins. This type of plug-in only interacts with the plug-in container for the container to start and stop the plug-in and to initialize and shutdown the plug-in libraries. Generic Plugin
Alert methods Defines an alert notification method, or the way that an alert is sent. AlertHandler
Bundle Defines and processes a type of bundle. This type of plug-in performs tasks that the core server needs to process and manage bundles of specific bundle types, such as Ant recipes or file-based bundles. Each bundle server plug-in knows about and can process a single bundle type. Bundle Plugin
Drift Processes drift operations and configuration. This stores and retrieves content (files) being managed for drift detection and remediation. Drift JPA Plugin
Content Contains metadata for a a repository or a group of repositories. PackageSource
Repository (also Package) Defines a content repository. Plug-ins can define a single repository,which is then used for provisioning, entitlements, and updates for JBoss ON-managed resources. ChannelSource

Note

New plug-in containers cannot be created without rebuilding JBoss ON, because the plug-in containers are part of the core JBoss ON code. Rather than defining a new plug-in type, use the generic plug-in container, since this provides full access to the server functionality, anyway.

2.2. The Breakdown of Server-Side Plug-in Configuration

JBoss ON plug-ins are packaged .jar files.The directory structure, libraries, and classes used by those .jar files is completely up to the discretion and requirements of the plug-in writer, with only one requirement: All plug-in .jar files must have a plug-in descriptor file, META-INF/rhq-serverplugin.xml.

Note

The one major guideline when writing plugins is that it should implement the org.rhq.enterprise.server.plugin.pc.ServerPluginComponent class. This controls the lifecycle of the plug-in within the container.
The server-side plug-in is defined within the JBoss ON server through three types of files:
  • An XML file which functions as the plug-in's descriptor
  • Java files which pull in the descriptor information and implement the classes for the plug-in.
  • Optional library dependencies. Any third-party libraries must be stored in the plug-in JAR file's lib/ directory.

2.2.1. Descriptor and Configuration

The plug-in descriptor is the mechanism that tells the plug-in container how the plug-in should be deployed, along with any additional information about the plug-in configuration and behavior. The plug-in descriptor is contained in an XML file which can use any default or user-defined tags and attributes to define that configuration.

Note

The XML file for the server-side plug-in is defined in the rhq-serverplugin.xml file in the META-INF/ directory in the plug-in's JAR file. (Default server-side plug-ins follow this same configuration.) This file is required.
The most important configuration in the plug-in descriptor is the basic definition for the plug-in which includes the type of plug-in, its name, and its version. Every plug-in has this basic definition. If the version number is not passed manually in the plug-in descriptor, then it is picked up automatically from the MANIFEST.MF file.
The key to server-side plug-ins is their flexibility. They have near absolute access to server functionality and can extend any of the existing functions of the server — monitoring, alerting, remote actions, provisioning, resource configuration, whatever. Maintaining this flexibility demands that server-side plug-ins at least have the option of advanced configuration in three general areas:
  • Scheduling actions periodically or using cron schedules
  • Setting global parameters for all instances of a specific plug-in type
  • Allowing local or instance-specific configuration for a plug-in type
2.2.1.1. Definitions and Classes
Each server-side plug-in has a root element that contains attributes for the name, display name, package, version, and other plug-in information. This also imports and defines the XML schema definitions used for the plug-in configuration (which is described in more detail in Section 2.2.2, “Schema Files”).

Example 1. Plug-in Descriptor: Definition

<alert-plugin
         name="alert-email"
         displayName="Alert:Email"
         xmlns="urn:xmlns:rhq-serverplugin.alert"
         xmlns:c="urn:xmlns:rhq-configuration"
         xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
         package="org.rhq.enterprise.server.plugins.alertEmail"
         description="Alert sender plugin that sends alert notifications via email"
         version="1.0"
         >
The second part of the plug-in configuration sets the components or classes to use with the plug-in. Every server-side plug-in will implement the org.rhq.enterprise.server.plugin.pc.ServerPluginComponent class, which provides simple lifecycle management for the plug-in. This component provides the hook for the container to initialize, start, stop, and shut down the plug-in. When a plug-in is initialized, it is given a server plug-in context that provides information about the runtime environment of the plug-in.
This component is a stateful object, remaining alive for as long as the plug-in is initialized. While this object is alive, the plug-in can perform any tasks or call any methods to do the work they need to do.
Developers have the option of invoking a component for the plug-in in one of two ways:
  • Using the <plugin-component> tag to specify the class (this is available to every type of plug-in)
  • Using a user-defined tag to identify the class (this is available to some types of server-side plug-ins, depending on the available schema for the plug-in container)
It's not required to use any given invocation method for a plug-in, so using something like <plugin-component> is optional. Whatever the method of invoking the component, only one plug-in component can be specified in the descriptor.

Example 2. Plug-in Descriptor: Class Info

<serverplugin:plugin-component class="MyLifecycleListener" />
Alternatively, a container-defined tag (like <plugin-class> for the email alert server-side plug-in) can be created for the plug-in. Creating a class introduces the option to provide configuration options or other information with the component.
<plugin-class>RolesSender</plugin-class>

Note

The example in Example 2, “Plug-in Descriptor: Class Info” is specific to certain type of server-side plug-in. Not all server-side plug-ins support that structure.
Some descriptor tags are made available through the schema defined for that plug-in type. That is the schema that is defined in the plug-in container schema files. In this example, the alert sender plug-in container supplies the <plugin-class> element for any alert sender plug-in to hook into the alert mechanism in JBoss ON.
Container-defined schema isn't ad hoc. It can't be dropped into just any plug-in file, and developers cannot define their own schema elements.
2.2.1.2. Control Operations
Sometimes a user need to interact directly with a server plug-in's stateful component. This interaction can take any number of forms, such retrieving a list of agents or resources in contact with the plug-in to testing the plug-in itself.
To allow user-defined controls, the ServerPluginComponent class can optionally implement the ControlFacet interface. These control operations can then be invoked directly in the JBoss ON web interface, in the plug-in configuration area.
Control operations are configured in the plug-in descriptor using the <control> element, which is a child to the <plugin-component> element. Controls are optional, so you don't have to specify any, or you can specify multiple controls. Each control can also have optional parameters for the user to pass to the control operation, as well as (optional) result properties.

Example 3. Control Operation Configuration

<serverplugin:plugin-component class="MyLifecycleListener">
   <serverplugin:control name="testControl" description="A test control operation">
      <serverplugin:parameters>
         <c:simple-property name="paramProp" required="true" description="Set to 'fail' to simulate an error"/>
      </serverplugin:parameters>
      <serverplugin:results>
         <c:simple-property name="resultProp" required="false"/>
      </serverplugin:results>
   </serverplugin:control>
</serverplugin:plugin-component>
Control operations can be used with any server-side plug-in type.
2.2.1.3. Scheduling Jobs
One of the main advantages of the server-side plug-in framework is the capability to define scheduled jobs for the plug-in. The plug-in container handles actually scheduling and invoking those jobs. The plug-in descriptor has the scheduling information which simply tells the plugin container what classes and methods should be invoked when the job is triggered, how often those jobs should be triggered, and what configuration settings to pass to the job method when it is invoked.
The job can perform any work it needs to get done when it is invoked, including accessing the plug-in's stateful component, as well as any information about the job itself through the ScheduledJobInvocationContext component.
Job configuration is entirely flexible:
  • A job class can be stateless (meaning each job class is instantiated for each job invocation) or it can be stateful by invoking the plug-in component instance.

    Note

    Any server-side plug-in can define a plug-in component to act as the lifecycle listener for the plug-in. Using a plug-in component is extremely useful; in fact, it is the only mechanism for a Generic server-side plug-in to connect with the core server.
  • A job can be concurrent, meaning more than one invocation can be performed at any one time on any number of servers (including on the same server). If a job is not concurrent, that means one and only one job invocation can be performed at any time. (If a job is not concurrent and is not clustered, then only one job invocation can be performed anywhere in the JBoss ON server cloud).
  • A job can be clustered, meaning the job can be run from any server in the JBoss ON server cloud. If a job is not clustered,  the job always runs on the machine where the job was scheduled. This works in conjunction with the concurrent setting.
  • The schedule can be either periodic (such as running every hour) or recurring on a pattern (such as every Monday at 5pm).
  • There can be multiple jobs scheduled for the same plug-in, each in its own <map-property> under the plug-in's <scheduled-jobs> entry.
Each scheduled job is a mapping entry that sets the name, schedule, frequency, methods, or classes invoked by the job, and any callback data.

Example 4. Plug-in Descriptor: Scheduled Jobs

<serverplugin:scheduled-jobs>
         <!-- notice that we use the map name as the methodName -->
         <c:map-property name="myScheduledJobMethod1">
             <c:simple-property name="enabled" type="boolean" required="true" default="true" summary="true" description="Whether or not the job should be scheduled"/>
             <c:simple-property name="scheduleType" type="string" required="true" default="cron" summary="true" description="Indicates when the schedule triggers">
                 <c:property-options>
                     <c:option value="periodic"/>
                     <c:option value="cron" default="true"/>
                 </c:property-options>
             </c:simple-property>
             <c:simple-property name="scheduleTrigger" type="string" required="true" default="0 0/5 * * * ?" summary="true" description="Based on the schedule type, this is either the period, in milliseconds, or the cron expression"/>
             <c:simple-property name="concurrent" type="boolean" required="false" default="false" summary="true" description="Whether or not the job can be run multiple times concurrently"/>
             <c:simple-property name="clustered" type="boolean" required="false" default="true" summary="true" description="Whether or not the job can be run anywhere in the JBoss ON server cluster, or if it must be run on the server where the job was schedule."/>
         </c:map-property>
</serverplugin:scheduled-jobs>
There is only one <scheduled-jobs> container entry. Each individual job is within this container, in mapping (<map-property>) entries.
2.2.1.3.1. States for Jobs
Server-side plug-ins can run one of two jobs: stateless or stateful. The only difference between a stateful job and a stateless job is whether the job specifies a class. If a plug-in does not specify a class, the plug-in job is stateful because it uses the plug-in component. If the job specifies a class, then the class is instantiated every time a new job starts, so the job is stateless.
At its simplest, a stateless job requires only a class and a method to call when the plug-in is started. For example:

Example 5. Stateless Job Configuration

<c:map-property name="statelessJob1" description="invokes a stateless job class but given a job context">
      <c:simple-property name="class" type="string" required="true" readOnly="true" default="MyScheduledJob" summary="true" />
      <c:simple-property name="methodName" type="string" required="true" readOnly="true" default="executeWithContext" summary="true" />
</c:map-property>
Aside from the class specified for stateless jobs, stateless and stateful jobs have similar configuration options. Both stateful and stateless jobs can take other optional parameters that help schedule the job. Scheduled jobs use the same configuration properties as other components in the plug-in, but scheduled jobs have a specialized semantics that require special properties to be defined to set create the job. Essentially, this is a property map for each job. These properties include:
  1. A method name for the job to invoke. For stateful jobs, the target method is in the plug-in component; for stateless jobs, it is in the class specified with the class property. Either way, the method name tells the server what to call. A default method is already defined in the plug-in component, and stateful jobs can call on that without having a specific method name property.
    <c:simple-property name="methodName" type="string" required="true" readOnly="true" default="executeWithContext" summary="true" />
    
    Any method must either have no arguments or have a single argument of the type ScheduledJobInvocationContext.
  2. A setting showing whether the job is enabled.
    <simple-property name="enabled" type="boolean" ... />
    
  3. A schedule type showing whether it's a periodic or cron job. The type of job is identified in the option which is set to true. For example:
    <simple-property name="scheduleType" ... default="periodic" ... >
          <c:property-options>
                <c:option value="periodic" default="true"/>
                <c:option value="cron" />
          </c:property-options>
    </c:simple-property>
    
  4. The actual schedule for when to run the job (the "trigger"), which can be a time period or a cron schedule. For a periodic job, this gives a time interval, in milliseconds:
    <simple-property name="scheduleTrigger" type="string" required="true" default="60000" ... />
    
    For a cron job, the default argument contains the full cron expression:
    <simple-property name="scheduleTrigger" type="string" required="true" default="0 0/5 * * * ?" ... />
    
    (A full description of the cron schedule format is at http://quartz.sourceforge.net/javadoc/org/quartz/CronTrigger.html.)
  5. A setting on whether the job is concurrent (meaning, whether this job can be running multiple times on more than one server or at the same time). If this is false, so that only one instance of the job can be running at a time, then even if multiple servers are scheduled to run the job, it will only run on one of them.
    <simple-property name="concurrent" type="boolean" ... />
    
  6. A job can allow a setting on whether it runs anywhere in the JBoss ON server cloud or if it must be run on the same machine where the job was scheduled. Setting the cluster value to true allows the job to be called from any server in the JBoss ON cloud, so the job is clustered. This value should be false if the job must be run on all machines on schedule. Since all plug-ins are registered on all servers automatically, a non-clustered job will run on each server, independently.
    <simple-property name="clustered" type="boolean" default="true" ... />
    
  7. A job can optionally contain custom strings which accept callback data.
    <simple-property name="custom1" type="boolean" required="true" default="true" summary="true" description="A custom boolean for callback data"/>
    
    Callback data can be of any type — boolean, string, long, or whatever else is appropriate for the job being performed.
  8. Stateless jobs have a property that passes the method name of the class. The method name can identify the class that is called in the plug-in component or, alternatively, it can call a class to instantiate when the job is invoked. Both the method and the class keys are shown in Example 5, “Stateless Job Configuration”. Whatever class is used as the target, it must have the method defined in the method name simple property.
    Typically, the class isn't specified because the job will target the stateful plug-in component. The class property allows the option of writing a stateless job, however.
2.2.1.3.2. Concurrent and Clustered Jobs
When a scheduled job is run is determined by its schedule (scheduleTrigger setting). Where and how a job is run is determined by two settings: concurrent and clustered.
Just because the scheduled time for a job arrives doesn't necessarily mean that a specific JBoss ON server should run it. The server has to determine which server should run the task, and this is given in the clustered setting. If the clustered setting is set to true, then any server in the JBoss ON server cloud can invoke the task; if it is set to false, then the task can only run on the server where it is scheduled.

Note

One thing about clustering is that while the job can run on any server in the JBoss ON server cloud, there is no way to predict or require which servers will run the job. Some machines might never run the job.
On the other hand, the JBoss ON server-side plug-ins are automatically propagated to all servers in the cloud when they are deployed. If clustering is turned off (meaning each job only runs from the local server), all JBoss ON servers will eventually run this job independent of when the other servers run the job. The end result is that you are guaranteed that all JBoss ON servers will run this job on a consistent schedule and may even run more than one of the jobs at the same time.
Once the JBoss ON server identifies where to run the task, then it must find out if the task is already running. If the concurrent setting is true, then the job is invoked every the schedule is triggered, even if the task is already running on another server (or even the same server). If concurrent is set to false and the job is already running somewhere in the JBoss ON server cloud, then the server must wait until that job invocation is complete before it can run the job.
The clustered and concurrent settings can play off each other in several ways.
If a job is clustered but not concurrent, then before the JBoss ON server can invoke a job, it has to check whether it is running anywhere else in the JBoss ON server cloud. If it is, then the server has to wait until that job completes before invoking the new job.
If the job is not clustered and not concurrent, then the JBoss ON server only checks the local machine to see if the job is running. If the job is not running locally, then the JBoss ON server can invoke the job, even if it is running on another server in the cloud because the job is not clustered.
Essentially, the clustered setting determines how strict the concurrency check should be. If clustered is false, the concurrency check is performed only on the machine where the job was scheduled; if clustered is true, the concurrency check is performed on all machines in the cluster.

Table 2. Comparison of Concurrent and Clustered Behavior

Concurrent Clustered When the schedule is triggered...
true true ... the job will always be invoked. It may be invoked on any server in the JBoss ON server cloud.
true false ... the job will always be invoked and will run on the server where the job is scheduled.
false true
... the JBoss ON server checks to see if this job is running anywhere else in the JBoss ON server cloud. If it is, the new job must wait until that old job has finished before being invoked.
Only one instance of this job can ever be running anywhere in the JBoss ON server cloud.
false false ... the scheduler checks to see if the job is already running locally before invoking the job. Only one job invocation may be running on the server at any time, but multiple servers in the cloud may be running the job at the same time.

Note

To guarantee that a job will run on all servers on a consistent schedule, set clustered to false. concurrent will determine if you are allowed to start a new job on a machine while an old job is still running on that machine.
To run a job somewhere, but not on any one specified JBoss ON server, set clustered to true. concurrent will determine if you are allowed to have more than one job running anywhere at any one time.
2.2.1.4. Plug-in Configuration (Both Global and Local)
Global configuration settings can be set for default values or global settings for every instance of that server-side plug-in. All of the global configuration parameters are contained within a <plugin-configuration> entry (defined in the standard JBoss ON schema) and then each parameter is identified with a <simple-property> item. Global settings are useful for any plug-in which accesses a single identity, such as alerts which use the same email or SNMP account.

Example 6. Plug-in Descriptor: Global Configuration

<serverplugin:plugin-configuration>
         <c:simple-property name="user" type="string" required="false"/>
         <c:simple-property name="password" type="password" required="false"/>
</serverplugin:plugin-configuration>
The same server-side plug-in can be created with multiple instances. These different instances are obviously going to require slightly different settings in order to fulfill different functions. For example, different instances of email alert senders should send notifications to different groups of sys admins.
These instance-specific configuration settings are identified in the plug-in descriptor through a configuration entry using schema specific to the server-side plug-in (such as <alert-configuration> and <simple-property> item).

Example 7. Plug-in Descriptor: Instance-Specific Configuration (Alerts)

<alert-configuration>
         <c:simple-property name="emailAddress" displayName="Receiver Email Address(es)" type="longString"
                 description="Email addresses (separated by comma) used for notifications."/>

h5. </alert-configuration>
Each plug-in container type defines its own set of schema, relevant to that type of plug-in. For example, GUI or perspectives have separate explicit schema elements for different types of UI elements.

Example 8. Plug-in Descriptor: Instance-Specific Configuration (Perspectives)

<perspectivePlugin
   description="The Core Perspective defining Core UI Elements"
   displayName="Core Perspective"
   name="CorePerspective"
   package="org.rhq.perspective.core"
   xmlns="urn:xmlns:rhq-serverplugin.perspective"
   xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">


<!-- Menu -->
<menuItem name="logo" displayName="" url="/" iconUrl="/images/JBossLogo_small.png">
   <position placement="firstChild" />
</menuItem>
Check the plug-in container schema in the sourceRoot/modules/enterprise/server/xml-schemas/src/main/resources directory to see what elements are available for the specific type of plug-in. Not all plug-in types accept local configuration settings; generic plug-ins, for example, only accept global plug-in configuration.

Note

The container schema is included with the RHQ source code, not the JBoss ON packages. To check out the code:
git clone http://git.fedorahosted.org/git/rhq/rhq.git
The example plug-ins are the sourceRoot/etc/samples/custom-serverplugin/ directory which can be used as a template for writing new plug-ins. Rather than checking out the entire source code, you can manually download the custom-serverplugin files at this URL:
http://git.fedorahosted.org/git/?p=rhq/rhq.git;a=tree;f=etc/samples/custom-serverplugin;hb=master

2.2.2. Schema Files

The server-side 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 the plug-in container type.
The descriptor file must conform to the elements within the plug-in types scheme. If the descriptor is improperly configured — such as missing required elements or attempting to use elements not defined in the plug-in container's schema — then the plug-in will fail to load.
Every plug-in — both agent plug-ins and server-side plug-ins — uses the rhq-configuration.xsd file. This file defines the basic configuration options available to any plug-in.
The schema in rhq-configuration.xsd file is extended by rhq-serverplugin.xsd. This file provides additional XML elements that are specific to the functions of server-side plug-ins. This file is referenced by every server-side plug-in.
The last XSD file used by a server-side plug-in is one that is specific to its plug-in container. The plug-in container schema files may define required elements for plug-ins of that type (as with alert sender plug-ins) or may not have any specific schema elements (as with generic plug-ins).
Specific server-side plug-in schema files are located in the sourceRoot/modules/enterprise/server/xml-schemas/src/main/resources directory.
This section takes a high-level look at the configuration elements and attributes that are associated with each XSD to give you enough familiarity with XSD in general and specifically the files with JBoss ON in order to help write server-side plug-ins and extend the schema as necessary.
More information about each XSD file is available through the comments (in <xs:annotation> items) in the XSD files themselves. For more information on XSD files and XML schema, check out a reference guide for XML and XSD, like http://www.w3.org/TR/xmlschema-0/.

Note

The JBoss ON XSD files are annotated with descriptions of each configuration area within the file.
2.2.2.1. Parsing the Plug-in Container Schema Files
All of the schema elements available and required for a specific type of server-side plug-in are defined in the schema for that type of plug-in container. There are two relevant elements configured in the XSD files:
  • Elements
  • Attributes

Note

For more detailed information on XML schema, check out a reference guide for XML and XSD, like http://www.w3.org/TR/xmlschema-0/.
Elements translate into available tags for the plug-ins XML file. For example:
<xs:element name="alert-plugin">
In the plug-in's XML file, that element defines the tag:
<alert-plugin>
Stuff
</alert-plugin>
Attributes are flags that available to the tags in the XML file. For example:
<xs:attribute name="name">
The attribute looks like this in the XML file:
<alert-plugin name="myAlertPlugin">
Stuff
</alert-plugin>
Elements and attributes are arranged hierarchically in the XSD file. The container element for the plug-in file is defined at the top of the XSD. Child elements reference the parent element's type and are included as sub-elements within the parent's definition. Likewise, any attributes that are available to an element are included within the element's definition.
One of the easiest ways to find the tags and attributes defined for a type of server-side plug-in is to check the plug-in container schema in the sourceRoot/modules/enterprise/server/xml-schemas/src/main/resources directory and search for <xs:element name=""> and <xs:attribute name=""> entries.

Note

The container schema is included with the RHQ source code, not the JBoss ON packages. To check out the code:
git clone http://git.fedorahosted.org/git/rhq/rhq.git
2.2.2.2. The rhq-configuration.xsd File
The rhq-configuration.xsd file provides schema which is available for all JBoss ON plug-ins. This is used by both agent and server-side plug-ins.
The rhq-configuration.xsd file is in source/modules/core/client-api/src/main/resources.

Note

The container schema is included with the RHQ source code, not the JBoss ON packages. To check out the code:
git clone http://git.fedorahosted.org/git/rhq/rhq.git
The example plug-ins are the sourceRoot/etc/samples/custom-serverplugin/ directory which can be used as a template for writing new plug-ins. Rather than checking out the entire source code, you can manually download the custom-serverplugin files at this URL:
http://git.fedorahosted.org/git/?p=rhq/rhq.git;a=tree;f=etc/samples/custom-serverplugin;hb=master
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>.

Table 3. rhq-configuration.xsd Schema Elements

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.

Table 4. rhq-configuration.xsd Schema Element 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.
There are many other elements and attributes set in the rhq-configuration.xsd file. Each one is described by the text in the <xs:annotation> tags for the item.
2.2.2.3. The rhq-serverplugin.xsd File
The rhq-serverplugin.xsd is the central server-side plug-in schema file.
The rhq-serverplugin.xsd file provides schema elements that are important for every server-side plug-in. Possibly the two most important elements are <server-plugin> (for the plug-in's root element) and <scheduled-jobs> (for running jobs on a resource or server).
The rhq-serverplugin.xsd file is in source/modules/enterprise/server/xml-schemas/src/main/resources.
The most common elements in the rhq-serverplugin.xsd file are listed in Table 5, “rhq-serverplugin.xsd Schema Elements”.

Table 5. rhq-serverplugin.xsd Schema Elements

Element Description
server-plugin Contains the root element for the plug-in descriptor.
help Contains additional usage information or other tips that can help users integrate the plug-in with other applications.
plugin-component Identifies a class that will be notified when the plug-in stops or starts. This is a stateful object and is the target of any scheduled stateful jobs.
scheduled-jobs Defines a schedule for the plug-in to execute any specified task
Most of the attributes defined within the rhq-serverplugin.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 server-side plug-ins.

Table 6. rhq-serverplugin.xsd Schema Element Attributes

Attribute Description
package For setting the plug-in package name.
version For setting the version of the plug-in. If the version isn't set in the descriptor, the plug-ins JAR file, META-INF/MANIFEST.MF, must define the version number in the Implementation-Version setting.
apiVersion For setting the version of the API used to write the plug-in.
There are many other elements and attributes set in the rhq-serverplugin.xsd file. Each one is described by the text in the <xs:annotation> tags for the item.

2.2.3. Java Class Files

Any Java class files used by the plug-in to implement elements like ServerPluginComponent or ControlFacet must be available in the JAR file for the plug-ins.

2.3. Anatomy of Alert Sender Server-Side Plug-ins

An alert notification sender is simply the method used to send an alert. Each sender is implemented through an alert sender plug-in. Multiple instances of the same type of plug-in can be configured with different settings; all the plug-in provides is the functionality of sending an alert in that way.
Alert senders are implemented as server-side plug-ins (with the same general configuration concepts as those covered in Section 2.2, “The Breakdown of Server-Side Plug-in Configuration”. The server-side plug-in framework allows the alert sender configuration to be easily extended through custom plug-ins or even by editing the configuration of the default server-side plug-ins.
This section deconstructs the elements of one of the default server-side plug-ins — the email alert sender — to make the process of creating an alert sender clear and simple.

2.3.1. Default Alert Senders

JBoss ON provides multiple alert sender plug-ins with the default installation, which cover some of the most common ways of sending an alert.

Table 7. Default Alert Senders

Alert Method Description Plug-in Name
Email Sends emails with the alert information to a user or list of users. alert-email
Roles Sends an internal message to a JBoss ON user role. alert-roles
SNMP Sends a notification to an SNMP trap. alert-snmp
Operations Initiated a JBoss ON-supported task on a target resource. alert-operations
Subject Sends a notification to a user in JBoss ON. alert-subject
Plug-in developers and administrators can create and deploy custom alert sender plug-ins to cover other scenarios or formats that are specific to an organization, such as additional instant messaging systems.

2.3.2. Breakdown of a Real Alert Sender Plug-in

As described in Section 2.2, “The Breakdown of Server-Side Plug-in Configuration”, any server-side plug-in uses three types of files for its configuration:
  • An XML plug-in descriptor that conforms to a given XML schema file (XSD)
  • Java files
The XML plug-in descriptor and the Java files are unique to every plug-in. All of the default alert senders, however, use the same three schema files to provide attributes for the descriptor.
Section 3.4, “Deploying Server-Side Plug-ins” covers the process for building and deploying plug-ins. This section annotates the elements of each of the configuration files used to define a default alert sender (alert-email) as an example of how to write an alert plug-in.
2.3.2.1. Descriptor
Every plug-in descriptor is a file called rhq-serverplugin.xml in the src/main/resources/META-INF/ file for that plug-in.

Note

The default alert schema has to be used with the plug-in descriptor for the alert plug-in validator to work and for the alert to tie into the monitoring system successfully.
The header in the plug-in descriptor pulls in the schema files to use with the plug-in and defines the package information (class, description, version number) for the plug-in. The displayName flag contains the name to give for the plug-in in the list of installed server-side plug-ins.
<alert-plugin
     name="alert-email"
     displayName="Alert:Email"
     xmlns="urn:xmlns:rhq-serverplugin.alert"
     xmlns:c="urn:xmlns:rhq-configuration"
     xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
     package="org.rhq.enterprise.server.plugins.alertEmail"
     description="Alert sender plugin that sends alert notifications via email"
>
The next section supplies help text for the alert.
<serverplugin:help>
     Used to send notifications to direct email addresses.
</serverplugin:help>
The help text is displayed in a help description section in the UI.
Alert Help Text

Figure 3. Alert Help Text

The next section in the descriptor is filler for the alert-email plug-in.
<!-- startup & tear down listener, + scheduled jobs
<serverplugin:plugin-component />
-->
For other types of server-side plug-ins, this area could contain scheduling information in a <scheduled-jobs> element or implement a Java class in a <plugin-component> element. There's no reason to schedule any jobs with an alert sender since the plug-ins don't perform tasks; they provide methods of sending message from the server when an event is detected.
The global preferences define parameters that apply to every single instance of the alert, meaning it applies to every notification which is configured to use that alert sender. These global configuration parameters can be configured in the XML file, but they can also be edited through the JBoss ON GUI, as described in Section 3.9, “Setting Plug-in Configuration Properties”.
For the alert-email plug-in, these parameters include the sender mail address to use for notifications, the mail server, and any login credentials.
<!-- Global preferences for all email alerts -->

<serverplugin:plugin-configuration>
     <c:simple-property name="mailserver" displayName="Mail server address" type="longString"
          description="Address of the mail server to use (if not the default JBoss ON one )"
          required="false"/>
     <c:simple-property name="senderEmail" displayName="Email of sender" type="string"
          description="Email of the account from which alert emails should come from"
          required="false"/>
     <c:simple-property name="needsLogin" displayName="Needs credentials?"
          description="Mark this field if the server needs credentials to send email and give them below" type="boolean"
          default="false"/>
     <c:simple-property name="user" type="string" required="false"/>
     <c:simple-property name="password" type="password" required="false"/>
</serverplugin:plugin-configuration>
If defaults are set, then there is a default value given in the configuration itself. The alert-email plug-in, however, doesn't have defaults set for any of its parameters, so the values for the plug-in configuration have to be added through the plug-in configuration page.
The <short-name> element is required for every alert sender plug-in. This gives the name that is used for the alert sender type in the notification area of the alert definition.
<!-- How does this sender show up in drop downs etc -->

<short-name>Email</short-name>
Since the <short-name> value is used in drop-down menus and other user-oriented areas, this value is much more human-friendly than the displayName value.
The next section gives the plug-in class used to send the alert notification. The component for server-side plug-ins is typically org.rhq.enterprise.server.plugins.pluginName, taken from the package element in the <plugin> element of the descriptor. For the alert-email plug-in, the full package name is org.rhq.enterprise.server.plugins.alertEmail, pointing to the EmailSender.java class.
 <!-- Class that does the actual sending -->

<plugin-class>EmailSender</plugin-class>
The last section in the alert-email descriptor provides the other half to the communication configuration. The global parameters set things that apply to every notification, like the mail server that the JBoss ON server used to send the email notification. The <alert-configuration> entry provides information that is configured individually, for every notification instance which uses that alert sender type. For alert-email, this is a field which allows a list of email addresses that will receive the emailed notifications.
 <!-- What can a user configure when defining an alert -->

<alert-configuration>
     <c:simple-property name="emailAddress" displayName="Receiver Email Address(es)" type="longString"
          description="Email addresses (separated by comma) used for notifications."/>
     </alert-configuration>
2.3.2.2. Java Resource
The first part of the Java file identifies the package name and imports whatever properties are required for that type of sender. For the email sender Java file, this includes configuration to pull in the alert send plug-in container, the notification templates, and other classes to define alerts.
package org.rhq.enterprise.server.plugins.alertEmail;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.alert.notification.SenderResult;
import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
import org.rhq.enterprise.server.util.LookupUtil;
The rest of the EmailSender.java file pulls data from the notification configuration and the plug-in's global configuration.
The opening sets up the sender.
public class EmailSender extends AlertSender {

    @Override
    public SenderResult send(Alert alert) {
        String emailAddressString = alertParameters.getSimpleValue("emailAddress", null);
        if (emailAddressString == null) {
            return SenderResult.getSimpleFailure("No email address given");
        }
The next lines pull in the email address to receive the notification from the notification configuration and the mail server to send the notification and the sender's email account from the global configuration.
        List<String> emails = AlertSender.unfence(emailAddressString, String.class, ",");
        try {
            Set<String> uniqueEmails = new HashSet<String>(emails);
            Collection<String> badEmails = LookupUtil.getAlertManager()
                .sendAlertNotificationEmails(alert, uniqueEmails);

            List<String> goodEmails = new ArrayList<String>(uniqueEmails);
            goodEmails.removeAll(badEmails);

            SenderResult result = new SenderResult();
            result.setSummary("Target addresses were: " + uniqueEmails);
            if (goodEmails.size() > 0) {
                result.addSuccessMessage("Successfully sent to: " + goodEmails);
            }
            if (badEmails.size() > 0) {
                result.addFailureMessage("Failed to send to: " + badEmails);
            }
            return result;
        } catch (Throwable t) {
            return SenderResult.getSimpleFailure("Error sending email notifications to " + emails + ", cause: "
                + t.getMessage());
        }

    }

    @Override
    public String previewConfiguration() {
        String emailAddressString = alertParameters.getSimpleValue("emailAddress", null);
        if (emailAddressString == null || emailAddressString.trim().length() == 0) {
            return "<empty>";
        }
        return emailAddressString;
    }
}
The last part configures the responses for the email alert plug-in, simple failure or success.
      catch (Exception e) {
         log.warn("Sending of email failed: " + e);
         return SenderResult.getSimpleFailure("Sending failed :" + e.getMessage());

      }
      return SenderResult.getSimpleSuccess("Send notification to " + txt + ", msg-id: " + status.getId());
   }
}
2.3.2.3. Schema Elements
The alert-email plug-in (as all of the default alert sender plug-ins) uses three schema files:
  • rhq-configuration.xsd, which is used by all JBoss ON plug-ins
  • rhq-serverplugin.xsd, which is used by all server-side plug-ins
  • rhq-serverplugin-alert.xsd, which is used by alert plug-ins
The schema in these files build on and expand each other.
The rhq-serverplugin-alert.xsd file is required for any alert sender plug-in. While additional schema files can be added to contain other elements, the alert schema already contains several very useful schema elements for the alert sender plug-ins.

Table 8. Useful Alert Schema Elements

Schema Element Description Parent Tag
alert-plugin The root element for a single alert plug-in definition. None.
short-name The display name for the plug-in, which is used in the UI. alert-plugin
plugin-class The class which implements the plug-in's functionality. alert-plugin
alert-configuration A (default) configuration element to display in the UI when the alert instance is configured. This includes general data like a username, password, URL, server name, or port. alert-plugin