内容


IBM WebSphere 开发者技术期刊

WebSphere Application Server 的管理命令框架编程指南

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: IBM WebSphere 开发者技术期刊

敬请期待该系列的后续内容。

此内容是该系列的一部分:IBM WebSphere 开发者技术期刊

敬请期待该系列的后续内容。

摘自 IBM WebSphere 开发者技术期刊

引言

WebSphere Application Server 命令框架为开发执行 WebSphere Application Server 管理任务的命令以及执行该命令提供了概念和逻辑上的结构。命令框架基于命令模式概念;命令模式将请求转换为命令对象,该命令对象封装请求数据,之后,通过传递命令对象可以在各种执行环境中执行它。

WebSphere 命令框架可让开发人员为普通的但很复杂的管理任务(如配置和应用程序管理服务功能、JMX MBean 的执行等)实现最终用户更友好和面向高级任务的命令。命令框架还提供基本的命令管理功能,如命令注册、命令列表和其他功能。

WebSphere 命令框架基础结构将命令逻辑从命令执行环境中分离开。此分离为各种命令执行环境中的命令用户和命令提供程序提供了一致的编程模式。图 1 演示了高级命令执行流程。

图 1. 高级命令执行流程
图 1. 高级命令执行流程
图 1. 高级命令执行流程

在与命令框架一起使用时,有两种常见的使用场景:

  • 使用 wsadmin 脚本工具

    WebSphere 命令框架可以扩展 wsadmin 功能,而无需进行任何其他 wsadmin 开发。wsadmin 工具查询可用的管理命令,并自动地将它们表现为 wsadmin $AdminTask 命令。当您以交互模式执行任务命令时,系统将指导您执行一系列的步骤,以交互方式收集复杂管理任务的输入。

  • 通过应用程序开发

    应用程序开发人员还可以利用现有的管理命令,以便在应用程序内部提供管理功能。

编程接口概念

命令框架适应两种类型的命令:

  • 管理命令——获取一定数量的输入参数,并执行该命令。
  • 任务命令——由零个或多个步骤组成,除任务参数外,每个步骤还拥有自己的参数。

每个命令都在命令定义文件中定义,该文件包含以下各部分:

命令提供程序:

  • 命令组
    • 命令
  • 命令
    • 参数
  • 任务命令
    • 参数
    • 步骤
      • 参数
  • 任务命令扩展
    • 步骤
      • 参数
  • 命令组扩展
    • 名称
    • 命令

命令定义文件包含一个或多个命令提供程序,每个命令提供程序都可以拥有一个或多个命令组。每个命令组都可以拥有一个或多个命令(管理或任务类型,或同时拥有这两种类型)。管理命令拥有零个或多个参数。任务命令拥有零个或多个参数和零个或多个步骤。每个步骤拥有零个或多个参数。命令提供程序还可以包括由另一个命令提供程序提供的任务命令的扩展任务命令扩展包含添加到现有命令的其他步骤。

下面提供了有关上述每个命令定义文件元素的详细信息:

命令

管理命令

在命令框架中,AdminCommand 接口是所有命令的基础。它定义方法(如参数 listing/setting/getting)、验证和命令执行。在命令框架中,AbstractAdminCommand 实现 AdminCommand 接口。所有的命令都应该扩展 AbstractAdminCommand 类。

  • CommandMetaData

    CommandMetaData 定义每个命令的属性。表 1 显示了常用于 CommandMetaData 的属性。

    表 1. CommandMetaData
    属性名称描述类型缺省值必需
    Version命令实现的版本。string--false
    Priority命令的优先级。如果多个命令具有相同的名称,则较高优先级的命令定义会覆盖较低优先的命令定义。int-- false
    supportLocalModesupportLocalMode 标志指示命令是否以本地模式工作。只有任务中的每个步骤都支持本地模式,TaskCommand 才能够支持本地模式。booleantruefalse
    isTargetObjectRequiredisTargetObjectRequired 标志指示是否必须为命令设置目标对象。booleantruefalse
    targetObjectType目标对象的类型。仅支持字符串和 javax.management.ObjectName。string-- false
    targetObjectConfigType与目标对象对应的完全限定配置类型。int--false
  • ParameterMetadata

    每个命令都可以拥有参数。如果需要参数,那么提供程序需要在 commandMetadata 下定义 parameterMetadata。

    表 2. ParameterMetadata
    属性名称描述类型缺省值必需
    Type命令参数的完全限定类名称。string-- true
    required参数值是否必需。booleanfalsefalse
    configAttribute如果参数直接映射到配置属性。String-- false
    defaultValue此参数的缺省值。命令框架自动将字符串值转换为适当类型的值。String-- false
    readonly参数是否为只读。将缺省值设置为参数值。提供程序还可以在命令实现中设置该值。booleanfalse false
    keyField是否使用参数来标识行。如果参数在命令或非表步骤上,则忽略此标志。booleanfalsefalse

任务命令

TaskCommand 使提供程序能够使用多个步骤构造复杂的管理命令。

  • 命令步骤

    多个步骤组成一个任务命令。命令步骤类似于管理命令;不过,命令步骤可以单独执行。

  • CommandStepMetadata

    CommandStepMetadata 扩展 commandMetadataData。除 commandMetadataData 中定义的元数据外,commandStepMetadta 还定义以下内容:

    表 3. CommandStepMetadata
    属性名称描述类型缺省值必需
    isTable标志指示步骤参数数据是否为表。booleanfalsefalse
    enableAddRows标志指示步骤是否允许用户添加或删除行。当步骤不是表时,忽略此标志。booleanfalse false
  • TaskCommandExtension

    通过添加附加步骤或覆盖现有步骤,可以扩展每个任务。不需要在同一 admin-command-def.xml 文件内部定义任务扩展步骤。它们可以存在于独立包中的独立 admin-command-def.xml 中,只要命令框架运行时能够找到就行。

    表 4. TaskCommandExtension
    属性名称描述类型缺省值必需
    名称要扩展的任务命令的名称。string-- false
    baseTaskCommand基本任务命令的名称。如果指定它,则使用其他功能创建继承基本命令所有接口和功能的新任务命令。string--false
    loadSequence此任务命令扩展的序列。序列号命令将优先于具有相同名称的命令。string-- false
    steps扩展步骤。CommandStepMetadata-- true

CommandGroup

CommandGroup 组合相关的管理命令。命令提供程序可以确定将哪些命令放在一个组中。通常,将具有相似功能的命令组合在一起。

  • CommandGroupMetadata

    CommandgroupMetadata 定义命令组中要包括的命令。

    表 5. CommandGroupMetadata
    属性名称描述类型缺省值必需
    Commands属于此命令组的命令名称。列表--true
  • CommandGroupExtension

    CommandGroupExtension 指定名称属性中的命令组名称和命令属性中的命令名称列表。命令提供程序可以指定多个 CommandGroupExtension 项,以便在各种命令组中添加命令。

    表 6. CommandGroupExtension
    属性名称描述类型缺省值必需
    name要扩展的命令组名称。string-- true
    Commands属于此命令组的命令名称。列表--true

命令提供程序

命令提供程序提供实际的命令实现,并且还为提供程序实现的所有命令指定属性。

  • CommandProviderMetadata

    在命令定义中,CommandProviderMetadata 是顶级元素。所有的命令、组和扩展都在此元素之下。

    表 7. CommandProviderMetadata
    属性名称描述类型缺省值必需
    implClass实现列出的命令的完全限定类名称。string--true
    resourceBundle消息的完全限定资源绑定名称string--true
    commandGroups命令组定义metadata--false
    Commands命令定义metadata--false
    taskCommands任务命令定义metadata--false
    commandGroupExts命令组扩展定义metadata--false
    taskCommandExts任务命令扩展定义metadata--false

创建命令

