JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle GlassFish Server 3.1 Add-On Component Development Guide
search filter icon
search icon

Document Information

Preface

1.   Introduction to the Development Environment for GlassFish Server Add-On Components

2.  Writing HK2 Components

3.  Extending the Administration Console

4.  Extending the asadmin Utility

About the Administrative Command Infrastructure of GlassFish Server

Adding an asadmin Subcommand

Representing an asadmin Subcommand as a Java Class

Specifying the Name of an asadmin Subcommand

Ensuring That an AdminCommand Implementation Is Stateless

Example of Adding an asadmin Subcommand

Adding Parameters to an asadmin Subcommand

Representing a Parameter of an asadmin Subcommand

Identifying a Parameter of an asadmin Subcommand

Specifying Whether a Parameter Is an Option or an Operand

Specifying the Name of an Option

Specifying the Long Form of an Option Name

Specifying the Short Form of an Option Name

Specifying the Acceptable Values of a Parameter

Specifying the Default Value of a Parameter

Specifying Whether a Parameter Is Required or Optional

Example of Adding Parameters to an asadmin Subcommand

Making asadmin Subcommands Cluster-Aware

Specifying Allowed Targets

The Target Utility

Specifying asadmin Subcommand Execution

Subcommand Preprocessing and Postprocessing

Running a Command from Another Command

Adding Message Text Strings to an asadmin Subcommand

Enabling an asadmin Subcommand to Run

Setting the Context of an asadmin Subcommand

Changing the Brand in the GlassFish Server CLI

Examples of Extending the asadmin Utility

Implementing Create, Delete, and List Commands Using Annotations

Command Patterns

Resolvers

The @Create Annotation

The @Delete Annotation

The @Listing Annotation

Create Command Decorators

Delete Command Decorators

Specifying Command Execution

Using Multiple Command Annotations

5.  Adding Monitoring Capabilities

6.  Adding Configuration Data for a Component

7.  Adding Container Capabilities

8.  Creating a Session Persistence Module

9.  Packaging, Integrating, and Delivering an Add-On Component

A.  Integration Point Reference

Index

Implementing Create, Delete, and List Commands Using Annotations

Many asadmin subcommands simply create, delete, or list objects in the configuration. Such code is repetitive to write and error prone. To simplify the writing of these asadmin commands, GlassFish Server supports annotations that can create, delete, and list configuration objects from a command invocation. Unless attributes or properties are set to non-default values or extra actions are required, no writing of code is needed.

The following topics are addressed here:

Command Patterns

Create command pattern. The most basic create commands are implemented in the following pattern:

  1. Retrieve the parent configuration object instance to which the child will be added. For example, the parent could be a Clusters object and the child a Cluster object.

  2. Start a transaction on the parent instance.

  3. Create the child configuration object instance.

  4. Set the attributes and properties of the newly created child instance.

  5. Add the child to the parent using one of the following accessor methods:

    void setChild(ChildType child)

    Used when there can be zero or one children of a single type associated with one parent instance.

    List<ChildType> getChildren()

    Used when there can be zero or more children of a single type associated with one parent instance.

    You cannot retrieve a set of children of the same type from the same parent using two different accessor methods.

  6. Commit the transaction.

A generic create command implementation can do most of these tasks if the following information is provided:

Delete command pattern. The most basic delete commands are implemented in the following pattern:

  1. Retrieve the configuration object instance to be deleted.

  2. Start a transaction on the parent instance.

  3. Delete the child by removing it from the list or calling setXXX(null).

  4. Commit the transaction.

A generic delete command implementation can do most of these tasks if the following information is provided:

List command pattern. The most basic list commands simply retrieve all configuration object instances of a given type.

Resolvers

A resolver retrieves a configuration object instance of a particular type. For a create command, it retrieves the parent of the object to be created. For a delete command, it retrieves the object to be deleted. A resolver implements the CrudResolver interface:

package org.glassfish.config.support;

/**
 * A config resolver is responsible for finding the target object of a specified
 * type on which a creation command invocation will be processed.
 *
 * Implementation of these interfaces can be injected with the command invocation
 * parameters in order to determine which object should be returned
 */
@Contract
public interface CrudResolver {

