 | 级别: 中级 Leigh Williamson (leighw@us.ibm.com), 系统管理架构师, IBM John Chang (jchang3@us.ibm.com), 顾问软件工程师, IBM Amy Lin (amylin@us.ibm.com), 高级软件工程师, IBM Alex Huang (alexh@us.ibm.com), 顾问软件工程师, IBM Vishwanath Venkataramappa (vish@us.ibm.com), 高级软件工程师, IBM
2007 年 1 月 15 日 IBM® WebSphere® Application Server 命令框架将复杂的管理任务包装为简单的、用户友好的命令提供程序,用户可以容易地调用它,以执行复杂的系统管理活动。本文的目标读者是希望利用管理功能创建命令提供程序,以便为最终用户提供命令实现的 WebSphere 开发人员。
摘自 IBM WebSphere 开发者技术期刊。
引言
WebSphere Application Server 命令框架为开发执行 WebSphere Application Server 管理任务的命令以及执行该命令提供了概念和逻辑上的结构。命令框架基于命令模式概念;命令模式将请求转换为命令对象,该命令对象封装请求数据,之后,通过传递命令对象可以在各种执行环境中执行它。
WebSphere 命令框架可让开发人员为普通的但很复杂的管理任务(如配置和应用程序管理服务功能、JMX MBean 的执行等)实现最终用户更友好和面向高级任务的命令。命令框架还提供基本的命令管理功能,如命令注册、命令列表和其他功能。
WebSphere 命令框架基础结构将命令逻辑从命令执行环境中分离开。此分离为各种命令执行环境中的命令用户和命令提供程序提供了一致的编程模式。图 1 演示了高级命令执行流程。
图 1. 高级命令执行流程
在与命令框架一起使用时,有两种常见的使用场景:
编程接口概念
命令框架适应两种类型的命令:
- 管理命令——获取一定数量的输入参数,并执行该命令。
- 任务命令——由零个或多个步骤组成,除任务参数外,每个步骤还拥有自己的参数。
每个命令都在命令定义文件中定义,该文件包含以下各部分:
命令提供程序:
命令定义文件包含一个或多个命令提供程序,每个命令提供程序都可以拥有一个或多个命令组。每个命令组都可以拥有一个或多个命令(管理或任务类型,或同时拥有这两种类型)。管理命令拥有零个或多个参数。任务命令拥有零个或多个参数和零个或多个步骤。每个步骤拥有零个或多个参数。命令提供程序还可以包括由另一个命令提供程序提供的任务命令的扩展。任务命令扩展包含添加到现有命令的其他步骤。
下面提供了有关上述每个命令定义文件元素的详细信息:
命令
管理命令
在命令框架中,AdminCommand 接口是所有命令的基础。它定义方法(如参数 listing/setting/getting)、验证和命令执行。在命令框架中,AbstractAdminCommand 实现 AdminCommand 接口。所有的命令都应该扩展 AbstractAdminCommand 类。
任务命令
TaskCommand 使提供程序能够使用多个步骤构造复杂的管理命令。
命令步骤
多个步骤组成一个任务命令。命令步骤类似于管理命令;不过,命令步骤可以单独执行。
CommandStepMetadata
CommandStepMetadata 扩展 commandMetadataData。除 commandMetadataData 中定义的元数据外,commandStepMetadta 还定义以下内容:
表 3. CommandStepMetadata| 属性名称 | 描述 | 类型 | 缺省值 | 必需 |
|---|
| isTable | 标志指示步骤参数数据是否为表。 | boolean | false | false |
|---|
| enableAddRows | 标志指示步骤是否允许用户添加或删除行。当步骤不是表时,忽略此标志。 | boolean | false | 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 组合相关的管理命令。命令提供程序可以确定将哪些命令放在一个组中。通常,将具有相似功能的命令组合在一起。
命令提供程序
命令提供程序提供实际的命令实现,并且还为提供程序实现的所有命令指定属性。
创建命令
实现新命令包括以下常见步骤:
创建描述命令元数据的命令定义文件。 命令定义文件基于 XML,其名称为 admin-command-def.xml,必须存在于包含命令提供程序和命令实现的 JAR 文件的 META-INF 目录中。此 JAR 文件必须位于需要执行命令的程序的类路径中。
创建命令提供程序。 命令提供程序提供一个或多个命令。命令提供程序应该实现一些方法,以创建和加载由该提供程序提供的命令。命令提供程序应该实现 com.ibm.websphere.management.cmdframework.provider.CommandProvider 中指定的接口。
创建执行命令的逻辑。 为执行该命令而开发的代码将取决于命令类型:AdminCommand 或 TaskCommand。
在接下来的各个部分中,将介绍实现两种类型的命令和包装命令提供程序、命令和命令定义文件的详细示例:
- 管理命令的命令实现
- 任务命令的命令实现
- 包装命令实现
1. 管理命令的命令实现
- 创建管理命令定义
- 创建管理命令提供程序
- 创建管理命令
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.创建管理命令提供程序
管理命令提供程序应该为创建和加载命令提供方法。
在任何时候都可以使用 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. 任务命令的命令实现
- 创建任务命令定义
- 创建任务命令提供程序
- 创建任务命令
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> |
 | | 命令框架调用步骤的所有 execute() 方法,无论是否需要或提供参数。步骤的 execute() 逻辑应该确定执行什么。 |