实现新命令包括以下常见步骤:

  1. 创建描述命令元数据的命令定义文件。
    命令定义文件基于 XML,其名称为 admin-command-def.xml,必须存在于包含命令提供程序和命令实现的 JAR 文件的 META-INF 目录中。此 JAR 文件必须位于需要执行命令的程序的类路径中。

  2. 创建命令提供程序。
    命令提供程序提供一个或多个命令。命令提供程序应该实现一些方法,以创建和加载由该提供程序提供的命令。命令提供程序应该实现 com.ibm.websphere.management.cmdframework.provider.CommandProvider 中指定的接口。

  3. 创建执行命令的逻辑。
    为执行该命令而开发的代码将取决于命令类型:AdminCommand 或 TaskCommand。

在接下来的各个部分中,将介绍实现两种类型的命令和包装命令提供程序、命令和命令定义文件的详细示例:

  1. 管理命令的命令实现
  2. 任务命令的命令实现
  3. 包装命令实现

1. 管理命令的命令实现

  1. 创建管理命令定义
  2. 创建管理命令提供程序
  3. 创建管理命令

1a.创建管理命令定义

假设我们需要创建显示“Hello World”的管理命令。我们可以按照以下所示创建命令定义文件:

清单 1
<Metadata xmlns="commandmetadata.xsd">
   <commandProvider implClass="HelloWorldProvider">
      <commandGroups name="HelloWorld">
         <commands>helloWorld</commands>
      </commandGroups>
      <commands name="helloWorld" 
            description="Hello World command" title="Hello World Command">
         <targetObjectAllowed>false</targetObjectAllowed>
      </commands>
   </commandProvider>
</Metadata>

在清单 1 中,有一个命令提供程序。implClass 属性定义实现在其块中指定的命令的提供程序。在此示例中,有一个命令组 (HelloWorld) 和一个命令 (helloWorld)。注意,命令名以小写字母开头。所有命令应该遵守此约定。另外,当使用 wsadmin 以交互模式执行命令时,提供命令的描述和标题非常有用,因为这些值会显示给最终用户。注意,应该将 targetObjectAllowed 属性设置为 false。在缺省情况下,它设置为 true,这需要指定 targetObjectType。因为此命令不需要传递任何目标对象,所以我们应该将其设置为 false。

添加参数

上面的命令不带有任何输入参数。现在,让我们尝试将一些参数添加到 HelloWorld 命令,以便它可以处理输入参数(如个人名称、拥有的宠物和其他属性),并显示该信息以及 Hello World 消息。

