| type=page |
| status=published |
| title=Extending the asadmin Utility |
| next=adding-monitoring-capabilities.html |
| prev=extending-the-admin-console.html |
| ~~~~~~ |
| |
| = Extending the asadmin Utility |
| |
| [[GSACG00004]][[ghmrd]] |
| |
| |
| [[extending-the-asadmin-utility]] |
| == Extending the `asadmin` Utility |
| |
| The `asadmin` utility is a command-line tool for configuring and |
| administering {productName}. Extending the `asadmin` utility enables |
| you to provide administrative interfaces for an add-on component that |
| are consistent with the interfaces of other {productName} components. |
| A user can run `asadmin` subcommands either from a command prompt or |
| from a script. For more information about the `asadmin` utility, see the |
| link:reference-manual/asadmin.html#GSRFM00263[`asadmin`(1M)] man page. |
| |
| The following topics are addressed here: |
| |
| * link:#ghpuj[About the Administrative Command Infrastructure of {productName}] |
| * link:#ghpwe[Adding an `asadmin` Subcommand] |
| * link:#ghpwa[Adding Parameters to an `asadmin` Subcommand] |
| * link:#gkygt[Making `asadmin` Subcommands Cluster-Aware] |
| * link:#ghptw[Adding Message Text Strings to an `asadmin` Subcommand] |
| * link:#ghpvn[Enabling an `asadmin` Subcommand to Run] |
| * link:#ghpvq[Setting the Context of an `asadmin` Subcommand] |
| * link:#ghpwn[Changing the Brand in the {productName} CLI] |
| * link:#ghmza[Examples of Extending the `asadmin` Utility] |
| * link:#gkzlq[Implementing Create, Delete, and List Commands Using |
| Annotations] |
| |
| [[ghpuj]][[GSACG00105]][[about-the-administrative-command-infrastructure-of-glassfish-server]] |
| |
| === About the Administrative Command Infrastructure of {productName} |
| |
| To enable multiple containers to be independently packaged and loaded, |
| the administrative command infrastructure of {productName} provides |
| the following features: |
| |
| * Location independence. Administration subcommands can be loaded from |
| any add-on component that is known to {productName}. |
| * Extensibility. Administrative subcommands that are available to |
| {productName} are discovered on demand and not obtained from a preset |
| list of subcommands. |
| * Support for the HK2 architecture. Subcommands can use injection to |
| express their dependencies, and extraction to provide results to a user. |
| For more information, see link:writing-hk2-components.html#ghmna[Writing |
| HK2 Components]. |
| |
| [[ghpwe]][[GSACG00107]][[adding-an-asadmin-subcommand]] |
| |
| === Adding an `asadmin` Subcommand |
| |
| An `asadmin` subcommand identifies the operation or task that a user is |
| to perform. Adding an `asadmin` subcommand enables the user to perform |
| these tasks and operations through the `asadmin` utility. |
| |
| The following topics are addressed here: |
| |
| * link:#ghrqj[Representing an `asadmin` Subcommand as a Java Class] |
| * link:#ghrpm[Specifying the Name of an `asadmin` Subcommand] |
| * link:#ghrng[Ensuring That an `AdminCommand` Implementation Is |
| Stateless] |
| * link:#ghrqx[Example of Adding an `asadmin` Subcommand] |
| |
| [[ghrqj]][[GSACG00194]][[representing-an-asadmin-subcommand-as-a-java-class]] |
| |
| ==== Representing an `asadmin` Subcommand as a Java Class |
| |
| Each `asadmin` subcommand that you are adding must be represented as a |
| Java class. To represent an `asadmin` subcommand as a Java class, write |
| a Java class that implements the `org.glassfish.api.admin.AdminCommand` |
| interface. Write one class for each subcommand that you are adding. Do |
| not represent multiple `asadmin` subcommands in a single class. |
| |
| Annotate the declaration of your implementations of the `AdminCommand` |
| interface with the `org.jvnet.hk2.annotations.Service` annotation. The |
| `@Service` annotation ensures that the following requirements for your |
| implementations are met: |
| |
| * The implementations are eligible for resource injection and resource extraction. |
| * The implementations are location independent, provided that the |
| component that contains them is made known to the {productName} runtime. |
| + |
| For information about how to make a component known to the {productName} runtime, see |
| link:packaging-integrating-delivering.html#ghmne[Integrating an Add-On Component With {productName}]. |
| |
| [[ghrpm]][[GSACG00195]][[specifying-the-name-of-an-asadmin-subcommand]] |
| |
| ==== Specifying the Name of an `asadmin` Subcommand |
| |
| To specify the name of the subcommand, set the `name` element of the |
| `@Service` annotation to the name. |
| |
| |
| [NOTE] |
| ==== |
| Subcommand names are case-sensitive. |
| ==== |
| |
| |
| Subcommands that are supplied in {productName} distributions |
| typically create, delete, and list objects of a particular type. For |
| consistency with the names of subcommands that are supplied in {productName} distributions, follow these conventions when specifying the name |
| of a subcommand: |
| |
| * For subcommands that create an object of a particular type, use the name `create-`object`.` |
| * For subcommands that delete an object of a particular type, use the name `delete-`object`.` |
| * For subcommands that list all objects of a particular type, use the name `list-`objects`.` |
| |
| For example, {productName} provides the following subcommands for |
| creating, deleting, and listing HTTP listeners: |
| |
| * `create-http-listener` |
| * `delete-http-listener` |
| * `list-http-listeners` |
| |
| You must also ensure that the name of your subcommand is unique. |
| To obtain a complete list of the names of all `asadmin` subcommands that |
| are installed, use the |
| link:reference-manual/list-commands.html#GSRFM00154[`list-commands`] subcommand. |
| For a complete list of `asadmin` subcommands that are supplied in |
| {productName} distributions, see the |
| link:reference-manual.html#GSRFM[{productName} Reference Manual]. |
| |
| [[ghrng]][[GSACG00196]][[ensuring-that-an-admincommand-implementation-is-stateless]] |
| |
| ==== Ensuring That an `AdminCommand` Implementation Is Stateless |
| |
| To enable multiple clients to run a subcommand simultaneously, ensure |
| that the implementation of the `AdminCommand` interface for the |
| subcommand is stateless. To ensure that the implementation of the |
| `AdminCommand` interface is stateless, annotate the declaration of your |
| implementation with the `org.jvnet.hk2.annotations.Scoped` annotation. |
| In the `@Scoped` annotation, set the scope as follows: |
| |
| * To instantiate the subcommand for each lookup, set the scope to `PerLookup.class`. |
| * To instantiate the subcommand only once for each session, set the scope to `Singleton`. |
| |
| [[ghrqx]][[GSACG00197]][[example-of-adding-an-asadmin-subcommand]] |
| |
| ==== Example of Adding an `asadmin` Subcommand |
| |
| [[GSACG00034]][[ghrqq]] |
| Example 4-1 Adding an `asadmin` Subcommand |
| |
| This example shows the declaration of the class `CreateMycontainer` that |
| represents an `asadmin` subcommand that is named `create-mycontainer`. |
| The subcommand is instantiated for each lookup. |
| |
| [source,java] |
| ---- |
| package com.example.mycontainer; |
| |
| import org.glassfish.api.admin.AdminCommand; |
| ... |
| import org.jvnet.hk2.annotations.Service; |
| ... |
| import org.jvnet.hk2.annotations.Scoped; |
| import org.jvnet.hk2.component.PerLookup; |
| |
| /** |
| * Sample subcommand |
| */ |
| @Service(name="create-mycontainer") |
| @Scoped(PerLookup.class) |
| public Class CreateMycontainer implements AdminCommand { |
| … |
| } |
| ---- |
| |
| [[ghpwa]][[GSACG00108]][[adding-parameters-to-an-asadmin-subcommand]] |
| |
| === Adding Parameters to an `asadmin` Subcommand |
| |
| The parameters of an `asadmin` subcommand are the options and operands |
| of the subcommand. |
| |
| * Options control how the `asadmin` utility performs a subcommand. |
| * Operands are the objects on which a subcommand acts. For example, the |
| operand of the link:reference-manual/start-domain.html#GSRFM00235[`start-domain`] subcommand is the domain |
| that is to be started. |
| |
| The following topics are addressed here: |
| |
| * link:#ghpvh[Representing a Parameter of an `asadmin` Subcommand] |
| * link:#ghptx[Identifying a Parameter of an `asadmin` Subcommand] |
| * link:#ghpxp[Specifying Whether a Parameter Is an Option or an Operand] |
| * link:#ghpxj[Specifying the Name of an Option] |
| * link:#ghpxl[Specifying the Acceptable Values of a Parameter] |
| * link:#ghrgt[Specifying the Default Value of a Parameter] |
| * link:#ghpuk[Specifying Whether a Parameter Is Required or Optional] |
| * link:#CDCFAJDG[Specifying Whether a Parameter Can Be Used Multiple |
| Times on the Command Line] |
| * link:#ghpxd[Example of Adding Parameters to an `asadmin` Subcommand] |
| |
| [[ghpvh]][[GSACG00198]][[representing-a-parameter-of-an-asadmin-subcommand]] |
| |
| ==== Representing a Parameter of an `asadmin` Subcommand |
| |
| Represent each parameter of a subcommand in your implementation as a |
| field or as the property of a JavaBeans specification setter method. Use |
| the property of a setter method for the following reasons: |
| |
| * To provide data encapsulation for the parameter |
| * To add code for validating the parameter before the property is set |
| |
| [[ghptx]][[GSACG00199]][[identifying-a-parameter-of-an-asadmin-subcommand]] |
| |
| ==== Identifying a Parameter of an `asadmin` Subcommand |
| |
| Identifying a parameter of an `asadmin` subcommand enables {productName} to perform the following operations at runtime on the parameter: |
| |
| * Validation. The {productName} determines whether all required |
| parameters are specified and returns an error if any required parameter |
| is omitted. |
| * Injection. Before the subcommand runs, the {productName} injects |
| each parameter into the required field or method before the subcommand |
| is run. |
| * Usage message generation. The {productName} uses reflection to |
| obtain the list of parameters for a subcommand and to generate the usage |
| message from this list. |
| * Localized string display. If the subcommand supports |
| internationalization and if localized strings are available, the |
| {productName} can automatically obtain the localized strings for a |
| subcommand and display them to the user. |
| |
| To identify a parameter of a subcommand, annotate the declaration of the |
| item that is associated with the parameter with the |
| `org.glassfish.api.Param` annotation. This item is either the field or |
| setter method that is associated with the parameter. |
| |
| To specify the properties of the parameter, use the elements of the |
| `@Param` annotation as explained in the sections that follow. |
| |
| [[ghpxp]][[GSACG00200]][[specifying-whether-a-parameter-is-an-option-or-an-operand]] |
| |
| ==== Specifying Whether a Parameter Is an Option or an Operand |
| |
| Whether a parameter is an option or an operand determines how a user |
| must specify the parameter when running the subcommand: |
| |
| * If the parameter is an option, the user must specify the option with |
| the parameter name. |
| * If the parameter is an operand, the user may omit the parameter name. |
| |
| To specify whether a parameter is an option or an operand, set the |
| `primary` element of the `@Param` annotation as follows: |
| |
| * If the parameter is an option, set the `primary` element to `false`. |
| This value is the default. |
| * If the parameter is an operand, set the `primary` element to `true`. |
| |
| [[ghpxj]][[GSACG00201]][[specifying-the-name-of-an-option]] |
| |
| ==== Specifying the Name of an Option |
| |
| The name of an option is the name that a user must type on the command |
| line to specify the option when running the subcommand. |
| |
| The name of each option that you add in your implementation of an |
| `asadmin` subcommand can have a long form and a short form. When running |
| the subcommand, the user specifies the long form and the short form as |
| follows: |
| |
| * The short form of an option name has a single dash (`-`) followed by a |
| single character. |
| * The long form of an option name has two dashes (`--`) followed by an |
| option word. |
| |
| For example, the short form and the long form of the name of the option |
| for specifying terse output are as follows: |
| |
| * Short form: `-m` |
| * Long form: `--monitor` |
| |
| |
| [NOTE] |
| ==== |
| Option names are case-sensitive. |
| ==== |
| |
| |
| [[ghpvy]][[GSACG00163]][[specifying-the-long-form-of-an-option-name]] |
| |
| ===== Specifying the Long Form of an Option Name |
| |
| To specify the long form of an option name, set the `name` element of |
| the `@Param` annotation to a string that specifies the name. If you do |
| not set this element, the default name depends on how you represent the |
| option. |
| |
| * If you represent the option as a field, the default name is the field |
| name. |
| * If you represent the option as the property of a JavaBeans |
| specification setter method, the default name is the property name from |
| the setter method name. For example, if the setter method `setPassword` |
| is associated with an option, the property name and the option name are |
| both `password`. |
| |
| [[sthref5]][[specifying-the-short-form-of-an-option-name]] |
| |
| ===== Specifying the Short Form of an Option Name |
| |
| [[ghpvi]] |
| |
| To specify the short form of an option name, set the `shortName` element |
| of the `@Param` annotation to a single character that specifies the |
| short form of the parameter. The user can specify this character instead |
| of the full parameter name, for example `-m` instead of `--monitor`. If |
| you do not set this element, the option has no short form. |
| |
| [[ghpxl]][[GSACG00202]][[specifying-the-acceptable-values-of-a-parameter]] |
| |
| ==== Specifying the Acceptable Values of a Parameter |
| |
| When a user runs the subcommand, the {productName} validates option |
| arguments and operands against the acceptable values that you specify in |
| your implementation. |
| |
| To specify the acceptable values of a parameter, set the |
| `acceptableValues` element of the `@Param` annotation to a string that |
| contains a comma-separated list of acceptable values. If you do not set |
| this element, any string of characters is acceptable. |
| |
| [[ghrgt]][[GSACG00203]][[specifying-the-default-value-of-a-parameter]] |
| |
| ==== Specifying the Default Value of a Parameter |
| |
| The default value of a parameter is the value that is applied if a user |
| omits the parameter when running the subcommand. |
| |
| To specify the default value of a parameter, set the `defaultValue` |
| element of the `@Param` annotation to a string that contains the default |
| value. You can also compute the default value dynamically by extending |
| the `ParamDefaultCalculator` class and setting the `defaultCalculator` |
| element of the `@Param` annotation to this class. If these elements are |
| not set, the parameter has no default value. |
| |
| [[ghpuk]][[GSACG00204]][[specifying-whether-a-parameter-is-required-or-optional]] |
| |
| ==== Specifying Whether a Parameter Is Required or Optional |
| |
| Whether a parameter is required or optional determines how a subcommand |
| responds if a user omits the parameter when running the subcommand: |
| |
| * If the parameter is required, the subcommand returns an error. |
| * If the parameter is optional, the subcommand runs successfully. |
| |
| To specify whether a parameter is optional or required, set the |
| `optional` element of the `@Param` annotation as follows: |
| |
| * If the parameter is required, set the `optional` element to `false`. |
| This value is the default. |
| * If the parameter is optional, set the `optional` element to `true`. |
| |
| [[CDCFAJDG]][[specifying-whether-a-parameter-can-be-used-multiple-times-on-the-command-line]] |
| |
| Specifying Whether a Parameter Can Be Used Multiple Times on the Command |
| ==== Line |
| |
| By default, each parameter can be used once on the command line. To use |
| the parameter multiple times, set the `multiple` element of the `@Param` |
| annotation to `true`. The type of the annotated parameter must be an |
| array. |
| |
| [[ghpxd]][[GSACG00205]][[example-of-adding-parameters-to-an-asadmin-subcommand]] |
| |
| ==== Example of Adding Parameters to an `asadmin` Subcommand |
| |
| [[GSACG00035]][[ghpuh]] |
| Example 4-2 Adding Parameters to an `asadmin` Subcommand |
| |
| This example shows the code for adding parameters to an `asadmin` |
| subcommand with the properties as shown in the table. |
| |
| |=== |
| |Name |Represented As |Acceptable Values |Default Value |Optional or |
| Required |Short Name |Option or Operand |
| |`--originator` |A field that is named `originator` |Any character |
| string |None defined |Required |None |Option |
| |
| |`--description` |A field that is named `mycontainerDescription` |Any |
| character string |None defined |Optional |None |Option |
| |
| |`--enabled` |A field that is named `enabled` |`true` or `false` |
| |`false` |Optional |None |Option |
| |
| |`--containername` |A field that is named `containername` |Any character |
| string |None defined |Required |None |Operand |
| |=== |
| |
| |
| [source,java] |
| ---- |
| ... |
| import org.glassfish.api.Param; |
| ... |
| { |
| //… |
| @Param |
| String originator; |
| |
| @Param(name="description", optional=true) |
| //… |
| String mycontainerDescription |
| |
| @Param (acceptableValues="true,false", defaultValue="false", optional=true) |
| String enabled |
| |
| @Param(primary=true) |
| String containername; |
| //… |
| } |
| ---- |
| |
| [[gkygt]][[GSACG00109]][[making-asadmin-subcommands-cluster-aware]] |
| |
| === Making `asadmin` Subcommands Cluster-Aware |
| |
| The {productName} `asadmin` command framework provides support for |
| making `asadmin` subcommands work properly in a clustered environment or |
| with standalone server instances. A command that changes a configuration |
| is first executed on the domain administration server (DAS) and then |
| executed on each of the server instances affected by the change. |
| Annotations provided by the framework determine the instances on which |
| the command should be replicated and executed. Commands that do not |
| change a configuration need not be executed on the DAS at all, but only |
| on the necessary instances. The framework provides support for |
| collecting the output from the instances and sending a report back to |
| the user. |
| |
| Subcommands in a multi-instance environment can accept a `--target` |
| option to specify the cluster or instance on which the command acts. |
| From within the command, the `Target` utility allows the command to |
| determine information about where it is running. For some commands, it |
| may be desirable to have a main command that runs on the DAS and |
| supplemental preprocessing or postprocessing commands that run on the |
| instances. |
| |
| The following topics are addressed here: |
| |
| * link:#gkyjk[Specifying Allowed Targets] |
| * link:#gkykm[The `Target` Utility] |
| * link:#gkyfv[Specifying `asadmin` Subcommand Execution] |
| * link:#gkyjs[Subcommand Preprocessing and Postprocessing] |
| * link:#gkyit[Running a Command from Another Command] |
| |
| [[gkyjk]][[GSACG00206]][[specifying-allowed-targets]] |
| |
| ==== Specifying Allowed Targets |
| |
| When you define a `--target` option by using the `@Param` annotation in |
| the `org.glassfish.api` package, possible targets are as follows: |
| |
| * `domain` — The entire domain |
| * `server` — The domain administration server, or DAS |
| * cluster — A homogeneous set of server instances that function as a |
| unit |
| * standalone instance — A server instance that isn't part of a cluster |
| * clustered instance — A server instance that is part of a cluster |
| * config — A configuration for a cluster or standalone server instance |
| |
| These possible targets are represented by the following `CommandTarget` |
| elements of the `@TargetType` annotation in the |
| `org.glassfish.config.support` package: |
| |
| * `CommandTarget.DOMAIN` |
| * `CommandTarget.DAS` |
| * `CommandTarget.CLUSTER` |
| * `CommandTarget.STANDALONE_SERVER` |
| * `CommandTarget.CLUSTERED_INSTANCE` |
| * `CommandTarget.CONFIG` |
| |
| By default, the allowed targets are `server` (the DAS), standalone |
| server instances, clusters, and configurations. Not specifying a |
| `@TargetType` annotation is equivalent to specifying the following |
| `@TargetType` annotation: |
| |
| [source,java] |
| ---- |
| @TargetType(CommandTarget.DAS,CommandTarget.STANDALONE_SERVER,CommandTarget.CLUSTER,CommandTarget.CONFIG) |
| ---- |
| |
| Subcommands that support other combinations of targets must specify |
| `@TargetType` annotations. For example, the `create-http-lb` subcommand |
| supports only standalone server instance and cluster targets. Its |
| `@TargetType` annotation is as follows: |
| |
| [source,java] |
| ---- |
| @TargetType(CommandTarget.STANDALONE_SERVER,CommandTarget.CLUSTER) |
| ---- |
| |
| Most subcommands do not act on server instances that are part of a |
| cluster. This ensures that all server instances in a cluster remain |
| synchronized. Thus, the `CommandTarget.CLUSTERED_INSTANCE` element of |
| the `@TargetType` annotation is rarely used. |
| |
| An example exception is the `enable` subcommand. To perform a rolling |
| upgrade of an application deployed to a cluster, you must be able to |
| enable the new application (which automatically disables the old) on one |
| clustered instance at a time. The `@TargetType` annotation for the |
| `enable` subcommand is as follows, all on one line: |
| |
| [source,java] |
| ---- |
| @TargetType(CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, |
| CommandTarget.CLUSTERED_INSTANCE) |
| ---- |
| |
| Note that the `CommandTarget.CLUSTERED_INSTANCE` element is specified. |
| |
| The target name specified in the command line is injected into the |
| subcommand implementation if the following annotation is present: |
| |
| [source,java] |
| ---- |
| @Param(optional=true,defaultValue=SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME) |
| String target; |
| ---- |
| |
| [[gkykm]][[GSACG00207]][[the-target-utility]] |
| |
| ==== The `Target` Utility |
| |
| The `Target` utility is a service, present in the `internal-api` module, |
| `org.glassfish.internal.api` package, which a command implementation can |
| obtain by using the following annotation: |
| |
| [source,java] |
| ---- |
| @Inject Target targetUtil; |
| ---- |
| |
| You can use this utility to avoid writing boiler plate code for actions |
| such as getting the list of server instances for a cluster or checking |
| if a server instance is part of a cluster. For example, here is an |
| example of using the utility to obtain the configuration for a target |
| cluster or server instance: |
| |
| [source,java] |
| ---- |
| Config c = targetUtil.getConfig(target); |
| ---- |
| |
| The `Target` utility is packaged in the |
| as-install``/modules/internal-api.jar`` file. Its methods are documented |
| with comments. |
| |
| [[gkyfv]][[GSACG00208]][[specifying-asadmin-subcommand-execution]] |
| |
| ==== Specifying `asadmin` Subcommand Execution |
| |
| By default, all `asadmin` subcommands are automatically replicated and |
| run on the DAS and all {productName} instances specified in the |
| `--target` option. To run a subcommand only on the DAS, use the |
| following `@ExecuteOn` annotation in the `org.glassfish.api.admin` package: |
| |
| [source,java] |
| ---- |
| @ExecuteOn(RuntimeType.DAS) |
| ---- |
| |
| The `stop-domain` subcommand and subcommands that list information are |
| examples of subcommands that execute only on the DAS. |
| |
| To run a subcommand only on applicable server instances, use the |
| following `@ExecuteOn` annotation: |
| |
| [source,java] |
| ---- |
| @ExecuteOn(RuntimeType.INSTANCE) |
| ---- |
| |
| Not specifying an `@ExecuteOn` annotation is equivalent to specifying |
| the following `@ExecuteOn` annotation: |
| |
| [source,java] |
| ---- |
| @ExecuteOn(RuntimeType.DAS,RuntimeType.INSTANCE) |
| ---- |
| |
| In addition to `RuntimeType`, you can specify the following additional |
| elements with the `@ExecuteOn` annotation: |
| |
| * `ifFailure` — By default, if errors occur during execution of a |
| subcommand on a server instance, command execution is considered to have |
| failed and further execution is stopped. However, you can choose to |
| ignore the failure or warn the user rather than stopping further command |
| execution. Specify the `ifFailure` element and set it to |
| `FailurePolicy.Ignore` or `FailurePolicy.Warn`. For example: |
| + |
| [source,java] |
| ---- |
| @ExecuteOn(value={RuntimeType.DAS}, ifFailure=FailurePolicy.Warn) |
| ---- |
| * `ifOffline` — By default, if a server instance is found to be offline |
| during the command replication process, command execution is considered |
| to have failed and further execution is stopped. However, you can choose |
| to ignore the failure or warn the user rather than stopping further |
| command execution. Specify the `ifOffline` element and set it to |
| `FailurePolicy.Ignore` or `FailurePolicy.Warn`. For example: |
| + |
| [source,java] |
| ---- |
| @ExecuteOn(value={RuntimeType.DAS}, ifOffline=FailurePolicy.Ignore) |
| ---- |
| |
| [[gkyjs]][[GSACG00209]][[subcommand-preprocessing-and-postprocessing]] |
| |
| ==== Subcommand Preprocessing and Postprocessing |
| |
| Some `asadmin` subcommands may require preprocessing or postprocessing. |
| For example, after an application is deployed to the DAS, references are |
| created in all applicable server instances, which synchronize with the |
| DAS. As another example, Message Queue or load balancer settings may |
| have to be reconfigured whenever a server instance is added to a |
| cluster. |
| |
| For such cases, the command replication framework provides the |
| `@Supplemental` annotation (in the `org.glassfish.api.admin` package). |
| An implementation must use the `value` element of the `@Supplemental` |
| annotation to express the supplemented command. This value is the name |
| of the command as defined by the supplemented command's `@Service` |
| annotation (in the `org.jvnet.hk2.annotations` package). |
| |
| For example, the `deploy` subcommand requires postprocessing. The |
| deployment command implementation looks like this: |
| |
| [source,java] |
| ---- |
| @Service(name="deploy") |
| @ExecuteOn(RuntimeType.DAS) |
| public DeployCommand implements AdminCommand { |
| // Do Actual Deployment |
| } |
| ---- |
| |
| A supplemental command that is run after every successful deployment |
| looks like this: |
| |
| [source,java] |
| ---- |
| @Service(name="DeploymentSupplementalCommand") |
| @Supplemental("deploy") |
| @ExecuteOn(RuntimeType.INSTANCE) |
| public DeploymentSupplementalCommand implements AdminCommand { |
| // Do logic that happens after deployment has been done |
| } |
| ---- |
| |
| As another example, a subcommand to create a local server instance might |
| look like this: |
| |
| [source,java] |
| ---- |
| @Service(name = "create-local-instance") |
| @Scoped(PerLookup.class) |
| public final class CreateLocalInstanceCommand implements AdminCommand { |
| // Do local instance creation |
| } |
| ---- |
| |
| A supplemental command to change Message Queue or load balancer settings |
| after local instance creation might look like this: |
| |
| [source,java] |
| ---- |
| @Service(name="CreateLocalInstanceSupplementalCommand") |
| @Supplemental("create-local-instance") |
| public CreateLocalInstanceSupplementalCommand implements AdminCommand { |
| // Change MQ/LB properties here |
| } |
| ---- |
| |
| A supplemental command implements AdminCommand, thus it can use the |
| `@Param` annotation and expect the corresponding `asadmin` command |
| parameters to be injected at runtime. The parameter values available for |
| injection are the same ones provided for the original command with which |
| the supplemental command is associated. For example, the |
| `DeploymentSupplementalCommand` has access to the parameter values |
| available to the `DeployCommand` invocation. |
| |
| An `asadmin` subcommand can be supplemented with multiple supplemental |
| commands. In this case, all supplemental commands are run after |
| completion of the main command but without any guarantee of the order in |
| which they run. |
| |
| To specify that a supplemental command is run before the main command, |
| set the `on` element of the `@Supplemental` annotation to |
| `Supplemental.Timing.Before`. For example: |
| |
| [source,java] |
| ---- |
| @Supplemental(value="mycommand", on=Supplemental.Timing.Before) |
| ---- |
| |
| Supplemental commands can use the `@ExecuteOn` annotation as described |
| in link:#gkyfv[Specifying `asadmin` Subcommand Execution]. |
| |
| [[gkyit]][[GSACG00210]][[running-a-command-from-another-command]] |
| |
| ==== Running a Command from Another Command |
| |
| An `asadmin` subcommand or supplemental command might need to run |
| another subcommand. For example, a subcommand running on the DAS might |
| need to run a different subcommand on one or more server instances. Such |
| invocations might use the `ClusterExecutor` class (in the |
| `org.glassfish.api.admin` package), which accepts a `ParameterMap`, to |
| pass parameters and their values to the invoked command. |
| |
| The `ParameterMapExtractor` utility is a service, present in the |
| `common-util` module, `org.glassfish.common.util.admin` package, which |
| creates a new `ParameterMap` populated using the parameters and values |
| of another `AdminCommand` that has already been injected. |
| |
| To list parameter names you want excluded from the `ParameterMap`, pass |
| the following: |
| |
| [source,java] |
| ---- |
| Set<String> |
| ---- |
| |
| This is optional. |
| |
| [[ghptw]][[GSACG00110]][[adding-message-text-strings-to-an-asadmin-subcommand]] |
| |
| === Adding Message Text Strings to an `asadmin` Subcommand |
| |
| A message text string provides useful information to the user about an |
| `asadmin` subcommand or a parameter. |
| |
| To provide internationalization support for the text string of a |
| subcommand or parameter, annotate the declaration of the subcommand or |
| parameter with the `org.glassfish.api.I18n` annotation. The `@I18n` |
| annotation identifies the resource from the resource bundle that is |
| associated with your implementation. |
| |
| To add message text strings to an `asadmin` subcommand, create a plain |
| text file that is named `LocalStrings.properties` to contain the |
| strings. Define each string on a separate line of the file as follows: |
| |
| [source] |
| ---- |
| key=string |
| ---- |
| |
| key:: |
| A key that maps the string to a subcommand or a parameter. The format |
| to use for key depends on the target to which the key applies and |
| whether the target is annotated with the `@I18n` annotation. See the |
| following table. |
| + |
| [width="100%",cols="<36%,<64%",options="header",] |
| |=== |
| |Target |Format |
| |Subcommand or parameter with the `@I18n` annotation |
| |`subcommand-name.command.resource-name` |
| |
| |Subcommand without the `@I18n` annotation |
| |`subcommand-name.command` |
| |
| |Parameter without the `@I18n` annotation |
| |`subcommand-name.command.param-name` |
| |=== |
| + |
| The replaceable parts of these formats are as follows: |
| + |
| subcommand-name;; |
| The name of the subcommand. |
| resource-name;; |
| The name of the resource that is specified in the`@I18n` annotation. |
| param-name;; |
| The name of the parameter. |
| string:: |
| A string without quotes that contains the text of the message. |
| |
| |
| [NOTE] |
| ==== |
| To display the message strings to users, you must provide code in your |
| implementation of the `execute` method to display the text. For more |
| information about implementing the `execute` method, see |
| link:#ghpvn[Enabling an `asadmin` Subcommand to Run]. |
| ==== |
| |
| [[GSACG00036]][[ghpvm]] |
| Example 4-3 Adding Message Strings to an `asadmin` Subcommand |
| |
| This example shows the code for adding message strings to the |
| `create-mycontainer` subcommand as follows: |
| |
| * The `create-mycontainer` subcommand is associated with the message |
| `Creates a custom container`. No internationalization support is |
| provided for this message. |
| * The `--originator` parameter is associated with the message |
| `The originator of the container`. No internationalization support is |
| provided for this message. |
| * The `--description` parameter is associated with the message that is |
| contained in the resource `mydesc`, for which internationalization is |
| provided. This resource contains the message text |
| `A description of the container`. |
| * The `--enabled` parameter is associated with the message |
| `Whether the container is enabled or disabled`. |
| No internationalization support is provided for this message. |
| * The `--containername` parameter is associated with the message |
| `The container name`. No internationalization support is provided for this message. |
| |
| The addition of the parameters `originator`, `description`, `enabled` |
| and `containername` to the subcommand is shown in link:#ghpuh[Example 4-2]. |
| |
| [source,java] |
| ---- |
| package com.example.mycontainer; |
| |
| import org.glassfish.api.admin.AdminCommand; |
| import org.glassfish.api.I18n; |
| import org.glassfish.api.Param; |
| import org.jvnet.hk2.annotations.Service; |
| import org.jvnet.hk2.annotations.Scoped; |
| import org.jvnet.hk2.component.PerLookup; |
| //... |
| |
| /** |
| * Sample subcommand |
| */ |
| @Service(name="create-mycontainer") |
| @Scoped(PerLookup.class) |
| public Class CreateMycontainer implements AdminCommand { |
| |
| @Param |
| String originator; |
| |
| @Param(name="description", optional=true) |
| @I18n("mydesc") |
| String mycontainerDescription |
| |
| @Param (acceptableValues="true,false", defaultValue="false", optional=true) |
| String enabled |
| |
| @Param(primary=true) |
| String containername; |
| //... |
| } |
| ---- |
| |
| The following message text strings are defined in the file |
| `LocalStrings.properties` for use by the subcommand: |
| |
| [source] |
| ---- |
| create-mycontainer.command=Creates a custom container |
| create-mycontainer.command.originator=The originator of the container |
| create-mycontainer.command.mydesc=A description of the container |
| create-mycontainer.command.enabled=Whether the container is enabled or disabled |
| create-mycontainer.command.containername=The container name |
| ---- |
| |
| [[ghpvn]][[GSACG00111]][[enabling-an-asadmin-subcommand-to-run]] |
| |
| === Enabling an `asadmin` Subcommand to Run |
| |
| To enable an `asadmin` subcommand to run, implement the `execute` method |
| in your implementation of the `AdminCommand` interface. The declaration |
| of the `execute` method in your implementation must be as follows. |
| |
| [source,java] |
| ---- |
| public void execute(AdminCommandContext context); |
| ---- |
| |
| Pass each parameter of the subcommand as a property to your |
| implementation of the `execute` method. Set the key of the property to |
| the parameter name and set the value of the property to the parameter's |
| value. |
| |
| In the body of the `execute` method, provide the code for performing the |
| operation that the command was designed to perform. For examples, see |
| link:#ghrsi[Example 4-6] and link:#gkbdf[Example 4-7]. |
| |
| [[ghpvq]][[GSACG00112]][[setting-the-context-of-an-asadmin-subcommand]] |
| |
| === Setting the Context of an `asadmin` Subcommand |
| |
| The `org.glassfish.api.admin.AdminCommandContext` class provides the |
| following services to an `asadmin` subcommand: |
| |
| * Access to the parameters of the subcommand |
| * Logging |
| * Reporting |
| |
| To set the context of an `asadmin` subcommand, pass an |
| `AdminCommandContext` object to the `execute` method of your |
| implementation. |
| |
| [[ghpwn]][[GSACG00113]][[changing-the-brand-in-the-glassfish-server-cli]] |
| |
| === Changing the Brand in the {productName} CLI |
| |
| The brand in the {productName} command-line interface (CLI) consists |
| of the product name and release information that are displayed in the |
| following locations: |
| |
| * In the string that the link:reference-manual/version.html#GSRFM00261[`version`] subcommand displays |
| * In each entry in the `server.log` file |
| |
| If you are incorporating {productName} into a new product with an |
| external vendor's own brand name, change the brand in the {productName} CLI. |
| |
| To change the brand in the {productName} CLI, create an OSGi fragment |
| bundle that contains a plain text file that is named |
| `src/main/resources/BrandingVersion.properties`. |
| |
| In the `BrandingVersion.properties` file, define the following |
| keyword-value pairs: |
| |
| [source] |
| ---- |
| product_name=product-name |
| abbrev_product_name=abbrev-product-name |
| major_version=major-version |
| minor_version=minor-version |
| build_id=build-id |
| version_prefix=version-prefix |
| version_suffix=version-suffix |
| ---- |
| |
| Define each keyword-value pair on a separate line of the file. Each |
| value is a text string without quotes. |
| |
| The meaning of each keyword-value pair is as follows: |
| |
| `product_name=`product-name:: |
| Specifies the full product name without any release information, for |
| example, |
| `name="ProductNameFullPlain" content="{productName}"`. |
| `abbrev_product_name=`abbrev-product-name:: |
| Specifies an abbreviated form of the product name without any release |
| information, for example, |
| `name="ProductNamePlain" content="{productName}"`. |
| `major_version=`major-version:: |
| Returns the product major version, for example, `6` |
| `minor_version=`minor-version:: |
| Specifies the product minor version, for example, `0`. |
| `build_id=`build-id:: |
| Specifies the build version, for example, `build 17`. |
| `version_prefix=`version-prefix:: |
| Specifies a prefix for the product version, for example, `v`. |
| `version_suffix=`version-suffix:: |
| Specifies a suffix for the product version, for example, `Beta`. |
| |
| [[GSACG00037]][[ghrfh]] |
| Example 4-4 `BrandingVersion.properties` File for Changing the Brand in |
| the {productName} CLI |
| |
| This example shows the content of the `BrandingVersion.properties` for |
| defining the product name and release information of {productName} 6.0.0, build 17. The abbreviated product name is |
| `glassfish-server`. |
| |
| [source] |
| ---- |
| product_name=Eclipse GlassFish |
| abbrev_product_name=glassfish-server |
| major_version=6 |
| minor_version=0.0 |
| build_id=build 17 |
| ---- |
| |
| To enable the display of OEM-specific information, the following |
| properties might also be required: |
| |
| [source] |
| ---- |
| LEGAL_COPYRIGHT "Copyright 2020" |
| LEGAL_COMPANY_NAME "Eclipse Foundation" |
| LEGAL_RIGHTS "All rights reserved." |
| SIMPLE_COMPANY_NAME "Eclipse" |
| COMPANY_CONTACT_URL "http://www.glassfish.org" |
| PRODUCT_TRADEMARKS "GlassFish is a trademark of the Eclipse Foundation" |
| ---- |
| |
| [[ghmza]][[GSACG00114]][[examples-of-extending-the-asadmin-utility]] |
| |
| === Examples of Extending the `asadmin` Utility |
| |
| [[GSACG00038]][[ghrnt]] |
| Example 4-5 `asadmin` Subcommand With Empty `execute` Method |
| |
| This example shows a class that represents the `asadmin` subcommand |
| `create-mycontainer`. |
| |
| The usage statement for this subcommand is as follows: |
| |
| [source] |
| ---- |
| asadmin create-mycontainer --originator any-character-string |
| [--description any-character-string] |
| [--enabled {true|false}] any-character-string |
| ---- |
| |
| This subcommand uses injection to specify that a running domain is |
| required. |
| |
| [source,java] |
| ---- |
| package com.example.mycontainer; |
| |
| import org.glassfish.api.admin.AdminCommand; |
| import org.glassfish.api.admin.AdminCommandContext; |
| import org.glassfish.api.I18n; |
| import org.glassfish.api.Param; |
| import org.jvnet.hk2.annotations.Service; |
| import org.jvnet.hk2.annotations.Inject; |
| import org.jvnet.hk2.annotations.Scoped; |
| import org.jvnet.hk2.component.PerLookup; |
| |
| /** |
| * Sample subcommand |
| */ |
| @Service(name="create-mycontainer") |
| @Scoped(PerLookup.class) |
| public Class CreateMycontainer implements AdminCommand { |
| |
| @Inject |
| Domain domain; |
| |
| @Param |
| String originator; |
| |
| @Param(name="description", optional=true) |
| @I18n("mydesc") |
| String mycontainerDescription |
| |
| @Param (acceptableValues="true,false", defaultValue="false", optional=true) |
| String enabled |
| |
| @Param(primary=true) |
| String containername; |
| |
| /** |
| * Executes the subcommand with the subcommand parameters passed as Properties |
| * where the keys are the paramter names and the values the parameter values |
| * @param context information |
| */ |
| public void execute(AdminCommandContext context) { |
| // domain and originator are not null |
| // mycontainerDescription can be null. |
| } |
| } |
| ---- |
| |
| The following message text strings are defined in the file |
| `LocalStrings.properties` for use by the subcommand: |
| |
| [source] |
| ---- |
| create-mycontainer.command=Creates a custom container |
| create-mycontainer.command.originator=The originator of the container |
| create-mycontainer.command.mydesc=A description of the container |
| create-mycontainer.command.enabled=Whether the container is enabled or disabled |
| create-mycontainer.command.containername=The container name |
| ---- |
| |
| [[GSACG00039]][[ghrsi]] |
| Example 4-6 `asadmin` Subcommand for Retrieving and Displaying Information |
| |
| This example shows a class that represents the `asadmin` subcommand |
| `list-runtime-environment`. The subcommand determines the operating |
| system or runtime information for {productName}. |
| |
| The usage statement for this subcommand is as follows: |
| |
| [source] |
| ---- |
| asadmin list-runtime-environment{runtime|os} |
| ---- |
| [source,java] |
| ---- |
| package com.example.env.cli; |
| |
| import org.glassfish.api.admin.AdminCommand; |
| import org.glassfish.api.admin.AdminCommandContext; |
| import org.glassfish.api.ActionReport; |
| import org.glassfish.api.I18n; |
| import org.glassfish.api.ActionReport.ExitCode; |
| import org.glassfish.api.Param; |
| import org.jvnet.hk2.annotations.Service; |
| import org.jvnet.hk2.annotations.Inject; |
| import org.jvnet.hk2.annotations.Scoped; |
| import org.jvnet.hk2.component.PerLookup; |
| |
| import java.lang.management.ManagementFactory; |
| import java.lang.management.OperatingSystemMXBean; |
| import java.lang.management.RuntimeMXBean; |
| |
| /** |
| * Demos asadmin CLI extension |
| */ |
| @Service(name="list-runtime-environment") |
| @Scoped(PerLookup.class) |
| public class ListRuntimeEnvironmentCommand implements AdminCommand { |
| |
| // this value can be either runtime or os for our demo |
| @Param(primary=true) |
| String inParam; |
| |
| public void execute(AdminCommandContext context) { |
| |
| ActionReport report = context.getActionReport(); |
| report.setActionExitCode(ExitCode.SUCCESS); |
| |
| // If the inParam is 'os' then this subcommand returns operating system |
| // info and if the inParam is 'runtime' then it returns runtime info. |
| // Both of the above are based on mxbeans. |
| |
| if ("os".equals(inParam)) { |
| OperatingSystemMXBean osmb = ManagementFactory.getOperatingSystemMXBean(); |
| report.setMessage("Your machine operating system name = " + osmb.getName()); |
| } else if ("runtime".equals(inParam)) { |
| RuntimeMXBean rtmb = ManagementFactory.getRuntimeMXBean(); |
| report.setMessage("Your JVM name = " + rtmb.getVmName()); |
| } else { |
| report.setActionExitCode(ExitCode.FAILURE); |
| report.setMessage("operand should be either 'os' or 'runtime'"); |
| } |
| } |
| } |
| ---- |
| |
| [[GSACG00040]][[gkbdf]] |
| Example 4-7 `asadmin` Subcommand for Updating Configuration Data |
| |
| This example shows a class that represents the `asadmin` subcommand |
| `configure-greeter-container`. The subcommand performs a transaction to |
| update configuration data for a container component. For more |
| information about such transactions, see |
| link:adding-configuration-data.html#gjrcz[Creating a Transaction to |
| Update Configuration Data]. |
| |
| The usage statement for this subcommand is as follows: |
| |
| [source] |
| ---- |
| asadmin configure-greeter-container --instances instances [--language language] [--style style] |
| ---- |
| |
| The acceptable values and default value of each option of the subcommand |
| are shown in the following table. The table also indicates whether each |
| option is optional or required. |
| |
| [width="100%",cols="<25%,<25%,<25%,<25%",options="header",] |
| |=== |
| |Option |Acceptable Values |Default value |Optional or Required |
| |`--instances` |An integer in the range 1-10 |5 |Required |
| |`--language` |`english`, `norsk`, or `francais` |`norsk` |Optional |
| |`--style` |`formal`, `casual`, or `expansive` |`formal` |Optional |
| |=== |
| |
| |
| Code for the container component is shown in |
| link:adding-container-capabilities.html#gkane[Example of Adding Container |
| Capabilities]. |
| |
| Code that defines the configuration data for the container component is |
| shown in link:adding-configuration-data.html#gkaal[Examples of Adding |
| Configuration Data for a Component]. |
| |
| [source,java] |
| ---- |
| package org.glassfish.examples.extension.greeter.config; |
| |
| import org.glassfish.api.admin.AdminCommand; |
| import org.glassfish.api.admin.AdminCommandContext; |
| import org.glassfish.api.Param; |
| import org.jvnet.hk2.annotations.Service; |
| import org.jvnet.hk2.annotations.Inject; |
| import org.jvnet.hk2.config.Transactions; |
| import org.jvnet.hk2.config.ConfigSupport; |
| import org.jvnet.hk2.config.SingleConfigCode; |
| import org.jvnet.hk2.config.TransactionFailure; |
| |
| import java.beans.PropertyVetoException; |
| |
| @Service(name = "configure-greeter-container") |
| public class ConfigureGreeterContainerCommand implements AdminCommand { |
| |
| @Param(acceptableValues = "1,2,3,4,5,6,7,8,9,10", defaultValue = "5") |
| String instances; |
| @Param(acceptableValues = "english,norsk,francais", defaultValue = "norsk", |
| optional = true) |
| String language; |
| @Param(acceptableValues = "formal,casual,expansive", defaultValue = "formal", |
| optional = true) |
| String style; |
| @Inject |
| GreeterContainerConfig config; |
| |
| public void execute(AdminCommandContext adminCommandContext) { |
| try { |
| ConfigSupport.apply(new SingleConfigCode<GreeterContainerConfig>() { |
| |
| public Object run(GreeterContainerConfig greeterContainerConfig) |
| throws PropertyVetoException, TransactionFailure { |
| greeterContainerConfig.setNumberOfInstances(instances); |
| greeterContainerConfig.setLanguage(language); |
| greeterContainerConfig.setStyle(style); |
| return null; |
| } |
| }, config); |
| } catch (TransactionFailure e) { |
| } |
| |
| } |
| } |
| ---- |
| |
| [[gkzlq]][[GSACG00115]][[implementing-create-delete-and-list-commands-using-annotations]] |
| |
| === 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, {productName} |
| 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: |
| |
| * link:#gkzkc[Command Patterns] |
| * link:#gkzle[Resolvers] |
| * link:#gkzoy[The `@Create` Annotation] |
| * link:#gkzoo[The `@Delete` Annotation] |
| * link:#gkzpl[The `@Listing` Annotation] |
| * link:#gkznf[Create Command Decorators] |
| * link:#gkznx[Delete Command Decorators] |
| * link:#gkzmu[Specifying Command Execution] |
| * link:#gkznd[Using Multiple Command Annotations] |
| |
| [[gkzkc]][[GSACG00211]][[command-patterns]] |
| |
| ==== 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: |
| + |
| [source,java] |
| ---- |
| void setChild(ChildType child) |
| ---- |
| Used when there can be zero or one children of a single type associated |
| with one parent instance. |
| + |
| [source,java] |
| ---- |
| 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: |
| |
| * A way to resolve the identity of the parent instance. |
| * The type of the child instance. |
| * A mapping between command options and child attributes. |
| * The accessor method for adding the child to the parent. |
| |
| 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: |
| |
| * A way to resolve the identity of the child instance. |
| * The accessor method for deleting the child. |
| |
| List command pattern. The most basic list commands simply retrieve all |
| configuration object instances of a given type. |
| |
| [[gkzle]][[GSACG00212]][[resolvers]] |
| |
| ==== 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: |
| |
| [source,java] |
| ---- |
| 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: |
| |
| * `TargetBasedResolver` — Uses the `--target` option and the expected |
| return type to retrieve the configuration object instance. |
| * `TargetAndNameBasedResolver` — Uses the `--target` option to look up a |
| `Config` object and a name to retrieve one of the `Config` object's |
| children. |
| * `TypeAndNameResolver` — Uses the requested type and `asadmin` command |
| name operand to find the configuration object instance. This is useful |
| for a configuration that uses the `@Index` annotation, which registers |
| instances under names. |
| * `TypeResolver` — Uses the requested type to find the configuration |
| object instance. This is the default resolver. |
| |
| [[gkzoy]][[GSACG00213]][[the-create-annotation]] |
| |
| ==== The `@Create` Annotation |
| |
| By placing the `org.glassfish.config.support.Create` annotation on a |
| method, you provide the following information: |
| |
| * The `value` element of the `@Create` annotation is the name of the |
| `asadmin` subcommand that creates the configuration object. |
| * The method's class is the type of the parent. |
| * The method's return type or parameter type is the type of the child. |
| * The method is the accessor method that adds a child of the specified |
| type to the parent. |
| |
| The only additional information needed is the resolver to use. |
| |
| The following example specifies a `create-cluster` subcommand: |
| |
| [source,java] |
| ---- |
| @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. |
| |
| [[gkzoo]][[GSACG00214]][[the-delete-annotation]] |
| |
| ==== The `@Delete` Annotation |
| |
| By placing the `org.glassfish.config.support.Delete` annotation on a |
| method, you provide the following information: |
| |
| * The `value` element of the `@Delete` annotation is the name of the |
| `asadmin` subcommand that deletes the configuration object. |
| * The method's class is the type of the parent. |
| * The method's return type or parameter type is the type of the child. |
| * The method is the accessor method that deletes a child of the |
| specified type from the parent. |
| |
| The only additional information needed is the resolver to use. |
| |
| The following example specifies a `delete-cluster` subcommand: |
| |
| [source,java] |
| ---- |
| @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. |
| |
| [[gkzpl]][[GSACG00215]][[the-listing-annotation]] |
| |
| ==== The `@Listing` Annotation |
| |
| By placing the `org.glassfish.config.support.Listing` annotation on a |
| method, you provide the following information: |
| |
| * The `value` element of the `@Listing` annotation is the name of the |
| `asadmin` subcommand that lists the configuration objects. |
| * The method's class is the type of the parent. |
| * The method's return type is the type of the children to be listed. |
| * The method is always the following accessor method: |
| + |
| [source,java] |
| ---- |
| List<ChildType> getChildren() |
| ---- |
| |
| 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: |
| |
| [source,java] |
| ---- |
| @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(); |
| } |
| ---- |
| |
| [[gkznf]][[GSACG00216]][[create-command-decorators]] |
| |
| ==== 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: |
| |
| [source,java] |
| ---- |
| @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: |
| |
| [source,java] |
| ---- |
| @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: |
| |
| [source,java] |
| ---- |
| @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. |
| |
| [[gkznx]][[GSACG00217]][[delete-command-decorators]] |
| |
| ==== 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: |
| |
| [source,java] |
| ---- |
| /** |
| * 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: |
| |
| [source,java] |
| ---- |
| @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: |
| |
| [source,java] |
| ---- |
| @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. |
| |
| [[gkzmu]][[GSACG00218]][[specifying-command-execution]] |
| |
| ==== 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 |
| link:#gkyfv[Specifying `asadmin` Subcommand Execution]. |
| |
| To add an `@ExecuteOn` annotation to a `@Create` or `@Delete` |
| annotation, use the `cluster` element. For example: |
| |
| [source,java] |
| ---- |
| @Create(value="create-instance", resolver=TypeResolver.class, |
| decorator=Server.CreateDecorator.class, |
| cluster=@org.glassfish.api.admin.ExecuteOn(value=RuntimeType.DAS)) |
| ---- |
| |
| [[gkznd]][[GSACG00219]][[using-multiple-command-annotations]] |
| |
| ==== 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: |
| |
| [source,java] |
| ---- |
| @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: |
| |
| [source,java] |
| ---- |
| @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. |
| |