From the IBM WebSphere Developer Technical Journal.
The WebSphere Application Server command framework provides a conceptual and logical structure for developing and executing commands that perform WebSphere Application Server administrative tasks. The command framework is based on the command pattern concept; a command pattern turns a request into a command object, which encapsulates the request data, and can later be executed in various execution environments by passing around the command object.
The WebSphere command framework lets developers implement more end-user-friendly and high level task-oriented commands for common -- yet complex -- administrative tasks, such as, configuration and application management service functions, execution of JMX MBeans, and so on. The command framework also provides basic command management functions, like command registration, command listing, and others.
The WebSphere command framework infrastructure separates the command logic from the command execution environment. This separation provides a consistent programming model for both command users and command providers across various command execution environments. Figure 1 illustrates the high level command execution flow.
Figure 1. High level command execution flow
There are two general usage scenarios for working with the command framework:
-
Using the wsadmin scripting tool
The WebSphere command framework enables the extention of wsadmin functionality without any additional wsadmin development effort. The wsadmin tool queries available admin commands and automatically surfaces them as wsadmin $AdminTask commands. When you execute a task command in interactive mode, you are lead through a series of steps which interactively collect input for a complex admin task.
-
Through application development
An application developer can also leverage the existing admin commands to provide admin functionality inside an application.
Programming interface concepts
The command framework accommodates two types of commands:
- Admin command - takes a certain number of input parameters and executes the command.
- Task command - consists of zero or more steps, with each step having its own parameters in addition to the task's parameters.
Every command is defined in a command definition file, which contains the following parts:
Command provider(s):
- Command group(s)
- Command(s)
- Command(s)
- Command(s)
- Parameter(s)
- Parameter(s)
- TaskCommand(s)
- Parameter(s)
- Step(s)
- Parameter(s)
- Parameter(s)
- TaskCommandExtension(s)
- Step(s)
- Parameter(s)
- Parameter(s)
- Step(s)
- CommandGroupExtensions
- Name
- Command(s)
A command definition file contains one or more command providers, each of which can have one of more command groups. Each command group can have one or more commands (admin or task or both types). An admin command has zero or more parameters. A task command has zero or more parameters and zero or more steps. Each step has zero or more parameters. A command provider can also include extensions to a task command provided by another command provider. A task command extension contains additional steps added to an already existing command.
Details on each of these command definition file elements is provided below:
The AdminCommand interface is the base for all of the commands in the command framework. It defines methods such as parameters listing/setting/getting, validation, and command execution. In the command framework, AbstractAdminCommand implements the AdminCommand interface. All the commands should extend the AbstractAdminCommand class.
-
CommandMetaData
CommandMetaData defines attributes for each command. Table 1 shows the attributes most used for the CommandMetaData.
Table 1. CommandMetaData Attribute name Description Type Default value Required Version The version of the command implementation. string -- false Priority The priority of the command. If there are multiple commands with the same name, the higher priority command definition overrides the lower level priority command definition. int -- false supportLocalMode The supportLocalMode flag indicates if the command works in local mode. A TaskCommand can support local mode only if every step in the task supports local mode. boolean true false isTargetObjectRequired The isTargetObjectRequired flag indicates if target object must be set for the command. boolean true false targetObjectType The type of target object. Only String and javax.management.ObjectName are supported. string -- false targetObjectConfigType The corresponding fully qualified config type for the target object. int -- False
-
ParameterMetadata
Each command can have parameters. If parameters are needed, then the provider needs to define the parameterMetadata under the commandMetadata.
Table 2. ParameterMetadata Attribute name Description Type Default value Required Type The fully qualified class name for the command parameter. string -- true required If the parameter value is required or not. boolean false false configAttribute If the parameter maps directly to a config attribute. String -- false defaultValue Default value for this parameter. Command framework will convert the String value to the proper type automatically. String -- false readonly If the parameter is read only. The default value is set as the parameter value. The provider can also set the value in the command implementation. boolean false false keyField If the parameter is used to identify the row. This flag is ignored if the parameter is on a command or a non-table step. boolean false false
The TaskCommand enables the provider to construct a complicated admin command with the use of multiple steps.
-
Command step
Multiple steps make up a task command. A command step is similar to the admin command; however, a command step cannot be executed independently.
-
CommandStepMetadata
CommandStepMetadata extends the commandMetadataData. In addition to the metadata defined in the commandMetadataData, commandStepMetadta also defines the following:
Table 3. CommandStepMetadata Attribute name Description Type Default value Required isTable The flag indicates if the step parameter data is a table or not. boolean false false enableAddRows The flag indicates if the step lets the user add or remove rows. This flag is ignored when the step is not a table. boolean false false
-
TaskCommandExtension
Each task can be extended by adding addition steps, or by overwriting existing steps. Task extension steps do not need to be defined inside the same admin-command-def.xml. They can be in the separate admin-command-def.xml in the separate package as long as the command framework runtime is able to find it.
Table 4. TaskCommandExtension Attribute name Description Type Default value Required Name Name of the task command to extend. string -- false baseTaskCommand Name of the base task command. If this is specified, a new task command which inherits all the interface and functionalities of a base command will be created with the additional functionalities. string -- false loadSequence Sequence of this task command extension. The higher sequence number will take precedence over the command with the same name. string -- false steps Extension steps. CommandStepMetadata -- true
A CommandGroup groups together related admin commands. A command provider can determine which commands to put in a group. Usually, commands with similar functions are grouped together.
-
CommandGroupMetadata
CommandgroupMetadata defines commands to be included in the command group.
Table 5. CommandGroupMetadata Attribute name Description Type Default value Required Commands The names of the commands that belongs to this command group. list -- true
-
CommandGroupExtension
CommandGroupExtension specifies the command group name in the name attribute and the list of command names in the commands attribute. A command provider can specify multiple CommandGroupExtension entries to add commands in various command groups.
Table 6. CommandGroupExtension Attribute name Description Type Default value Required name Name of the command group to extend. string -- true Commands The names of commands that belong to this command group. list -- true
The command provider provides the actual command implementation, and also specifies attributes for all the commands that the provider implements.
-
CommandProviderMetadata
CommandProviderMetadata is the top level element in the command definition. All the commands, groups, and extensions are under this element.
Table 7. CommandProviderMetadata Attribute name Description Type Default value Required implClass Fully qualified class name that implements the listed commands. string -- true resourceBundle Fully qualified resource bundle name for messages string -- true commandGroups Command groups definition metadata -- false Commands Commands definition metadata -- false taskCommands Task commands definition metadata -- false commandGroupExts Command group extension definition metadata -- false taskCommandExts Task command extension definition metadata -- false
Implementing a new command consists of these general steps:
-
Create a command definition file that describes the command metadata.
The command definition file is XML based, is to be named admin-command-def.xml, and has to be present in the META-INF directory of the JAR file containing the command provider and the command implementation. This JAR file must be in the classpath of the program that needs to execute the command. -
Create the command provider.
A command provider provides one or more commands. A command provider should implement methods to create and load the command that is provided by that provider. A command provider should implement the interfaces specified in com.ibm.websphere.management.cmdframework.provider.CommandProvider. -
Create the logic to execute the command.
The code developed to execute the command will depend on the command type: AdminCommand or TaskCommand.
Detailed examples for implementing both types of commands, and for packaging the command provider, commands, and command definition files are presented in the next sections:
- Command implementation for AdminCommand
- Command implementation for TaskCommand
- Package command implementation
1. Command implementation for admin command
1a. Create admin command definition
Suppose we need to create an admin command that displays "Hello World." We can create a command definition file as follows:
Listing 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> |
In Listing 1, there is one command provider. The implClass attribute defines the provider that implements the commands specified within its block. In this example, there is one command group (HelloWorld) and one command (helloWorld). Notice that the name of the command begins with a lowercase character. All commands should follow this convention. Also, the description and title of the command are useful to have when the command is executed in interactive mode using wsadmin, because these values are displayed to the end user. Notice that the targetObjectAllowed attribute should be set to false. By default, it is set to true, which requires specifying the targetObjectType. Since this command does not need any target object to be passed, we should set it to false.
Adding paramaters
The above command does not take any input parameters. Now, let us try to add some parameters to the HelloWorld command so it can process the input parameters, such as an individual's name, pets owned, and other properties, and display that information along with the Hello World message.
Listing 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> |
We added four parameters to the command. Each parameter has a field that specified the type of parameter that can be input, and another that specifies whether the parameter is optional or not. If the required field is set to false, the parameter is optional. By default, each parameter is required. Parameters can be of any standard Java type. In this case, we used String, Properties, Array and ObjectName, but other types, such as Integer, Boolean, and others, can also be used. Again, notice that description and title are useful when the command is run in interactive mode using wsadmin.
1b. Create admin command provider
An admin command provider should provide methods for creating and loading commands.
-
createCommand() - called by the command framework code to create a command provided by the provider. This method should return an implementation of the AbstractAdminCommand that executes the command specified in the command metadata that is passed to the create method.
-
loadCommand() - called by the command framework to load a command provided by the provider. This method should return an implementation of AbstractAdminCommand that executes the command specified in the command data passed to the load method.
A command can be saved to a file at any time using command.save(outputstream), and loaded again later using CommandMgr.loadCommand(inputStream). When a loadCommand is used to reload a previously saved command, this method will be called by the command framework. Listing 3 shows an example of the HelloWorldProvider that provides the helloWorld command:
Listing 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());
}
} |
In this example, when a createCommand or loadCommand method is called, the provider simply creates a new object of type HelloWorldCommand and returns that object. The HelloWorldCommand class implements AbstractAdminCommand. Notice that it uses the name of the command to determine which command is to be created or loaded. Since there is only one command in this example provider, that check is not necessary.
An admin command should extend AbstractAdminCommand, and should provide two types of constructors for its provider to create and load the command. The constructor to create a command should accept CommandMetadata as the only input parameter. The constructor for loading a command should accept CommandData as the only input parameter. It should also implement the execute() method that contains the main command logic. All commands should provide this method, since it will be called by the 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 parameter types are correct. Any additional validation required by the command should be performed in this method.
The result of the command should be set in the command before returning from this method. In case of any error executing the command, an exception should be set in the command result. An exception set in the command result indicates a failure to execute the command.
Listing 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. Command implementation for task command
2a. Create task command definition
Suppose the command provider wants to write a Hello World command that takes input (person's name and country name) in a separate step and say Hello World to that person. We can create a task command that has one step (getPerson) with parameters as shown in Listing 5. There are two parameters in the step, one for name (personName) and another for country (countryName). A task command can have zero or more steps. Here, there is one step.
Listing 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> |
This example is similar to the admin command example, except that here, the
command is defined within
<taskCommands></taskCommands>,
and steps are defined within the task command with
<steps></steps>. We
don't have any parameters here for the taskCommand
(helloWorldTask) itself, but you can add parameters if you wish.
helloWorldTask has a step getPerson and that step requires two parameters
for the command. The required attributes for this step's
parameters can be set to false if the parameters are optional.
Table step
A table step is a step within a task command that takes input parameters in the form of a table (with multiple rows and columns). A table step is similar to a command step and has list of parameters. Each parameter in a table step represents a column. Each set of values assigned to step parameters represent one row. Multiple sets of parameter values can be assigned to form a table with many rows. For example, we can add a table step to the helloWorldTask command that contains person's contact information in the form of a table:
| Contact type | Contact address |
|---|---|
| home phone | xxx-xxx-xxxx |
| work phone | yyy-yyy-yyyy |
| e-mail address | xxx@yyy.com |
Such information can be obtained using a step table as shown in Listing 6.
Listing 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> |
Note that
<table>true</table>
is all that is required to make the step a table step. The keyField
attribute is required to represent one or more keys that can be used to
search the table entries.
Extending task commands by adding additional steps
A task command can be extended with additional steps. Normally, this type of extension is required to perform additional tasks for the base command. Listing 7 shows an example of how to extend a task command by adding a new step. In this example, a new step, additionalInfo, is added to the helloWorldTask command by command provider HelloWorldExtProvider. This extended step obtains additional customer information, such as a person's hobbies and sports preferences.
Listing 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> |
The command extension definition is similar to the task command definition,
except that the steps used for extending the base command are specified
within the
<taskCommandExts> </taskCommandExts>
block. The name element specifies the base command that these steps
extend.
Listing 8 shows the complete example of a command definition file that has both the admin command and task command.
Listing 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. Create task command provider
A task command provider should provide methods to create and load commands similar to the admin command. Since task commands also contain steps, it should also provide methods to create and load steps.
A task command provider should implement these methods:
-
createCommand() - called by the command framework code to create a command provided by this provider. This method should return an AbstractAdminCommand implementation that executes the command specified in the command metadata passed to the createCommand() method.
-
loadCommand() - called by the command framework to load a command provided by this provider. This method should return an AbstractAdminCommand implementation that executes the command specified in the command data passed to the loadCommand() method.
-
createCommandStep() - called by the command provider to create a step that is provided by this provider. This method should return an AbstractCommandStep implementation that executes the step specified in the step metadata passed to the createStep() method.
-
loadCommandStep() - called by the command framework to load a step that is provided by this provider. This method should return an AbstractCommandStep implementation that executes the step specified in the step data passed to loadStep() method.
Listing 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);
}
} |
Initializing table step
A table step occasionally needs to initialize the table with some default values. The command provider can initialize the table step by adding new rows at the time of command creation. The rows added to the table during command initialization will be available to the client and can be deleted or modified before the execution of the command. Additionally, more new rows can be added before the command is executed.
Listing 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
}
}
} |
In Listing 10, setInitialValues() method, which is called during command creation, adds two rows to the table step. It gets the table step from the task command first, then constructs a row. Each row consists of all the required parameters of the step and its values. In this case, there are two required parameters, type and value, which represent contact type and contact address. After constructing a row that has all the required parameters for the step with its values, it is added to the table using the initializeRow() method at the proper row index.
Task command extension provider
An extension command provider is similar to a task command provider, except that the extension command provider only needs to provide methods to create and load steps. This is because the extension command provider is meant to extend a base command by adding additional steps. However, an extension command provider can also include base commands of its own. In other words, a command provider can contain its own base commands and extend other commands. This provider should implement the create and load of both commands and steps provided by the provider.
Listing 11 shows an example of a task command extension provider.
Listing 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);
}
} |
A task command should extend AbstractTaskCommand. Just like an admin command, a task command should provide constructors to create and load commands. The constructor to create a command should accept TaskCommandMetadata as the only input parameter. The constructor for loading a command should accept CommandData as the only input parameter.
Unlike an admin command, a task command should not implement an execute() method. This is because: AbstractTaskCommand implements the execute() method, then the execute() method of the AbsractTaskCommand calls the beforeStepsExecuted() method of the task command and then all of the step's execute() methods, and then calls the afterStepsExecuted() method of the task command. If this execute() method is overridden, the steps will not be executed automatically. Therefore, a task command should just implement either beforeStepsExecuted() or afterStepsExecuted() or both, and then implement the command's logic.
If the execution of the steps depends on the result of the task command execution, then the task command should use the beforeStepsExecuted() method. In contrast, if the task command depends on the result of the steps executing, then the afterStepsExecuted() method should be used to implement the command logic.
The validate() method is called before execution of the command and its steps, and can be used to validate the input parameters. The command framework calls the method to validate the command first, and then to validate the steps. When the validate method is called, the parameter types and the required parameters are checked by the command framework, so there is no need to call super.validate() later.
For task commands, an empty command result is set before invoking the execute() method. For steps, however, the result is not set. Steps can either use the command's result or set its own result. In Listing 12, the steps use their task command's result and then add to it.
Listing 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();
}
} |
Creating steps within a task command
All steps of a task command should extend AbstractAdminStep. All steps should provide two constructors to create and load the command step. The command provider will use these constructors to create or load a step.
The constructor to create a step takes its parent task command and step metadata as input parameters. The constructor to load a step takes its parent task command and step data as input parameters.
-
Validate() - implemented by the step should call super.validate() first to make sure the parameters are of the proper type and all the required parameters are supplied. Any additional validation can be performed.
-
ExecuteStep() - used by the step to perform any task related to the step. This method should be implemented by all steps.
The result of a step's execution can be set either in the step's result or in the parent task command's result. In Listing 13, the execute() method extracts the parent task command's result and sets the result of the operation by appending the step result to the task command's result.
Listing 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);
}
} |
Table step implementation
Table step implementation is similar to implementing a typical command step and has the same set of methods. The only difference is the way in which the parameters are obtained from the table. Listing 14 shows the complete example of the table step for the HelloWorldTask.
Listing 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);
}
} |
In Listing 14, the execute() method first obtains the number of rows of parameters that are input to the step. For each row, the corresponding parameter values are obtained using the same getParameter() method; the only exception is that rowIndex is passed to the getParameter() method.
Also, notice that the initializeRow() method needs to be overwritten in the step command implementation if the provider wants to initialize the table with some rows while creating the command. This needs to happen because the initializeRow in the super class has protected access and cannot be directly called from the provider implementation.
Creating a command extension
An extension of a command consists simply of adding an additional step. The additional step implementation is similar to the implementation of a task command step. An example is shown in Listing 15. As you can see, the HelloWorldExtStep implementation is no different from the GetPerson step; it implements the same set of methods and updates the task's command result after execution.
Listing 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. Package command implementation
Packaging the command provider, commands, and command definition files is essentially done by creating a JAR file and placing it in the classpath.
The JAR file should consist of the command provider implementation, the command implementation, and the command definitions:
- META-INF/admin-command-def.xml
- Provider.classes
- Command.classes
For example:
Listing 16
META-INF/admin-command-def.xml HelloWorldProvider.class HelloWorldTaskProvider.class HelloWorldTaskCommand.class HelloWorldCommand.class HelloWorldTaskCommand.class HelloWorldExtStep.class |
Place the JAR file in the classpath of the program that needs it. For example, for wsadmin to use these new commands, the JAR file needs to be placed in the $WAS_HOME/classes directory or the $WAS_HOME/lib directory.
In WebSphere Application Server V6.1, if the commands are added in a new JAR file, then that JAR file's plugin.xml file should have the following extension defined:
<extension id="Runtime" point="com.ibm.wsspi.extension.admin-command-def"/>
Use AdminTask object to run an admin command
Admin commands are available in both connected and local modes. You can
start wsadmin without having a server running by using the
-conntype NONE option with the wsadmin tool. If
a server is currently running, do not run AdminTask commands in local
mode, because any configuration changes made in local mode are not
reflected in the running server configuration.
Invoke admin command or task command in different modes
The admin commands or task command can be invoked in batch or interactive
mode, in a script, or from an operations command prompt using the wsadmin
-c command.
Online help is available for admin commands when you need general information for the AdminTask object and associated commands:
Using Jacl: $AdminTask help
Using Jython: Print AdminTask.help()
help -commands- Lists all the admin commands.help -commandGroups- Lists all the admin command groups.help commandName- Displays detailed information for the specified command.help commandName stepName- Displays detailed information for the specified step belonging to the specified command.help commandGroupName- Displays detailed information for the specified command group.
There are various ways to invoke an admin command:
-
commandName- Invokes an admin command that does not require any argument. -
commandName targetObject- Invokes an admin command with the specified target object string; for example, the configuration object name of a resource adapter. The expected target object varies with the admin command invoked. Use the help command to get information on the target object of an admin command. -
commandName options- Invokes an admin command with the specified option strings. This invocation syntax is used to invoke an admin command that does not require a target object. It is also used to enter interactive mode if -interactive mode is included in the options string. -
commandName targetObject options- Invokes an admin command with the specified target object and options strings. If-interactiveis included in the options string, then interactive mode is entered. The target object and options strings vary depending on the admin command invoked. Use the help command to get information on the target object and options.
The information, code samples, and recommendations included in this section are provided for reference as you begin to work with these commands.
| Primitive data types | Other Java types |
|---|---|
| string boolean character integer long byte short float double | Javax.management.ObjectName Java.net.URL |
| Primitive data types | Other Java types |
|---|---|
| string boolean character integer long byte short float double | Javax.management.ObjectName Java.util.Properties String[] Java.net.URL |
Invoke admin command
Listing 17. Using Jacl interactive mode
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 |
Listing 18. Using Jacl batch mode
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 |
Where:
- personName is defined as a String parameter.
- personalInfo is defined as a java.util.Properties.
- pets is defined as String[].
- personID is defined as javax.management.ObjectName.
Listing 19. Using Jython interactive mode
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' |
Listing 20. Using Jython batch mode
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' |
Invoke task command. See Listing 21 for using Jacl interactive mode.
Listing 22. Using Jacl batch mode
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} |
Listing 23. Using Jython interactive mode
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}' |
Listing 24. Using Jython batch mode
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} |
The wsadmin tool will convert different admin command return types to string format, which means all admin command results will be displayed in string format. Table 11 lists all wsadmin supported return types in WebSphere Application Server V6.0 and V6.1x.
| Primitive data types | Other Java types |
|---|---|
| string (with example) 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[]) |
Listing 25
Return type: String:
Using Jacl:
wsadmin>$AdminTask helloWorld {-personName John}
Using Jython:
Wsadmin>print AdminTask.helloWorld('[-personName John]')
Hello World John |
Listing 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] |
Listing 27
Return type: String[]:
Using Jacl:
wsadmin>$AdminTask helloWorld {-pets dog;cat}
Using Jython:
Wsadmin>print AdminTask.helloWorld('[-pets dog;cat]')
dog
cat |
Listing 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] |
Listing 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 |
Listing 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 |
Naming guidelines
- Command name: lowerCamelCase; for example,
helloWorld - Command parameter name: lowerCamelCase; for example,
personName, personInfo, personID - Command step name: lowerCamelCase; for example,
personName, countryName
Programming guidelines
- Command
- Recommended
- Title: resource bundle message ID to provide title.
- Description: resource bundle message ID to provide one
to two sentence description of your
command.
- Recommended
-
Target object
If there is no target object for your command:
- Required
- TargetObjectAllowed set to false.
- <targetObjectAllowed>false</targetObjectAllowed>.
Else, if there is target object:
- Optional
- TargetObjectDescription: resource bundle message ID to provide description. Description should include what is expected as the input.
- TargetObjectTitle: resource bundle message ID to provide title.
- TargetObjectRequired: if the target object is required.
- TargetObjectType: the type of target
object.
- Required
-
Parameters
- Recommended
- Title: resource bundle message ID to provide title.
- Description: resource bundle message ID to provide description; should include what is expected as the input.
- Optional
- Provide input examples in the description if the input value is not obvious.
- Provide default values if applicable.
- Set to read only if applicable (default is NOT read only).
- Set to required if applicable (default is NOT
required).
- Recommended
-
Steps
Non-table step:
- Recommended
- Title: resource bundle message ID to provide title.
- Description: resource bundle message ID to provide description.
- Step parameters: same guideline as outlined in "Parameters".
Table step:
- Required
- Table: set to true.
- Recommended
- Title: resource bundle message ID to provide title.
- Description: resource bundle message ID to provide description.
- Step parameters: same guideline as Parameters, and have at least one parameter set as key field (default is NOT key field).
- Optional
- enableAddRows: enable user to add rows to table.
Default is false.
- enableAddRows: enable user to add rows to table.
Default is false.
- Recommended
This article offered a high level introduction to the command framework that can be exploited by WebSphere Application Server developers, and developers of stack products, for writing different types of admin commands, task commands, and task command extensions. Detailed examples, reference information, and guidelines were included to help you with your continued work in simplifying and expanding the capabilities of your application server administration.
Learn
-
System management for WebSphere Application Server V6:
New AdminTask commands make wsadmin scripting less complex and more practical -
Introduction to administrative scripting (wsadmin)
-
IBM developerWorks WebSphere Application Server zone
Get products and technologies
Leigh Williamson is a STSM Software Architect for IBM. As System Management Architect for WebSphere, he currently leads the evolution of WebSphere Application Server product management capabilities. He can be reached at leighw@us.ibm.com.
John Chang 是 IBM 的一名顾问软件工程师,在奥斯汀从事 WebSphere Application Server 开发工作。在加入 WebSphere 系统管理团队之前,John 曾在 WebSphere 安全性团队工作,主要研究 WebSphere 配置。
Amy Lin is a Staff Software Engineer at the IBM Austin on the WebSphere System Management team. She is currently the wsadmin scripting development lead and responsible for WebSphere wsadmin development to support multiple scripting languages (Jacl and Jython). Prior to this, she has worked on J2EE 1.4, mixed cell and admin security projects for WebSphere Application Server 4.0 and 6.0 releases. She holds a Master of Science degree in Computer Engineering and Bachelor of Science in Computer Science degree from the University of Texas at Austin.
Alex Huang is an advisory software engineer with IBM working in the WebSphere Application Server development organization in Austin, Texas. He has worked in the IBM Component Broker Object Services development for several years before joining the WAS System Management team, and has been with SM team since WebSphere Application Server Version 5.0. The main focus of his work is in WebSphere Application Server configuration.