清单 2
<commands name="helloWorld" description="Hello World command" 
      title="Hello World Command">
   <targetObjectAllowed>false</targetObjectAllowed>
   <parameters name="personName" description="Name of person" 
         title="Name of Person">
      <type>String</type>
      <required>false</required>
   </parameters>
   <parameters name="personalInfo" description="
         Person information in the form of properties such as address, cellPhone." 
         title="Properties of person">
      <type>java.util.Properties</type>
      <required>false</required>
   </parameters>
   <parameters name="pets" description="
         Pets owned by the person" title="Array of Pets owned">
      <type>[Ljava.lang.String;</type>
      <required>false</required>
   </parameters>
   <parameters name="personID" description="Person Identification" 
         title="Unique ObjectName representing the person">
      <type>javax.management.ObjectName</type>
      <required>false</required>
   </parameters>
</commands>

我们向该命令添加了四个参数。每个参数包含两个字段,一个指定可以输入的参数类型,另一个指定参数是否为可选。如果将“必需”字段设置为 false,则参数为可选参数。在缺省情况下,每个参数都是必需的。参数可以是任何标准 Java 类型。在这种情况下,我们使用了 String、Properties、Array 和 ObjectName,但是我们也可以使用其他类型,如 Integer、Boolean 等。请再次注意,当命令使用 wsadmin 以交互模式运行时,描述和标题非常有用。

1b.创建管理命令提供程序

管理命令提供程序应该为创建和加载命令提供方法。

  • createCommand()——由命令框架代码调用,以创建提供程序提供的命令。此方法应该返回 AbstractAdminCommand 的实现,后者执行在传递到创建方法的命令元数据中指定的命令。

  • loadCommand()——由命令框架调用,以加载由提供程序提供的命令。此方法应该返回 AbstractAdminCommand 的实现,该实现执行在传递到加载方法的命令数据中指定的命令。

在任何时候都可以使用 command.save(outputstream) 将命令保存到文件,并且稍后可以使用 CommandMgr.loadCommand(inputStream) 再次加载。当使用 loadCommand 重新加载先前保存的命令时,命令框架将调用此方法。清单 3 显示了提供 helloWorld 命令的 HelloWorldProvider 的示例:

清单 3
public class HelloWorldProvider extends CommandProvider
{
   /*
    * createCommand : All providers must provide this method. This method
    * will be called by the command framework when a command provided by
    * this provider is created.
    * This method should return AdminCommand that implements the command
    * specified by the commandName in the metadata passed.
    */
   public AbstractAdminCommand createCommand(CommandMetadata metadata)
   throws CommandNotFoundException
   {
      if ( metadata.getName().equals("helloWorld") )
         return new HelloWorldCommand(metadata);
      else
         throw new CommandNotFoundException(metadata.getName());
   }

   /*
    * loadCommand : All providers must provide this method. This method
    * will be called by the command framework when a command provided by
    * this provider is loaded.
    * This method should return AdminCommand that implements the command
    * specified by the commandName in the metadata.
    *
    * A command can be saved at any time using command.save(outputstream)
    * and loaded again later using CommandMgr.loadCommand(inputStream)
    * When a loadCommand is used to reload previously saved command, this
    * method will be called by the command framework.
    */
   public AbstractAdminCommand loadCommand(CommandData cmdData)
   throws CommandNotFoundException, CommandLoadException
   {
      if ( cmdData.getName().equals("helloWorld") )
         return new HelloWorldCommand(cmdData);
      else
         throw new CommandNotFoundException(cmdData.getName());
   }
}

在此示例中,当调用 createCommand 或 loadCommand 方法时,提供程序只需创建类型 HelloWorldCommand 的新对象,并返回该对象。HelloWorldCommand 类实现 AbstractAdminCommand。注意,它使用命令的名称来确定要创建或加载哪一个命令。由于此示例提供程序中只有一个命令,所以无需检查。

1c.创建管理命令

管理命令应该扩展 AbstractAdminCommand,并且应该为其提供程序提供两种类型的构造器,以创建和加载命令。创建命令的构造器应该作为唯一的输入参数接受 CommandMetadata。加载命令的构造器应该作为唯一的输入参数接受 CommandData。它还应该实现包含主要命令逻辑的 execute() 方法。所有命令都应提供此方法,因为它将由执行该命令的命令框架调用。在此方法中,应该提供命令执行逻辑。

在调用此方法时,不验证参数。此方法应该调用 super.validate() 来验证参数,以确保提供了该命令所需的所有参数,并且参数类型正确。在此方法中,应该执行该命令需要的任何其他验证。

从此方法返回之前,该命令的结果应该在命令中进行设置。如果在执行命令时发生了任何错误,则应在命令结果中设置异常。在命令结果中设置的异常指示执行命令失败。

清单 4
public class HelloWorldCommand extends AbstractAdminCommand
{
   /*
    * constructor to create a command. Used by provider to create
    * a new command. All commands should implement this constructor
    */
   public HelloWorldCommand (CommandMetadata metadata)
   throws CommandNotFoundException
   {
      // super constructor should be called
      super(metadata);
   }
   
   /*
    * constructor to load a command. Used by provider to load command
    * All commands should implement this constructor
    */
   public HelloWorldCommand (CommandData cmdData)
   throws CommandNotFoundException, CommandLoadException
   {
      // super constructor should be called
      super(cmdData);
   }

   /*
    * execute() : All commands should provide this method.
    * This method will be called by command framework to execute the
    * command.
    * Command execute logic should be provided in this method.
    * When this method is called, the parameters are not validated.
    * This method should call super.validate() to validate the parameters
    * to make sure all required parameters for the command are supplied
    * and the type of parameters is correct.
    * Any additional validation required by the command should be performed
    * in this method.
    *
    * Result of the command should be set in the command before returning
    * from this method.
    * In case of error executing the command an exception should be set in
    * in the command result. An exception set in the command result
    * indicates a failure to execute the command.
    */
   public void execute()
   {
      // create command result
      CommandResultImpl result = new CommandResultImpl();
      // clear result
      result.reset();

      try {
         // super validate should be called
         validate();

         // get parameters
         String personName = (String)getParameter("personName");
         Properties personalInfo = (Properties)getParameter("personalInfo");
         String pets[] = (String[])getParameter("pets");
         javax.management.ObjectName personID =
            (javax.management.ObjectName)getParameter("personID");

         // execute cmd

         // prepare hello message
         StringBuffer sb = new StringBuffer();
         sb.append("Hello World ");
         if ( personName != null ) {
            sb.append(personName);
         }

         if ( personID != null ) {
            sb.append(" ID =  ");
            sb.append(personID.toString());
         }


         if ( personalInfo != null ) {
            sb.append(" Personal Info = ");
            sb.append(personalInfo);
         }

         if ( pets != null ) {
            sb.append(" pets =  ");
            for ( int i=0; i<pets.length; i++ ) {
               if ( i!=0 ) sb.append(",");
               sb.append(pets[i]);
            }
         }

         // setup the result
         String res = sb.toString();
         result.setResult(res);

      }
      catch (CommandValidationException cve) {
         result.setException(cve);
      }
      catch (Throwable e) {
         result.setException(e);
      }

      // set command result
      setCommandResult(result);
   }
}

2. 任务命令的命令实现

  1. 创建任务命令定义
  2. 创建任务命令提供程序
  3. 创建任务命令

2a.创建任务命令定义

假设命令提供程序需要编写 Hello World 命令,该命令在单独步骤中接受输入(人员的名称和国家/地区名称),并向该人员说 Hello World。我们可以创建任务命令,它拥有附带参数的单一步骤 (getPerson),如清单 5 所示。在该步骤中有两个参数,一个是名称 (personName),另一个是国家/地区 (countryName)。任务命令可以拥有零个或多个步骤。这里是一个步骤。

清单 5
<commandProvider implClass="HelloWorldTaskProvider">
   <commandGroups name="HelloWorldTask">
      <commands>helloWorldTask</commands>
   </commandGroups>
   <taskCommands name="helloWorldTask" description="
         HelloWorld Task Command" title="Hello World Task Command">
      <targetObjectAllowed>false</targetObjectAllowed>
      <steps name="getPerson" description="
            Step to get person information" title="personal information step">
         <targetObjectAllowed>false</targetObjectAllowed>
         <priority>0</priority>
         <parameters name="personName" description="Name of person" 
               title="Name of Person">
            <type>String</type>
            <required>true</required>
         </parameters>
         <parameters name="countryName" description="
               Country Name of person" title="Name of Country">
            <type>String</type>
            <required>true</required>
         </parameters>
      </steps>
   </taskCommands>
</commandProvider>

此示例类似于管理命令示例,不同的是在 <taskCommands></taskCommands> 中定义命令,而在任务命令中使用 <steps></steps> 定义步骤。对于 taskCommand (helloWorldTask) 本身,我们这里没有任何参数,但是您可以根据需要添加参数。helloWorldTask 有一个步骤 getPerson,对于该命令,该步骤需要两个参数。如果参数是可选的,可以将此步骤的参数所需的属性设置为 false。

表步骤

表步骤是任务命令中的步骤,它以表(具有多个行和列)的形式接受输入参数。表步骤类似于命令步骤,并具有参数列表。表步骤中的每个参数表示一个列。分配给步骤参数的每组值表示一个行。可以分配多组参数值,以形成具有多个行的表。例如,我们可以将表步骤添加到 helloWorldTask 命令,该命令以表的形式包含个人的联系信息:

表 8. 表步骤示例
联系类型联系人地址
家庭电话xxx-xxx-xxxx
办公电话yyy-yyy-yyyy
电子邮件地址xxx@yyy.com

使用步骤表可以获得此类信息,如清单 6 所示。

清单 6
<steps name="contactInfo" description="
      Step to get person's contact information" title="
      Contact information step.">
   <targetObjectAllowed>false</targetObjectAllowed>
   <table>true</table>
   <priority>0</priority>
   <parameters name="type" description="contact type 
         (phone or e-mail) " title="contact type">
      <type>String</type>
      <required>true</required>
      <keyField>true</keyField>
   </parameters>
   <parameters name="value" description="
         contact value ( phone number or e-mail address )" 
         title="contact value">
      <type>String</type>
      <required>true</required>
      <keyField>true</keyField>
   </parameters>
</steps>

注意,<table>true</table> 是使步骤成为表步骤所需的所有内容。要求 keyField 属性表示一个或多个用于搜索表项的密钥。

通过添加其他步骤扩展任务命令

可以使用其他步骤扩展任务命令。通常,要求这种类型的扩展执行基本命令的其他任务。清单 7 显示了如何通过添加新的步骤扩展任务命令的示例。在此示例中,新的步骤 additionalInfo 通过命令提供程序 HelloWorldExtProvider 被添加到 helloWorldTask 命令。此扩展步骤可以获取客户的其他信息,如个人的业余爱好和喜欢的体育活动。

清单 7
<commandProvider implClass="HelloWorldExtProvider">
   <taskCommandExts>
      <name>helloWorldTask</name>
      <steps name="additionalInfo" description="
            extended step to add additional information" title="
            Additional Information Step Extension">
         <targetObjectAllowed>false</targetObjectAllowed>
         <priority>0</priority>
         <parameters name="hobbies" description="
               Hobbies" title="Hobbies">
            <type>[Ljava.lang.String;</type>
            <required>true</required>
         </parameters>
         <parameters name="sports" description="
               Sports" title="Sports">
            <type>[Ljava.lang.String;</type>
            <required>true</required>
         </parameters>
      </steps>
   </taskCommandExts>
</commandProvider>

命令扩展定义类似于任务命令定义,不同的是它在 <taskCommandExts> </taskCommandExts> 块中指定用于扩展基本命令的步骤。名称元素指定这些步骤扩展的基本命令。

清单 8 显示了命令定义文件的完整示例,它包含管理命令和任务命令。

清单 8
<Metadata xmlns="commandmetadata.xsd">
<!--
Admin Command Example :
This will display Hello or Hello personName
Result :
   Hello
   Hello John
   Hello John {cellPhone=123-456-7890 homePhone=123-456-7890 
         workPhone=123-456-7890} pets=dog,cat personId=John(organization=ibm,
         country=usa,state=texas,city=austin)
-->
   <commandProvider implClass="HelloWorldProvider">
      <commandGroups name="HelloWorld">
         <commands>helloWorld</commands>
      </commandGroups>
      <commands name="helloWorld" description="Hello World 
            command" title="Hello World Command">
         <targetObjectAllowed>false</targetObjectAllowed>
         <parameters name="personName" description="Name of 
               person" title="Name of Person">
            <type>String</type>
            <required>false</required>
         </parameters>
         <parameters name="personalInfo" description="Person 
               information in the form of properties such as address, 
               cellPhone." title="Properties of person">
            <type>java.util.Properties</type>
            <required>false</required>
         </parameters>
         <parameters name="pets" description="Pets owned 
               by the person" title="Array of Pets owned">
            <type>[Ljava.lang.String;</type>
            <required>false</required>
         </parameters>
         <parameters name="personID" description="Person 
               Identification" title="Unique ObjectName representing 
               the person">
            <type>javax.management.ObjectName</type>
            <required>false</required>
         </parameters>
      </commands>
   </commandProvider>

<!--
Task Command Example :
This will display Hello World or Hello World personName, countryName
Result :
   Hello World John,USA {phone=123-456-7890, e-mail=john@yahoo.com}

Table step : A step that accepts parameters in the form of a table.
It has two paramters type and value that represents two columns of the table.
Multiple rows can be specified as input paramters for this step as shown below.

   type                 value
   --------------       ------------
   home phone           xxx-xxx-xxxx
   work phone           xxx-xxx-xxxx
   e-mail address       xxx@yyyy.com
-->

   <commandProvider implClass="HelloWorldTaskProvider">
      <commandGroups name="HelloWorldTask">
         <commands>helloWorldTask</commands>
      </commandGroups>
      <taskCommands name="helloWorldTask" description="HelloWorld 
            Task Command" title="Hello World Task Command">
         <targetObjectAllowed>false</targetObjectAllowed>
         <steps name="getPerson" description="Step to get person 
               information" title="personal information step">
            <targetObjectAllowed>false</targetObjectAllowed>
            <priority>0</priority>
            <parameters name="personName" description="Name of 
                  person" title="Name of Person">
               <type>String</type>
               <required>true</required>
            </parameters>
            <parameters name="countryName" description="Country 
                  Name of person" title="Name of Country">
               <type>String</type>
               <required>true</required>
            </parameters>
         </steps>
         <steps name="contactInfo" description="Step to get 
               person's contact information" title="Contact information 
               step.">
            <targetObjectAllowed>false</targetObjectAllowed>
            <table>true</table>
            <priority>0</priority>
            <parameters name="type" description="contact type 
                  (phone or e-mail) " title="contact type">
               <type>String</type>
               <required>true</required>
               <keyField>true</keyField>
            </parameters>
            <parameters name="value" description="contact value 
                  (phone number or e-mail address )" title="contact value">
               <type>String</type>
               <required>true</required>
               <keyField>true</keyField>
            </parameters>
         </steps>
      </taskCommands>
   </commandProvider>

<!--
Task Command Extension Example :
This will add additional information to the above command.
In this example, a new step is added as an extension to the Hello World command.
This new step reads hobbies and sports parameters and adds to the result of the
original command.

Result :
   Hello World John,USA {phone=123-456-7890, e-mail=john@yahoo.com} {hobbies=movies,
      sports} {sports=cricket, tennis}
-->

   <commandProvider implClass="HelloWorldExtProvider">
      <taskCommandExts>
         <name>helloWorldTask</name>
         <steps name="additionalInfo" description="extended step to 
               additional information" title="Additional Information Step 
               Extension">
            <targetObjectAllowed>false</targetObjectAllowed>
            <priority>0</priority>
            <parameters name="hobbies" description="Hobbies" 
                  title="Hobbies">
               <type>[Ljava.lang.String;</type>
               <required>true</required>
             </parameters>
            <parameters name="sports" description="Sports" 
                  title="Sports">
               <type>[Ljava.lang.String;</type>
               <required>true</required>
             </parameters>
         </steps>
      </taskCommandExts>
   </commandProvider>

</Metadata>

2b.创建任务命令提供程序

任务命令提供程序应该为创建和加载类似于管理命令的命令提供方法。由于任务命令还包含步骤,所以它还应该为创建和加载步骤提供方法。

任务管理提供程序应该实现以下方法:

  • createCommand()——由命令框架代码调用,以创建此提供程序提供的命令。此方法应该返回 AbstractAdminCommand 实现,该实现执行在传递到 createCommand() 方法的命令元数据中指定的命令。

  • loadCommand()——由命令框架调用,以加载由此提供程序提供的命令。此方法应该返回 AbstractAdminCommand 实现,该实现执行在传递到 loadCommand() 方法的命令数据中指定的命令。

  • createCommandStep()——由命令提供程序调用,以创建由此提供程序提供的步骤。此方法应该返回 AbstractCommandStep 实现,该实现执行传递到 createStep() 方法的步骤元数据中指定的步骤。

  • loadCommandStep()——由命令框架调用,以加载由此提供程序提供的步骤。此方法应该返回 AbstractCommandStep 实现,该实现执行传递到 loadStep() 方法的步骤数据中指定的步骤。

清单 9
public class HelloWorldTaskProvider extends CommandProvider
{
   /*
    * createCommand : All providers must provide this method. This method
    * will be called by command framework to create a new command.
    * This method should return TaskCommand that implements the command
    * specified by name commandName in the metadata passed.
    */
   public AbstractAdminCommand createCommand(CommandMetadata metadata)
   throws CommandNotFoundException
   {
      HelloWorldTaskCommand cmd = new HelloWorldTaskCommand((TaskCommandMetadata)
         metadata);
      // set initial values for table
      setInitialValues(cmd);
      return cmd;
   }

   /*
    * loadCommand : All providers must provide this method. This method
    * will be called by command framework to load a command.
    * This method should return TaskCommand that implements the command
    * specified by name commandName in the command data passed.
    */
   public AbstractAdminCommand loadCommand(CommandData cmdData)
   throws CommandNotFoundException, CommandLoadException
   {
      HelloWorldTaskCommand cmd =  new HelloWorldTaskCommand((TaskCommandData)cmdData);
      // set initial values for table
      setInitialValues(cmd);
      return cmd; 
   }

   /*
    * createCommandStep : All providers must provide this method.
    * This method will be called by command framework to create
    * a step command.
    * This method should return CommandStep that implements the step
    * specified by stepName passed.
    */
   public AbstractCommandStep createCommandStep(AbstractTaskCommand taskCmd, String 
      stepName) 
   throws CommandNotFoundException
   {
      // get stepMetadata from task command metadata.
      // Command framework can improve this by passing stepMetadata.
      TaskCommandMetadata metadata = (TaskCommandMetadata) taskCmd.getCommandMetadata();
      CommandStepMetadata stepMetadata = null;
      for (Iterator iter = metadata.getSteps().iterator(); iter.hasNext();) {
         CommandStepMetadata temp = (CommandStepMetadata) iter.next();
         if (temp.getName().equals(stepName)) {
            stepMetadata = temp;
            break;
         }
      }

      if (stepMetadata == null)
         throw new CommandNotFoundException(taskCmd.getName(), stepName);

      if ( stepName.equals("getPerson") )
         return ((HelloWorldTaskCommand)taskCmd).new GetPerson((AbstractTaskCommand)
               taskCmd, stepMetadata);
      else if ( stepName.eqauls("contactInfo" )
         return ((HelloWorldTaskCommand)taskCmd).new ContactInfo((AbstractTaskCommand)
               taskCmd,stepMetadata);
      else
         throw new CommandNotFoundException(taskCmd.getName(), stepName);
   }

   /*
    * loadCommandStep : All providers must provide this method.
    * This method will be called by command framework to load
    * a step command.
    * This method should return CommandStep that implements the step
    * specified by stepName passed.
    */
   public AbstractCommandStep loadCommandStep(AbstractTaskCommand taskCmd, 
      CommandStepData stepData)
   throws CommandNotFoundException, CommandLoadException
   {
      // get taskname and stepname
      String taskName = taskCmd.getName();
      String stepName = stepData.getName();

      if ( !taskName.equals("helloWorldTask") )
         throw new CommandNotFoundException(taskName, stepName);
      if ( stepName.equals("getPerson") )
         return ((HelloWorldTaskCommand)taskCmd).new GetPerson((AbstractTaskCommand)
            taskCmd, stepData);
      else if ( stepName.equals("contactInfo") )
         return ((HelloWorldTaskCommand)taskCmd).new ContactInfo((AbstractTaskCommand)
            taskCmd, stepData);
      else
         throw new CommandNotFoundException(taskName, stepName);
   }
}

初始化表步骤

表步骤有时需要使用一些缺省值初始化表。通过在命令创建时添加新的行,命令提供程序可以初始化表步骤。在命令初始化过程中,添加到表的行将对客户机可用,并且在执行命令之前可以将其删除或修改。此外,在执行命令之前,可以添加更多的新行。

清单 10
public class HelloWorldTaskProvider extends CommandProvider
{
   public AbstractAdminCommand createCommand(CommandMetadata metadata)
   throws CommandNotFoundException
   {
      HelloWorldTaskCommand cmd = new HelloWorldTaskCommand((TaskCommandMetadata)
         metadata);
      // set initial values for table
      setInitialValues(cmd);
      return cmd;
   }

   public AbstractAdminCommand loadCommand(CommandData cmdData)
   throws CommandNotFoundException, CommandLoadException
   {
      HelloWorldTaskCommand cmd =  new HelloWorldTaskCommand((TaskCommandData)cmdData);
      // set initial values for table
      setInitialValues(cmd);
      return cmd; 
   }

...
...

   /**
    * setInitialvalues() : This method shows how to set initial values
    * of table paramter. In this example the table in the step is initialized
    * with two rows.
    */
   private void setInitialValues(HelloWorldTaskCommand cmd)
   {
      try {
         // get table step from the command
         HelloWorldTaskCommand.ContactInfo step =
            (HelloWorldTaskCommand.ContactInfo)cmd.getCommandStep("contactInfo");
      
         // create one row
         AttributeList rowData = new AttributeList();
         rowData.add(new Attribute("type", "home phone"));
         rowData.add(new Attribute("value", "xxx-xxx-xxxx"));

         // initialize step with one row at index 0
         step.initializeRow(rowData, 0);

         // create another row
         rowData.clear();
         rowData.add(new Attribute("type", "e-mail address"));
         rowData.add(new Attribute("value", "xxx@yyy.com"));
   
         // add another row to step at index 1
         step.initializeRow(rowData, 1);
      }
      catch (Exception e) {
         // error handling
      }
   }
}

在清单 10 中,在命令创建过程中调用的 setInitialValues() 方法向表步骤添加两行。它先从任务命令获取表步骤,然后构造行。每行由步骤及其值所需的所有参数组成。在此情况下,有两个必需参数:类型和值,它们表示联系类型和联系人地址。构造具有步骤及其值所需的所有参数的行之后,使用 initializeRow() 方法在适当的行索引将其添加到表。

任务命令扩展提供程序

扩展命令提供程序类似于任务命令提供程序,不同之处是扩展命令提供程序只需提供创建和加载步骤的方法。这是因为扩展命令提供程序是指通过添加其他步骤扩展基本命令。不过,扩展命令提供程序还可以包括自已的基本命令。换句话说,命令提供程序可以包含自已的基本命令,扩展其他命令。此提供程序应该实现提供程序提供的命令和步骤的创建和加载。

清单 11 显示了任务命令扩展提供程序的示例。

清单 11
/**
 * HelloExtProvider : A provider that provides an extension to
 * HelloWorldTaskCommand.
 * Since this provider only provides new steps to existing command,
 * only create and load step methods are required.
 */
public class HelloWorldExtProvider extends CommandProvider
{
   /*
    * createCommandStep : All providers must provide this method.
    * This method will be called by command framework to create
    * a step command.
    * This method should return CommandStep that implements the step
    * specified by stepName passed.
    */
   public AbstractCommandStep createCommandStep(AbstractTaskCommand taskCmd, 
   String stepName) throws CommandNotFoundException {

      // get stepMetadata from task command metadata.
      // Command framework can improve this by passing stepMetadata.
      TaskCommandMetadata metadata = (TaskCommandMetadata) taskCmd.getCommandMetadata();
      CommandStepMetadata stepMetadata = null;
      for (Iterator iter = metadata.getSteps().iterator(); iter.hasNext();) {
         CommandStepMetadata temp = (CommandStepMetadata) iter.next();
         if (temp.getName().equals(stepName)) {
            stepMetadata = temp;
            break;
         }
      }

      if (stepMetadata == null)
         throw new CommandNotFoundException(taskCmd.getName(), stepName);

      if ( stepName.equals("additionalInfo") )
         return new  HelloWorldExtStep((AbstractTaskCommand)taskCmd, stepMetadata);
      else
         throw new CommandNotFoundException(taskCmd.getName(), stepName);
   }

   /*
    * loadCommandStep : All providers must provide this method.
    * This method will be called by command framework to load
    * a step command.
    * This method should return CommandStep that implements the step
    * specified by stepName passed.
    */
   public AbstractCommandStep loadCommandStep(AbstractTaskCommand taskCmd, 
      CommandStepData stepData)
   throws CommandNotFoundException, CommandLoadException
   {
      // get taskname and stepname
      String taskName = taskCmd.getName();
      String stepName = stepData.getName();

      if ( taskName.equals("helloWorldTask") )
         throw new CommandNotFoundException(taskName, stepName);
      if ( stepName.equals("additionalInfo") )
         return new HelloWorldExtStep((AbstractTaskCommand)taskCmd, stepData);
      else
         throw new CommandNotFoundException(taskName, stepName);
   }
}

2c.创建任务命令

任务命令应该扩展 AbstractTaskCommand。就像管理命令一样,任务命令应该为创建和加载命令提供构造器。创建命令的构造器应该作为唯一输入参数接受 TaskCommandMetadata。加载命令的构造器应该作为唯一输入参数接受 CommandData。

与管理命令不同,任务命令不应实现 execute() 方法。这是因为:AbstractTaskCommand 先实现 execute() 方法,然后 AbsractTaskCommand 的 execute() 方法调用任务命令的 beforeStepsExecuted() 方法,再调用步骤的所有 execute() 方法,最后调用任务命令的 afterStepsExecuted() 方法。如果覆盖此 execute() 方法,则步骤不能自动执行。因此,任务命令应实现 beforeStepsExecuted() 或 afterStepsExecuted(),或同时实现二者,然后实现命令的逻辑。

如果步骤的执行取决于任务命令执行的结果,那么任务命令应该使用 beforeStepsExecuted() 方法。与之相反,如果任务命令取决于步骤执行的结果,那么应该使用 afterStepsExecuted() 方法实现命令逻辑。

在执行命令及其步骤之前调用 validate() 方法,并且将其用于验证输入参数。命令框架调用该方法来首先验证命令,然后验证步骤。当调用验证方法时,命令框架会检查参数类型和所需的参数,这样,稍后就无需调用 super.validate()。

对于任务命令,在调用 execute() 方法之前设置空的命令结果。不过,对于步骤,不设置结果。步骤可以使用命令的结果,也可以设置自已的结果。在清单 12 中,步骤使用任务命令的结果,然后对它进行添加。

清单 12
/**
 *
 * HelloWorldTaskCommand : A Hello World command. A task command with steps
 *
 * Note that a task command should not implement execute() method.
 * execute() method of AbsractTaskCommand calls beforeStepsExecuted() method
 * of the task command and then all the step's execute() methods and then
 * call afterStepsExecuted() method of the task command. If this execute()
 * method is overriden, the steps will not be executed automatically.
 *
 * Therefore, a task command should implement all the logic in either
 * beforeStepsExecuted() or afterStepsExecuted() methods depending on whether
 * steps execution depends on the task command execution result or vice-versa.
 *
 * For task commands, an empty command result is set before invoking execute()
 * method.  But, for steps, result is not set. Steps can either use command's
 * result or set its own result. In this example, steps use its task command's
 * result and add to it.
 */
public class HelloWorldTaskCommand extends AbstractTaskCommand
{
   /*
    * constructor to create task command using command metadata.
    * called during command create
    */
   public HelloWorldTaskCommand(TaskCommandMetadata metadata)
   throws CommandNotFoundException
   {
      super(metadata);
   }
   
   /*
    * constructor to create task command using command data.
    * called during command load
    */
   public HelloWorldTaskCommand(CommandData cmdData)
   throws CommandNotFoundException, CommandLoadException
   {
      super(cmdData);
   }

   /*
    * This method is called before execution of the command and its
    * steps. This method can be used to validate the input parameters.
    * validate of command is called first and then the validate of all
    * steps are called.
    * Need not call super.valdate();
    */
   public void validate() throws CommandValidationException
   {
      // no validation in this case
   }

   /*
    * This method is called before executing any step.
    * This method can be used to setup data in the command result that
    * step can use during thier execution.
    */
   protected void beforeStepsExecuted()
   {
      TaskCommandResult result = getTaskCommandResult();
      List res = new ArrayList();
      res.add("Hello ");
      ((CommandResultImpl)result).setResult(res);
   }

   /*
    * This method is called after executing all steps.
    */
   protected void afterStepsExecuted()
   {
      TaskCommandResult result = getTaskCommandResult();
      List res = (List)result.getResult();
   }
}

在任务命令中创建步骤

任务命令的所有步骤应该扩展 AbstractAdminStep。所有步骤都应提供两个构造器,以创建和加载命令步骤。命令提供程序将使用这些构造器创建或加载步骤。

创建步骤的构造器将其父任务命令和步骤元数据作为输入参数。加载步骤的构造器将其父任务命令和步骤数据作为输入参数。

  • Validate()——由步骤实现,应该首先调用 super.validate(),以确保参数为正确的类型,并提供了所需的所有参数。可以执行任何其他验证。

  • ExecuteStep()——由步骤使用,以执行与步骤相关的任何任务。所有的步骤都应该实现此方法。

可以在步骤的结果或父任务命令的结果中设置步骤的执行结果。在清单 13 中,execute() 方法提取父任务命令的结果,并通过将步骤结果附加到任务命令的结果而设置操作的结果。

清单 13
/*
 * Implementation of comand steps
 */
public class GetPerson extends AbstractCommandStep
{
   /*
    * constructor to create command step.
    * This constructor will be called to create a new step.
    */
   public GetPerson(AbstractTaskCommand parent, CommandStepMetadata metadata)
   throws CommandNotFoundException
   {
      super(parent, metadata);
   }

   /*
    * constructor to load command step.
    * This constructor will be called to load step.
    */
   public GetPerson(AbstractTaskCommand parent, CommandStepData cmdData)
   throws CommandNotFoundException, CommandLoadException
   {
      super(parent, cmdData);
   }

   /*
    * This method will be called before executeStep.
    * Should call super.valdate();
    */
   public void validate() throws CommandValidationException
   {
      super.validate();
      // perform more validation
   }

   /*
    * This method will be called to execute the step
    */
   protected void executeStep()
   {
      // get all parameters
      String personName = null;
      String countryName = null;
      String personInfo = null;
      try {
         personName = (String)getParameter("personName");
         countryName = (String)getParameter("countryName");
      }
      catch (InvalidParameterNameException e) {
         CommandResultImpl result = (CommandResultImpl)taskCmd.getCommandResult();
         result.setException(e);
         return;
      }
      
      // execute
      if ( personName != null )
         personInfo = personName + "," + countryName;

      // get task command result
      CommandResult result = taskCmd.getCommandResult();
      List res = (List)result.getResult();

      // update task command result
      res.add(personInfo);
   }
}

表步骤实现

表步骤实现类似于实现典型的命令步骤,它们有相同的方法集。唯一不同的是从表获取参数的方式。清单 14 显示了 HelloWorldTask 的表步骤的完整示例。

清单 14
public class ContactInfo extends AbstractCommandStep
{
   /*
    * constructor to create command step.
    * This constructor will be called to create a new step.
    */
   public ContactInfo(AbstractTaskCommand parent, CommandStepMetadata metadata)
   throws CommandNotFoundException
   {
      super(parent, metadata);
   }

   /*
    * constructor to load command step.
    * This constructor will be called to load step.
    */
   public ContactInfo(AbstractTaskCommand parent, CommandStepData cmdData)
   throws CommandNotFoundException, CommandLoadException
   {
      super(parent, cmdData);
   }

   /*
    * This method will be called before executeStep.
    * Should call super.valdate();
    */
   public void validate() throws CommandValidationException
   {
      super.validate();
      // perform more validation
   }

   /*
    * This method will be called to execute the step
    */
   protected void executeStep()
   {
      // get number of rows
      int rows = getNumberOfRows();
      StringBuffer sb = new StringBuffer();
      sb.append("{");
      try {
         // get each row
         for (int i=0; i<rows; i++) {
            // get type parameter indexed at "i"
            String type = (String)getParameter("type", i);
            // get value parameter indexed at "i"
            String value = (String)getParameter("value", i);

            if ( i!=0 ) sb.append(" ; ");
            sb.append(type);
            sb.append("=");
            sb.append(value);
         }
      }
      catch (InvalidParameterNameException e) {
         CommandResultImpl result = (CommandResultImpl)taskCmd.getCommandResult();
         result.setException(e);
         return;
      }
      sb.append("}");
      
      // execute
      String contactInfo = sb.toString();

      // get task command result
      CommandResult result = taskCmd.getCommandResult();
      List res = (List)result.getResult();

      // update task command result
      res.add(contactInfo);
   }

   /**
    * This method has protected access in
    * com.ibm.websphere.management.cmdframework.provider.AbstractCommandStep.
    * Therefore, we need to overwrite this method so that
    * the provider can initialze the rows.
    */
   protected void initializeRow(AttributeList rowData, int rowIndex)
   throws InvalidParameterValueException, IndexOutOfBoundsException
   {
      super.initializeRow(rowData, rowIndex);
   }
}

在清单 14 中,execute() 方法首先获取输入到步骤的参数的行数。对于每一行,使用同一 getParameter() 方法获取相应的参数值;唯一的不同是 rowIndex 被传递到 getParameter() 方法。

另外,请注意,在创建命令时,如果提供程序需要初始化带有若干行的表,则在步骤命令实现中需要覆盖 initializeRow() 方法。之所以需要这样,是因为超类中的 initializeRow 具有受保护的访问权限,它不能直接从提供程序实现中调用。

创建命令扩展

命令的扩展只包括添加其他步骤。其他步骤实现类似于任务命令步骤的实现。清单 15 给出了一个这样的示例。正如您看到的,HelloWorldExtStep 实现与 GetPerson 步骤没有任何不同;它实现一组相同的方法,并在执行后更新任务的命令结果。

清单 15
/**
 *
 * HelloWorldExtStep : An extended step to HelloWorld command
 *
 */
public class HelloWorldExtStep extends AbstractCommandStep
{
   /*
    * constructor to create command step.
    * This constructor will be called to create a new step.
    */
   public HelloWorldExtStep(AbstractTaskCommand parent, CommandStepMetadata metadata)
   throws CommandNotFoundException
   {
      super(parent, metadata);
   }

   /*
    * constructor to load command step.
    * This constructor will be called to load step.
    */
   public HelloWorldExtStep(AbstractTaskCommand parent, CommandStepData cmdData)
   throws CommandNotFoundException, CommandLoadException
   {
      super(parent, cmdData);
   }

   /*
    * This method will be called before executeStep.
    * Should call super.valdate();
    */
   public void validate() throws CommandValidationException
   {
      super.validate();
   }

   /*
    * This method will be called to execute the step
    */
   protected void executeStep()
   {
      // get parameters
      String[] hobbies = null;
      String[] sports = null;
      try {
         hobbies = (String[])getParameter("hobbies");
         sports = (String[])getParameter("sports");
      }
      catch (InvalidParameterNameException e) {
         CommandResultImpl result = (CommandResultImpl)taskCmd.getCommandResult();
         result.setException(e);
         return;
      }

      // execute
      StringBuffer sb = new StringBuffer();
      if ( hobbies != null ) {
         sb.append("hobbies =  ");
         for (int i=0; i<hobbies.length; i++) {
            if ( i!=0 ) sb.append(",");
            sb.append(hobbies[i]);
         }
      }
      sb.append("\n");
      if ( sports != null ) {
         sb.append("sports =  ");
         for ( int i=0; i<sports.length; i++ ) {
            if ( i!=0 ) sb.append(",");
            sb.append(sports[i]);
         }
      }

      String additionalInfo = sb.toString();

      // set any additional result in the task command
      CommandResultImpl result = (CommandResultImpl)taskCmd.getCommandResult();
      List res = (List)result.getResult();
      res.add(additionalInfo);
   }
}

3. 包装命令实现

通过创建 JAR 文件并将其放置在类路径中,便从本质上完成了包装命令提供程序、命令和命令定义文件。

JAR 文件应该由命令提供程序实现、命令实现和命令定义组成:

  • META-INF/admin-command-def.xml
  • Provider.classes
  • Command.classes

例如:

清单 16
META-INF/admin-command-def.xml
HelloWorldProvider.class
HelloWorldTaskProvider.class
HelloWorldTaskCommand.class

HelloWorldCommand.class
HelloWorldTaskCommand.class
HelloWorldExtStep.class

将 JAR 文件放置在需要它的程序的类路径中。例如,对于使用这些新命令的 wsadmin,需要将JAR 文件放置在 $WAS_HOME/classes 或 $WAS_HOME/lib 目录中。

在 WebSphere Application Server V6.1 中,如果在新的 JAR 文件中添加命令,那么 JAR 文件的 plugin.xml 文件应该定义以下扩展:

<extension id="Runtime" point="com.ibm.wsspi.extension.admin-command-def"/>

wsadmin 的注意事项

调用的方式

使用 AdminTask 对象运行管理命令

管理命令可用于连接模式和本地模式。在无需使用 wsadmin 工具 -conntype NONE 选项来运行服务器的情况下你也可以启动 wsadmin。如果服务器目前正在运行,则不能以本地模式运行 AdminTask 命令,因为在运行的服务器配置中不能反映以本地模式进行的任何配置更改。

以不同的模式调用管理命令或任务命令

可以在脚本中以批处理模式或交互模式调用管理命令或任务命令,或使用 wsadmin -c 命令从操作命令提示符调用。

获得联机帮助

当您需要 AdminTask 对象和关联命令的一般信息时,对管理命令可使用联机帮助:

使用 Jacl:$AdminTask help

使用 Jython:Print AdminTask.help()

  • help -commands——列出所有的管理命令。
  • help -commandGroups——列出所有的管理命令组。
  • help commandName——显示指定命令的详细信息。
  • help commandName stepName——显示属于指定命令的指定步骤的详细信息。
  • help commandGroupName——显示指定命令组的详细信息。

有多种方式可以调用管理命令:

  • commandName——调用不需要任何参数的管理命令。

  • commandName targetObject——使用指定的目标对象字符串调用管理命令;例如,资源适配器的配置对象名称。预期的目标对象因调用的管理命令而异。使用帮助命令获取关于管理命令的目标对象的信息。

  • commandName options——使用指定的选项字符串调用管理命令。此调用语法用来调用不需要目标对象的管理命令。如果交互模式包括在选项字符项中,则还可以使用该语法进入交互模式。

  • commandName targetObject options——使用指定的目标对象和选项字符串调用管理命令。如果 -interactive 包括在选项字符串中,那么进入交互模式。目标对象和选项字符串因调用的管理命令而异。使用帮助命令可获取关于目标对象和选项的信息。

指导原则

当您开始使用这些命令时,本部分包括的信息、代码示例和建议可用作参考。

支持的参数类型

表 9. WebSphere Application Server V6.0.x 中的脚本支持的参数类型
原始数据类型其他 Java 类型
string boolean character integer long byte short float doubleJavax.management.ObjectName
Java.net.URL
表 10. WebSphere Application Server V6.1.x 中的脚本支持的参数类型
原始数据类型其他 Java 类型
string boolean character integer long byte short float doubleJavax.management.ObjectName
Java.util.Properties
String[]
Java.net.URL

调用管理命令

清单 17. 使用 Jacl 交互模式
wsadmin>$AdminTask helloWorld -interactive
Hello World Command

Hello World command

Name of Person (personName): John
Properties of person (personalInfo): {cellPhone 123-456-7890} 
   {homePhone 123-456-7891} {WorkPhone 123-456-7892}  
Array of Pets owned (pets): dog;cat
Unique ObjectName representing the person (personID): 
PersonId=John(organization=ibm,country=usa,state=texas,city=austin)

Hello World Command

F (Finish)
C (Cancel)

Select [F, C]: [F]
WASX7278I: Generated command line: $AdminTask helloWorld 
{-personName John -personalInfo " { {cellPhone 123-456-7890} 
   {workPhone 123-456-7892} {homePhone 123-456-7891} }" -pets dog;cat 
   -personID WebSphere:John(organization=ibm,country=usa,state=texas,city=austin)}

Hello World John ID =  WebSphere:John(organization=ibm,country=usa,state=texas,
   city=austin) PersonalInfo = {cellPhone=123-456-7890, workPhone=123-456-7892, 
   homePhone=123-456-7891} pets =  dog,cat
清单 18. 使用 Jacl 批处理模式
wsadmin>$AdminTask helloWorld 
{-personName John -personalInfo " { {cellPhone 123-456-7890} 
   {WorkPhone 123-456-7892} {homePhone 123-456-7891} }" 
   -pets dog;cat -personID WebSphere:John(organization=ibm,country=usa,
   state=texas,city=austin)}

Hello World John ID =  WebSphere:John(organization=ibm,country=usa,
   state=texas,city=austin) PersonalInfo = {cellPhone=123-456-7890, 
   WorkPhone=123-456-7892, homePhone=123-456-7891} pets =  dog,cat

其中:

  • 将个人姓名定义为字符串参数。
  • 将个人信息定义为 java.util.Properties。
  • 将宠物定义为 String[]。
  • 将人员 ID 定义为 javax.management.ObjectName。
清单 19. 使用 Jython 交互模式
wsadmin>AdminTask.helloWorld('-interactive')
Hello World Command

Hello World command

Name of Person (personName): John
Properties of person (personalInfo): [cellPhone 123-456-7890] 
   [homePhone 123-456-7891] [workPhone 123-456-7892]
Array of Pets owned (pets): dog;cat;bird
Unique ObjectName representing the person (personID): 
John(organization=ibm,country=usa,state=texas,city=austin)

Hello World Command

F (Finish)
C (Cancel)

Select [F, C]: [F]
WASX7278I: Generated command line: AdminTask.helloWorld('[-personName 
   John -personalInfo "[ [cellPhone 123-456-7890] [workPhone 123-456-7892] 
   [homePhone 123-456-7891] ]" -pets dog;cat -personID WebSphere:John
   (organization=ibm,country=usa,state=texas,city=austin)]')

'Hello World John ID =  WebSphere:John(organization=ibm,country=usa,
   state=texas,city=austin) Personal Info = {cellPhone=123-456-7890, 
   workPhone=123-456-7892, homePhone=123-456-7891} pets =  dog,cat'
清单 20. 使用 Jython 批处理模式
wsadmin>print AdminTask.helloWorld('[-personName John 
   -personalInfo "[ [cellPhone 123-456-7890] [workPhone 123-456-7892] 
   [homePhone 123-456-7891] ]" -pets dog;cat -personID WebSphere:
   John(organization=ibm,country=usa,state=texas,city=austin)]')

'Hello World John ID =  WebSphere:John(organization=ibm,country=usa,
   state=texas,city=austin) Personal Info = {cellPhone=123-456-7890, 
   workPhone=123-456-7892, homePhone=123-456-7891} pets =  dog,cat'

调用任务命令

清单 21. 使用 Jacl 交互模式

清单 22. 使用 Jacl 批处理模式
wsadmin>$AdminTask helloWorldTask {-getPerson {-personName John -countryName 
   USA} -contactInfo {{phone 123-456-7890} {"home phone" xxx-xxx-xxxx} 
   {e-mail john@yahoo.com} {"e-mail address" xxx@yyy.com}} -additionalInfo 
   {-hobbies movies;sports -sports cricket;tennis}}
"Hello World "
John,USA
{phone=123-456-7890 ; home phone=xxx-xxx-xxxx ; e-mail=john@yahoo.com ; e-mail 
   address=xxx@yyy.com}
{hobbies=movies,sports}{sports=cricket,tennis}
清单 23. 使用 Jython 交互模式
1) Choose the "Select Row" option to modify the existing row 
      property values in the table