|
此示例类似于管理命令示例,不同的是在 <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。所有步骤都应提供两个构造器,以创建和加载命令步骤。命令提供程序将使用这些构造器创建或加载步骤。
创建步骤的构造器将其父任务命令和步骤元数据作为输入参数。加载步骤的构造器将其父任务命令和步骤数据作为输入参数。
可以在步骤的结果或父任务命令的结果中设置步骤的执行结果。在清单 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
double | Javax.management.ObjectName
Java.net.URL |
|---|
表 10. WebSphere Application Server V6.1.x 中的脚本支持的参数类型| 原始数据类型 | 其他 Java 类型 |
|---|
string
boolean
character
integer
long
byte
short
float
double | Javax.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 交互模式
1) Choose the "Select Row" option to modify the existing
row property values in the table
wsadmin>$AdminTask helloWorldTask -interactive
Hello World Task Command
HelloWorld Task Command
-> *1. personal information step (getPerson)
2. Contact information step. (contactInfo)
*3. Additional Information Step Extension (additionalInfo)
S (Select)
N (Next)
C (Cancel)
H (Help)
Select [S, N, C, H]: [S]
personal information step (getPerson)
*Name of Person (personName):
*Name of Country (countryName):
Select [C (Cancel), E (Edit)]: [E]
*Name of Person (personName): John
*Name of Country (countryName): USA
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
-> 2. Contact information step. (contactInfo)
*3. Additional Information Step Extension (additionalInfo)
S (Select)
N (Next)
P (Previous)
C (Cancel)
H (Help)
Select [S, N, P, C, H]: [S]
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
-> | home phone, xxx-xxx-xxxx
| e-mail address, xxx@yyy.com
contact type, contact value must be provided to specific a row in batch mode.
S (Select Row)
N (Next)
A (Add Row Before)
D (Delete Row)
F (Finish)
H (Help)
Select [S, N, A, D, F, H]: [F] S
*contact type (type): [home phone] phone
*contact value (value): [xxx-xxx-xxxx] 123-456-7890
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
| phone, 123-456-7890
-> | e-mail address, xxx@yyy.com
contact type, contact value must be provided to specific a row in batch mode.
S (Select Row)
N (Next)
P (Previous)
A (Add Row Before)
D (Delete Row)
F (Finish)
H (Help)
Select [S, N, P, A, D, F, H]: [F] S
*contact type (type): [e-mail address] e-mail
*contact value (value): [xxx@yyy.com] john@yahoo.com
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
| phone, 123-456-7890
| e-mail, john@yahoo.com
->
contact type, contact value must be provided to specific a row in batch mode.
P (Previous)
A (Add Row Before)
F (Finish)
H (Help)
Select [P, A, F, H]: [F]
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
2. Contact information step. (contactInfo)
-> *3. Additional Information Step Extension (additionalInfo)
S (Select Row)
P (Previous)
C (Cancel)
H (Help)
Select [S, P, C, H]: [S]
Additional Information Step Extension (additionalInfo)
*Hobbies (hobbies):
*Sports (sports):
Select [C (Cancel), E (Edit)]: [E]
*Hobbies (hobbies): movies;sports
*Sports (sports): cricket;tennis
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
2. Contact information step. (contactInfo)
3. Additional Information Step Extension (additionalInfo)
-> End of task
P (Previous)
F (Finish)
C (Cancel)
H (Help)
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 cricket;tennis}}
"Hello World"
John,USA
{phone=123-456-7890 ; e-mail=john@yahoo.com}
{hobbies=movies,sports}{sports=cricket,tennis}
2) Choose the "Add Row Before" option to add new rows into table
wsadmin>$AdminTask helloWorldTask -interactive
Hello World Task Command
HelloWorld Task Command
-> *1. personal information step (getPerson)
2. Contact information step. (contactInfo)
*3. Additional Information Step Extension (additionalInfo)
S (Select)
N (Next)
C (Cancel)
H (Help)
Select [S, N, C, H]: [S]
personal information step (getPerson)
*Name of Person (personName):
*Name of Country (countryName):
Select [C (Cancel), E (Edit)]: [E]
*Name of Person (personName): John
*Name of Country (countryName): USA
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
-> 2. Contact information step. (contactInfo)
*3. Additional Information Step Extension (additionalInfo)
S (Select)
N (Next)
P (Previous)
C (Cancel)
H (Help)
Select [S, N, P, C, H]: [S]
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
-> | home phone, xxx-xxx-xxxx
| e-mail address, xxx@yyy.com
contact type, contact value must be provided to specific a row in batch mode.
S (Select Row)
N (Next)
A (Add Row Before)
D (Delete Row)
F (Finish)
H (Help)
Select [S, N, A, D, F, H]: [F] A
*contact type (type): phone
*contact value (value): 123-456-7890
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
| phone, 123-456-7890
-> | home phone, xxx-xxx-xxxx
| e-mail address, xxx@yyy.com
contact type, contact value must be provided to specific a row in batch mode.
S (Select Row)
N (Next)
P (Previous)
A (Add Row Before)
D (Delete Row)
F (Finish)
H (Help)
Select [S, N, P, A, D, F, H]: [F] N
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
| phone, 123-456-7890
| home phone, xxx-xxx-xxxx
-> | e-mail address, xxx@yyy.com
contact type, contact value must be provided to specific a row in batch mode.
S (Select Row)
N (Next)
P (Previous)
A (Add Row Before)
D (Delete Row)
F (Finish)
H (Help)
Select [S, N, P, A, D, F, H]: [F] A
*contact type (type): e-mail
*contact value (value): john@yahoo.com
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
| phone, 123-456-7890
| home phone, xxx-xxx-xxxx
| e-mail, john@yahoo.com
-> | e-mail address, xxx@yyy.com
contact type, contact value must be provided to specific a row in batch mode.
S (Select Row)
N (Next)
P (Previous)
A (Add Row Before)
D (Delete Row)
F (Finish)
H (Help)
Select [S, N, P, A, D, F, H]: [F]
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
2. Contact information step. (contactInfo)
-> *3. Additional Information Step Extension (additionalInfo)
S (Select Row)
P (Previous)
C (Cancel)
H (Help)
Select [S, P, C, H]: [S]
Additional Information Step Extension (additionalInfo)
*Hobbies (hobbies):
*Sports (sports):
Select [C (Cancel), E (Edit)]: [E]
*Hobbies (hobbies): movies;sports
*Sports (sports): cricket;tennis
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
2. Contact information step. (contactInfo)
3. Additional Information Step Extension (additionalInfo)
-> End of task
P (Previous)
F (Finish)
C (Cancel)
H (Help)
Select [P, F, C, H]: [F]
WASX7278I: Generated command line: $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}
3) Choose the "Delete Row" option to delete the selected row in the table
wsadmin>$AdminTask helloWorldTask -interactive
Hello World Task Command
HelloWorld Task Command
-> *1. personal information step (getPerson)
2. Contact information step. (contactInfo)
*3. Additional Information Step Extension (additionalInfo)
S (Select)
N (Next)
C (Cancel)
H (Help)
Select [S, N, C, H]: [S]
personal information step (getPerson)
*Name of Person (personName):
*Name of Country (countryName):
Select [C (Cancel), E (Edit)]: [E]
*Name of Person (personName): John
*Name of Country (countryName): USA
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
-> 2. Contact information step. (contactInfo)
*3. Additional Information Step Extension (additionalInfo)
S (Select)
N (Next)
P (Previous)
C (Cancel)
H (Help)
Select [S, N, P, C, H]: [S]
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
-> | home phone, xxx-xxx-xxxx
| e-mail address, xxx@yyy.com
contact type, contact value must be provided to specific a row in batch mode.
S (Select Row)
N (Next)
A (Add Row Before)
D (Delete Row)
F (Finish)
H (Help)
Select [S, N, A, D, F, H]: [F] D
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
-> | e-mail address, xxx@yyy.com
contact type, contact value must be provided to specific a row in batch mode.
S (Select Row)
N (Next)
A (Add Row Before)
D (Delete Row)
F (Finish)
H (Help)
Select [S, N, A, D, F, H]: [F] D
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
A (Add Row)
F (Finish)
H (Help)
Select [A, F, H]: [A]
*contact type (type): home phone
*contact value (value): 123-456-7890
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
| home phone, 123-456-7890
->
contact type, contact value must be provided to specific a row in batch mode.
P (Previous)
A (Add Row Before)
F (Finish)
H (Help)
Select [P, A, F, H]: [F] A
*contact type (type): e-mail address
*contact value (value): john@yahoo.com
Contact information step. (contactInfo)
| contact type (type), contact value (value)
--------------------------------------------
| home phone, 123-456-7890
| e-mail address, john@yahoo.com
->
contact type, contact value must be provided to specific a row in batch mode.
P (Previous)
A (Add Row Before)
F (Finish)
H (Help)
Select [P, A, F, H]: [F]
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
2. Contact information step. (contactInfo)
-> *3. Additional Information Step Extension (additionalInfo)
S (Select Row)
P (Previous)
C (Cancel)
H (Help)
Select [S, P, C, H]: [S]
Additional Information Step Extension (additionalInfo)
*Hobbies (hobbies):
*Sports (sports):
Select [C (Cancel), E (Edit)]: [E]
*Hobbies (hobbies): movies;sports
*Sports (sports): cricket;tennis
Hello World Task Command
HelloWorld Task Command
1. personal information step (getPerson)
2. Contact information step. (contactInfo)
3. Additional Information Step Extension (additionalInfo)
-> End of task
P (Previous)
F (Finish)
C (Cancel)
H (Help)
Select [P, F, C, H]: [F]
WASX7278I: Generated command line: $AdminTask helloWorldTask {-getPerson {-personName
John -countryName USA} -contactInfo {{"home phone" 123-456-7890} {"e-mail
address" john@yahoo.com}} -additionalInfo {-hobbies movies;sports -sports
cricket;tennis}}
"Hello World "
John,USA
{home phone=123-456-7890 ; e-mail address=john@yahoo.com}
{hobbies=movies,sports}{sports=cricket,tennis} |
清单 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
double | Javax.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。
- 步骤参数:指导原则与“参数”中列出的相同。
表步骤:
- 必需
- 推荐
- 标题:提供标题的资源绑定消息 ID。
- 描述:提供描述的资源绑定消息 ID。
- 步骤参数:与参数的指导原则相同,并且至少将一个参数设置为主要字段(缺省为非主要字段)。
- 可选
- enableAddRows:使用户能够向表添加行。缺省为 false。
结束语
本文概括介绍了 WebSphere Application Server 开发人员和堆栈产品开发人员都可以使用的命令框架,他们可以利用该框架编写不同类型的管理命令、任务命令和任务命令扩展。本文还包括一些详细的示例、引用信息和指导原则,以便帮助您继续简化和扩展应用服务器管理的功能。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Code sample | cmdframework-sample.jar | 20 KB | HTTP |
|---|
参考资料 学习
获得产品和技术
作者简介  | |  | Leigh Williamson 是 IBM 的一名高级软件架构师。作为 WebSphere Application Server 的系统管理架构师,他目前负责 WebSphere Application Server 产品管理能力的发展。 |
 | |  | John Chang 是 IBM 的顾问软件工程师,在位于奥斯汀的 WebSphere Application Server 开发部门工作。在加入 WebSphere Web Services 团队之前,John 在 WebSphere 安全团队工作,主要从事 WebSphere Web Services 管理工作。 |
 | |  | Amy Lin 是 IBM 的一名软件工程师,在位于奥斯汀的 WebSphere System Management 团队工作。她目前是 wsadmin 脚本开发负责人,负责 WebSphere wsadmin 开发,以支持多种脚本语言(Jacl 和 Jython)。在此之前,她从事的工作是 J2EE 1.4、混合计算单元以及 WebSphere Application Server 4.0 和 6.0 版本的管理安全项目。她拥有德州大学奥斯汀分校的计算机工程硕士学位和计算机科学学士学位。 |
 | |  | Alex Huang 是 IBM 的顾问软件工程师,在位于德州澳斯汀的 WebSphere Application Server 开发部门工作。在加入 WAS System Management 团队之前,他从事 IBM Component Broker Object Services 开发工作多年,自从 WebSphere Application Server Version 5.0 发布以来,他一直在 SM 团队工作。他的工作重点是 WebSphere Application Server 配置。 |
 | |  | Vishwanath Venkataramappa 是 IBM 的高级软件工程师,在位于澳斯汀的 WebSphere Application Server 开发部门工作。在加入 WebSphere 系统管理团队之前,Vishwanath 在 WebSphere 安全团队工作,主要从事 WebSphere 配置工作。 |
对本文的评价
|  |