    /**
     * Retrieves the existing configuration object a command invocation is 
     * intented to mutate.
     * @param context the command invocation context
     * @param type the type of the expected instance
     * @return the instance or null if not found 
     */
    <T extends ConfigBeanProxy> T resolve(AdminCommandContext context, Class<T> type);
}

Given an AdminCommandContext, plus injection with the asadmin command line parameters (or any other HK2 services if necessary), the resolver should be able to determine the particular configuration object on which to act.

The following resolvers are provided in the org.glassfish.config.support package:

The @Create Annotation

By placing the org.glassfish.config.support.Create annotation on a method, you provide the following information:

The only additional information needed is the resolver to use.

The following example specifies a create-cluster subcommand:

@Configured
public interface Clusters extends ConfigBeanProxy, Injectable {

     /**
      * Return the list of clusters currently configured
      *
      * @return list of {@link Cluster }
      */
    @Element
    @Create(value="create-cluster")
    public List<Cluster> getCluster();
}

Because there is only one instance of the parent type, Clusters, in the configuration, this example uses the default resolver to retrieve it. Therefore, no resolver needs to be specified.

The @Delete Annotation

By placing the org.glassfish.config.support.Delete annotation on a method, you provide the following information:

The only additional information needed is the resolver to use.

The following example specifies a delete-cluster subcommand:

@Configured
public interface Clusters extends ConfigBeanProxy, Injectable {

     /**
      * Return the list of clusters currently configured
      *
      * @return list of {@link Cluster }
      */
    @Element
    @Delete(value="delete-cluster", resolver=TypeAndNameResolver.class)
    public List<Cluster> getCluster();
}

The TypeAndNameResolver uses the child type and the name operand passed through the command line to retrieve the specific cluster instance to be deleted.

The @Listing Annotation

By placing the org.glassfish.config.support.Listing annotation on a method, you provide the following information:

The default resolver retrieves all of the children of the specified type. Therefore, no resolver needs to be specified for a list command.

The following example specifies a list-clusters subcommand:

@Configured
public interface Clusters extends ConfigBeanProxy, Injectable {

     /**
      * Return the list of clusters currently configured
      *
      * @return list of {@link Cluster }
      */
    @Element
    @Listing(value="list-clusters")
    public List<Cluster> getCluster();
}

Create Command Decorators

Most create commands must do more than create a single configuration object instance with default attribute values. For example, most create commands allow the user to specify non-default attribute values through command options. For another example, the create-cluster subcommand creates children of the Cluster object and copies a referenced Config object. A creation decorator provides the code necessary to perform such additional operations.

The interface that a creation decorator must implement is as follows:

@Scoped(PerLookup.class)
public interface CreationDecorator<T extends ConfigBeanProxy> {

    /**
     * The element instance has been created and added to the parent, it can be
     * customized. This method is called within a 
     * {@link org.jvnet.hk2.config.Transaction}
     * and instance is therefore a writeable view on the configuration component.
     *
     * @param context administration command context
     * @param instance newly created configuration element
     * @throws TransactionFailure if the transaction should be rollbacked
     * @throws PropertyVetoException if one of the listener of <T> is throwing 
     * a veto exception
     */
    public void decorate(AdminCommandContext context, T instance) 
        throws TransactionFailure, PropertyVetoException;

    /**
     * Default implementation of a decorator that does nothing.
     */
    @Service
    public class NoDecoration implements CreationDecorator<ConfigBeanProxy> {
        @Override
        public void decorate(AdminCommandContext context, ConfigBeanProxy instance) 
            throws TransactionFailure, PropertyVetoException {
            // do nothing
        }
    }
}

The CreationDecorator interface is in the org.glassfish.config.support package.

A @Create annotation specifies a creation decorator using a decorator element. For example:

@Configured
public interface Clusters extends ConfigBeanProxy, Injectable {

     /**
      * Return the list of clusters currently configured
      *
      * @return list of {@link Cluster }
      */
    @Element
    @Create(value="create-cluster", decorator=Cluster.Decorator.class)
    public List<Cluster> getCluster();
}

The @Create annotation is on a method of the parent class. However, the referenced creation decorator class is associated with the child class. For example:

@Configured
public interface Cluster extends ConfigBeanProxy, ... {

    ...