wsadmin>AdminTask.helloWorldTask('-interactive')
//same as Jacl interactive mode 
 ...
Select [P, F, C, H]: [F]
WASX7278I: Generated command line: AdminTask.helloWorldTask('[-getPerson 
   [-personName John -countryName USA] -contactInfo [[phone 123-456-7890] [e-mail 
   john@yahoo.com]] -additionalInfo [-hobbies movies;sports -sports ricket;tennis]]')
'Hello World \r\nJohn,USA\r\n{phone=123-456-7890 ; e-mail=john@yahoo.com}\r\n
   {hobbies=movies,sports}
{sports=cricket,tennis}'

2) Choose the "Add Row Before" option to add new rows into table

wsadmin>AdminTask.helloWorldTask('-interactive')
//same as Jacl interactive mode 
 ...
Select [P, F, C, H]: [F]
WASX7278I: Generated command line: AdminTask.helloWorldTask('[-getPerson [-personName 
   John -countryName USA] -contactInfo [["home phone" 123-456-7890] ["home 
   phone" xxx-xxx-xxxx] ["e-mail address" john@yahoo.com] ["e-mail address" 
   xxx@yyy.com]] -additionalInfo [-hobbies movies;sports -sports cricket;tennis]]')
'Hello World \r\nJohn,USA\r\n{home phone=123-456-7890 ; home phone=xxx-xxx-xxxx ; e-mail 
   address=john@yahoo.com ; e-mail address=xxx@yyy.com}\r\n{hobbies=movies,sports}{sports=
   cricket,tennis}'

