Brian Stansberry [
http://community.jboss.org/people/brian.stansberry] modified the
document:
"Adding an Operation Handler for an AS 7 Subsystem"
To view the document, visit:
http://community.jboss.org/docs/DOC-16655
--------------------------------------------------------------
This article is a quick description of the steps needed to add a new handler to an AS7
subsystem for handling a management operation.
This is as of the AS 7.0.0.Beta1 release. Developers are encouraged to look at the latest
code as a better source for understanding the process. Looking at the handlers in the
org.jboss.as.web package in the AS 7 source tree's web/ module is a good approach.
h3. Handling the Operation
1) The handler must implement the org.jboss.as.controller.OperationHandler interface or
one of its subinterfaces.
2) Handlers that need to read or write the persistent management model (i.e. ones that
don't solely deal with their subsystem's runtime services) must implement one of
the following marker interfaces:
* ModelQueryOperationHandler -- for handlers that only read the persistent management
model
* ModelAddOperationHandler -- for handlers that add a new +addressable resource+ to the
model. (Inserting an attribute value for an existing resource is different.) Typically all
handlers that implement this interface would be for an operation named "add".
* ModelRemoveOperationHandler -- for handlers that remove a +addressable resource+ from
the model+.+ (Removing an attribute value for an existing resource to is different.)
Typically all handlers that implement this interface would be for an operation named
"remove".
* ModelUpdateOperationHandler -- for handlers that update existing resources in the
persistent management model.
(Note: these marker interfaces may be replaced with a diferent mechanism for providing
this information before AS 7.0.0.CR1)
3) Handlers are encouraged to perform some validation on the parameters contained in the
passed in operation ModelNode. See the org.jboss.as.controller.operations.validation
package for some general purpose helpers. If any parameter is invalid, the handler should
throw OperationFailedException. OFE is the preferred exception for pretty much any failure
condition.
4) If the handler needs to read or write the persistent management model, they can get a
reference to the portion of the model indicated by the operation's address by calling
context.getSubModel() on the passed in OperationContext.
5) If the operation doesn't throw an exception but the effect of the operation can be
reversed via another operation, the operation should create a ModelNode that represents
that "compensating operation" (E.g. an operation that sets an attribute to a new
value would create a ModelNode that represents an operation to set the attribute back to
the old value.) Pass this compensating operation out by calling
return new BasicOperationResult(compensatingOperation)
If there is no valid compensating operation (e.g. for a read-only operation) then
return new BasicOperationResult();
6) Handlers that seek to alter the runtime state are encouraged to do so asynchronously
(i.e. after the call to OperationHandler.execute() returns . This is done by calling
context.getRuntimeContext() on the passed in OperationContext.
* If that method returns null, the controller that called the handler has determined that
it's currently inappropriate to execute runtime operations. The handler should not
attempt to alter runtime state.
* Otherwise, the handler should create an object that implements the
org.jboss.as.controller.RuntimeTask interface. This typical idiom is to create an
anonymous inner class inside the OperationHandler.execute() method. This RuntimeTask
should be passed to the calling context via a call to
context.getRuntimeContext().setRuntimeTask(theTask)
The ModelController that called OperationHandler.execute() will ensure that either the
runtime task is run or the changes made by the handler to the model are discarded.
The RuntimeTask *must* ensure that one (and only one) of the following methods is invoked
on the passed in RuntimeHandler:
* handleResultComplete() -- if the runtime task is able to perform its changes
successfully
* handleResultFailed(ModelNode failureDescription) -- if some problem occurs. The
failureDescription should describe the problem.
The RuntimeTask need not invoke the ResultHandler directly. A common idiom is to install
or remove an MSC Service in the RuntimeTask and to add a listener that invokes the
RuntimeHandler when the service is started, stopped or fails. See
ResultHandler.ServiceStartListener and ResultHandler.ServiceRemoveListener for
ready-to-use listener implementations.
When the RuntimeTask executes, it is provided a RuntimeTaskContext from which it can get
access to an MSC ServiceTarget and ServiceRegistry.
7) All handlers *must* do one (and only one) of the following in the execute method:
* Throw an exception (preferably OperationFailedException)
* On the passed in ResultHandler, invoke resultHandler.handleResultComplete()
* Register a RuntimeTask as described in 6) above.
8) Handlers must be thread safe. The handler can assume that any object passed in is
thread safe (including the model made available via OperationContext.getSubModel()).
h3. Describing the Operation
All operations except "write-attribute" handlers (see below) must have a
description that management API callers can access. The description is registered with the
core management system along with the OperationHandler (see "Registering the
Operation" below). The description must come from an implementation of the
org.jboss.as.controller.descriptions.DescriptionProvider interface.
It is recommended that the handler implement the
org.jboss.as.controller.descriptions.DescriptionProvider interface. When the
OperationHandler implementation is registered, a DescriptionProvider impl must be
registered with it, and having the same class implement both interfaces works well.
See
http://community.jboss.org/docs/DOC-16317 http://community.jboss.org/docs/DOC-16317
for details on what the DescriptionProvider should return.
All free-form text output from a DescriptionProvider must be externalized into a
ResourceBundle.
It is strongly encouraged that DescriptionProvider implementations have minimal code, and
instead invoke a static method in a separate utility class. A typical idiom is to call
that utility class XYZSubsystemDescriptions. The goal here is to improve boot time
performance by not loading all the often-verbose code needed to generate description when
the DescriptionProvider implemenation is loaded. Instead the code is loaded when the
DescriptionProvider is invoked, which in many cases (e.g. embedded testing) will never
occur.
h3. Handlers for the "write-attribute" Operation
The system includes a special operation called "write-attribute". This operation
exists for every resource and takes two single parameters:
* name -- the name of the attribute that is being written
* value -- the new value of the attribute
This operation is logically equivalent to a JMX setAttribute call.
Calls to "write-attribute" will only be accepted for attributes that have had an
OperationHandler registered (see below). The handler must know how to access the
"name" and "value" parameters.
There is no need to write a DescriptionProvider to associate with the OperationHandler for
a "write-attribute" operation.
h3. Registering the Operation
Your OperationHandler will only be invoked if the core management system knows about it.
This is done by registering the handler as part of the subsystem's implementation of
the org.jboss.as.controller.Extension interface, in the implementation of the
Extension.initialize(ExtensionContext context) method.
Assume that the resource to which your operation applies had been registered as follows:
public void initialize(ExtensionContext context) {
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME);
final ModelNodeRegistration resource =
subsystem.registerSubsystemModel(getTheRootResourceDescription());
If your OperationHandler is a handler for the "write-attribute" operation, e.g.
for the "foo" attribute, it would generally be registered as follows:
resource.registerReadWriteAttribute("foo", null, handler,
AttributeAccess.Storage.CONFIGURATION);
The second parameter is usually null. It could be an OperationHandler that is able to
handle the "read-attribute" operation for the "foo" attribute. If
null, a default handler is used that reads the current attribute value from the persistent
configuration model.
The final parameter is either AttributeAccess.Storage.CONFIGURATION or
AttributeAccess.Storage.RUNTIME. This indicates where the attribute value is stored.
CONFIGURATION means it is stored in the persistent configuration; RUNTIME means it is
stored in runtime memory only and the value will be lost on server restart.
For all other operations, the OperationHandler is registered as follows:
resource.registerOperationHandler("my-operation-name", handler,
descriptionProvider);
where "my-operation-name" is the name of the operation the end user would invoke
to trigger your handler.
A common idiom is to have the same class implement OperationHandler and
DescriptionProvider, to make that class a singleton, and to declare the operation name as
a constant on the handler class:
resource.registerOperationHandler(MyHandler.OPERATION_NAME, MyHandler.INSTANCE,
MyHandler.INSTANCE);
There are some overloaded variants of ModelNodeRegistration.registerOperationHandler()
that may be useful in some unusual situations. See the javadoc.
--------------------------------------------------------------
Comment by going to Community
[
http://community.jboss.org/docs/DOC-16655]
Create a new document in JBoss AS7 Development at Community
[
http://community.jboss.org/choose-container!input.jspa?contentType=102&am...]