    @Service
    @Scoped(PerLookup.class)    
    class Decorator implements CreationDecorator<Cluster> {

        @Param(name="config", optional=true)
        String configRef=null;

        @Inject
        Domain domain;

        @Override
        public void decorate(AdminCommandContext context, final Cluster instance) 
                throws TransactionFailure, PropertyVetoException {

        ...

        }
    }
}

The decorator class can optionally be an inner class of the child class. You can inject command options using the @Param annotation. You can also inject HK2 services or configuration instances.

Delete Command Decorators

Some delete commands must do more than delete a single configuration object instance. For example, the delete-cluster subcommand deletes the referenced Config object if no other Cluster or Instance objects reference it. A deletion decorator provides the code necessary to perform such additional operations.

The interface that a deletion decorator must implement is as follows:

/**
 * A decorator for acting upon a configuration element deletion.
 *
 * @param <T> the deleted element parent type
 * @param <U> the deleted element
 */
@Scoped(PerLookup.class)
public interface DeletionDecorator<T extends ConfigBeanProxy, 
    U extends ConfigBeanProxy> {

    /**
     * notification of a configuration element of type U deletion.
     * 
     * Note that this notification is called within the boundaries of the
     * configuration transaction, therefore the parent instance is a
     * writable copy and further changes to the parent can be made without
     * enrolling it inside a transaction.
     *
     * @param context the command context to lead to the element deletion
     * @param parent the parent instance the element was removed from
     * @param child the deleted instance
     */
    public void decorate(AdminCommandContext context, T parent, U child);
}

The DeletionDecorator interface is in the org.glassfish.config.support package.

A @Delete annotation specifies a deletion decorator using a decorator element. For example:

@Configured
public interface Clusters extends ConfigBeanProxy, Injectable {

     /**
      * Return the list of clusters currently configured
      *
      * @return list of {@link Cluster }
      */
    @Element
    @Delete(value="delete-cluster", resolver= TypeAndNameResolver.class, 
        decorator=Cluster.DeleteDecorator.class)
    public List<Cluster> getCluster();
}

The @Delete annotation is on a method of the parent class. However, the referenced deletion decorator class is associated with the child class. For example:

@Configured
public interface Cluster extends ConfigBeanProxy, ... {

    ..
    @Service
    @Scoped(PerLookup.class)
    class DeleteDecorator implements DeletionDecorator<Clusters, Cluster> {
        ....
    }
}

The decorator class can optionally be an inner class of the child class. You can inject command options using the @Param annotation. You can also inject HK2 services or configuration instances.

Specifying Command Execution

Commands specified with the @Create, @Delete, and @Listing annotations can use the @ExecuteOn annotation. The @ExecuteOn annotation specifies whether the command runs on the DAS, on server instances, or both (the default). For more information, see Specifying asadmin Subcommand Execution.

To add an @ExecuteOn annotation to a @Create or @Delete annotation, use the cluster element. For example:

@Create(value="create-instance", resolver=TypeResolver.class,
        decorator=Server.CreateDecorator.class,
        cluster=@org.glassfish.api.admin.ExecuteOn(value=RuntimeType.DAS))

Using Multiple Command Annotations

You can specify multiple command annotations on the same method. The following example combines create, delete, and list commands for clusters:

@Configured
public interface Clusters extends ConfigBeanProxy, Injectable {

     /**
      * Return the list of clusters currently configured
      *
      * @return list of {@link Cluster }
      */
    @Element
    @Create(value="create-cluster", decorator=Cluster.Decorator.class)
    @Delete(value="delete-cluster", resolver= TypeAndNameResolver.class, 
        decorator=Cluster.DeleteDecorator.class)
    @Listing(value="list-clusters")
    public List<Cluster> getCluster();
}

You can also specify multiple create or delete command annotations for the same configuration object type using the @Creates or @Deletes annotation (both in the org.glassfish.config.support package). For example:

@Element
@Creates(
   @Create(value="create-something", decorator=CreateSomething.Decorator)
   @Create(value="create-something-else", decorator=CreateSomethingElse.Decorator)
   List<Something> getSomethings();
)

These commands create configuration object instances of the same type. Differences in the decorators and resolvers can produce differences in the options each command takes. The @Param annotated attributes of the created type define a superset of options for both commands.