3) Choose the "Delete Row" option to delete the selected row in the table

wsadmin>AdminTask.helloWorldTask('-interactive')
//same as Jacl interactive mode 
WASX7278I: Generated command line: AdminTask.helloWorldTask('[-getPerson [-personName 
   John -countryName USA] -contactInfo [[e-mail john@yahoo.com]] -additionalInfo 
   [-hobbies movies;sports -sports cricket;tennis]]')
'Hello World \r\nJohn,USA\r\n{e-mail=john@yahoo.com}\r\n{hobbies=movies,sports}
   {sports=cricket,tennis}'
清单 24. 使用 Jython 批处理模式
wsadmin>print AdminTask.helloWorldTask('[-getPerson [-personName John 
   -countryName USA] -contactInfo [["home phone" 123-456-7890] 
   ["home phone" xxx-xxx-xxxx] ["e-mail address" john@yahoo.com] 
   ["e-mail address" xxx@yyy.com]] -additionalInfo [-hobbies movies;sports 
   -sports cricket;tennis]]')
Hello World
John,USA
{home phone=xxx-xxx-xxxx ; e-mail address=xxx@yyy.com ; home phone=123-456-7890 ; 
   e-mail address=john@yahoo.com}
{hobbies=movies,sports}{sports=cricket,tennis}

支持的返回类型

wsadmin 工具将不同的管理命令返回类型转换为字符串格式,这意味着所有的管理命令结果将以字符串格式显示。表 11 列出了在 WebSphere Application Server V6.0 和 V6.1x 中 wsadmin 支持的所有返回类型。

表 11. wsadmin 支持的参数类型
原始数据类型其他 Java 类型
string(带有示例) boolean character integer long byte short float doubleJavax.management.ObjectName
Java.util.Properties
Java.management.AttributeList
Java.util.ArrayList
Java.util.Collection
Java.util.List
Java.net.URL
Array (string[], object[], integer[])
清单 25
Return type: String:
		Using Jacl:
		wsadmin>$AdminTask helloWorld {-personName John}
	
		Using Jython:
		Wsadmin>print AdminTask.helloWorld('[-personName John]')
		Hello World John
清单 26
Return type: java.util.Properties:
		Using Jacl:
wsadmin>$AdminTask helloWorld {-personalInfo "{ {cellPhone
   123-456-7890} {workPhone 123-456-7892} {homePhone 123-456-7891} }"}
		{cellPhone 123-456-7890}
		{workPhone 123-456-7892}
		{homePhone 123-456-7891} 

		Using Jython:
Wsadmin>print AdminTask.helloWorld('[-personalInfo "[ [cellPhone 
   123-456-7890] [workPhone 123-456-7892] [homePhone 123-456-7891] ]" 
   ]')
		[cellPhone 123-456-7890]
		[workPhone 123-456-7892]
		[homePhone 123-456-7891]
清单 27
Return type: String[]:
		Using Jacl:
		wsadmin>$AdminTask helloWorld {-pets dog;cat}

		Using Jython:
		Wsadmin>print AdminTask.helloWorld('[-pets dog;cat]')
		dog
		cat
清单 28
Return type: javax.management.AttributeList 
	Using Jacl:
	wsadmin>$AdminTask helloWorld {-pets dog;cat}
	{pet dog}
	{pet cat}
	
	Using Jython:
	wsadmin>print AdminTask.helloWorld('[-pets dog;cat]')
	[pet dog]
	[pet cat]
清单 29
Return type: java.util.ArrayList, java.util.List or java.util.Collection 
	Using Jacl: 
	wsadmin>$AdminTask helloWorld {-pets dog;cat}
		
	Using Jython:
	wsadmin>print AdminTask.helloWorld('[-pets dog;cat]')
	dog
	cat
清单 30
Return type: javax.management.ObjectName
		Using Jacl:
	wsadmin> $AdminTask helloWorld {-personID WebSphere:
	John(organization=ibm,country=usa,state=texas,city=austin)}

		Using Jython:
	Wsadmin>print AdminTask.helloWorld('[-personID WebSphere:
	John(organization=ibm,country=usa,state=texas,city=austin)]')

		WebSphere:
	John(organization=ibm,country=usa,state=texas,city=Austin

约定

命名指导原则

  • 命令名称:lowerCamelCase;例如 helloWorld
  • 命令参数名称:lowerCamelCase;例如 personName, personInfo, personID
  • 命令步骤名称:lowerCamelCase;例如 personName, countryName

编程指导原则

  • 命令
    • 推荐
      • 标题:提供标题的资源绑定消息 ID。
      • 描述:提供一至两个命令句子描述的资源绑定消息 ID。
  • 目标对象

    如果命令没有任何目标对象:

    • 必需
      • 将 TargetObjectAllowed 设置为 false。
      • <targetObjectAllowed>false</targetObjectAllowed>。

    另外,如果存在目标对象:

    • 可选
      • TargetObjectDescription:提供描述的资源绑定消息 ID。描述应该包括希望将什么作为输入内容。
      • TargetObjectTitle:提供标题的资源绑定消息 ID。
      • TargetObjectRequired:如果目标对象为必需。
      • TargetObjectType:目标对象的类型。
  • 参数

    • 推荐
      • 标题:提供标题的资源绑定消息 ID。
      • 描述:提供描述的资源绑定消息 ID;应该包括希望将什么作为输入内容。
    • 可选
      • 如果输入值不显示,则在描述中提供输入示例。
      • 如果适用,提供缺省值。
      • 如果适用,设置为只读(缺省为非只读)。
      • 如果适用,设置为必需(缺省为非必需)。
  • 步骤

    非表步骤:

    • 推荐
      • 标题:提供标题的资源绑定消息 ID。
      • 描述:提供描述的资源绑定消息 ID。
      • 步骤参数:指导原则与“参数”中列出的相同。

    表步骤:

    • 必需
      • 表:设置为 true。
    • 推荐
      • 标题:提供标题的资源绑定消息 ID。
      • 描述:提供描述的资源绑定消息 ID。
      • 步骤参数:与参数的指导原则相同,并且至少将一个参数设置为主要字段(缺省为非主要字段)。
    • 可选
      • enableAddRows:使用户能够向表添加行。缺省为 false。

结束语

本文概括介绍了 WebSphere Application Server 开发人员和堆栈产品开发人员都可以使用的命令框架,他们可以利用该框架编写不同类型的管理命令、任务命令和任务命令扩展。本文还包括一些详细的示例、引用信息和指导原则,以便帮助您继续简化和扩展应用服务器管理的功能。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=188264
ArticleTitle=IBM WebSphere 开发者技术期刊: WebSphere Application Server 的管理命令框架编程指南
publish-date=01152007