Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

IBM WebSphere Developer Technical Journal: Administrative Command Framework Programming Guide for WebSphere Application Server

Leigh Williamson, System Management Architect, IBM
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 (jchang3@us.ibm.com), Advisory Software Engineer, IBM
John Chang 是 IBM 的一名顾问软件工程师,在奥斯汀从事 WebSphere Application Server 开发工作。在加入 WebSphere 系统管理团队之前,John 曾在 WebSphere 安全性团队工作,主要研究 WebSphere 配置。
Amy Lin (amylin@us.ibm.com), Staff Software Engineer, IBM
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 (alexh@us.ibm.com), Advisory Software Engineer, IBM
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.
Vishwanath Venkataramappa (vish@us.ibm.com), Senior Software Engineer, IBM
Vishwanath Venkataramappa is a senior software engineer with IBM working on WebSphere Application Server development in Austin. Vishwanath worked on the WebSphere security team before joining the WebSphere system administration team, where he works primarily on WebSphere configuration.

Summary:  The IBM® WebSphere® Application Server command framework wraps complicated administrative tasks into simple, user friendly command providers that a user can easily invoke to perform complex system management activities. This article is targeted to WebSphere developers who want to leverage administrative functions for creating command providers, which provide the command implementation for end users.

Date:  25 Oct 2006
Level:  Intermediate

Activity:  4553 views
Comments:  

From the IBM WebSphere Developer Technical Journal.

Introduction

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
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)
    • Parameter(s)

  • TaskCommand(s)
    • Parameter(s)
    • Step(s)
      • Parameter(s)

  • TaskCommandExtension(s)
    • Step(s)
      • Parameter(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:

Commands

Admin command

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 nameDescriptionTypeDefault valueRequired
    VersionThe version of the command implementation.string--false
    PriorityThe 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
    supportLocalModeThe 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.booleantruefalse
    isTargetObjectRequiredThe isTargetObjectRequired flag indicates if target object must be set for the command.booleantruefalse
    targetObjectTypeThe type of target object. Only String and javax.management.ObjectName are supported.string-- false
    targetObjectConfigTypeThe 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 nameDescriptionTypeDefault valueRequired
    TypeThe fully qualified class name for the command parameter.string-- true
    requiredIf the parameter value is required or not.booleanfalsefalse
    configAttributeIf the parameter maps directly to a config attribute.String-- false
    defaultValueDefault value for this parameter. Command framework will convert the String value to the proper type automatically.String-- false
    readonlyIf 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.booleanfalse false
    keyFieldIf the parameter is used to identify the row. This flag is ignored if the parameter is on a command or a non-table step.booleanfalsefalse


Task command

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 nameDescriptionTypeDefault valueRequired
    isTableThe flag indicates if the step parameter data is a table or not.booleanfalsefalse
    enableAddRowsThe 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 nameDescriptionTypeDefault valueRequired
    NameName of the task command to extend.string-- false
    baseTaskCommandName 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
    loadSequenceSequence of this task command extension. The higher sequence number will take precedence over the command with the same name.string-- false
    stepsExtension steps.CommandStepMetadata-- true


CommandGroup

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 nameDescriptionTypeDefault valueRequired
    CommandsThe 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 nameDescriptionTypeDefault valueRequired
    nameName of the command group to extend.string-- true
    CommandsThe names of commands that belong to this command group.list--true


Command provider

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 nameDescriptionTypeDefault valueRequired
    implClassFully qualified class name that implements the listed commands.string--true
    resourceBundleFully qualified resource bundle name for messagesstring--true
    commandGroupsCommand groups definitionmetadata--false
    CommandsCommands definitionmetadata--false
    taskCommandsTask commands definitionmetadata--false
    commandGroupExtsCommand group extension definitionmetadata--false
    taskCommandExtsTask command extension definitionmetadata--false



Creating commands

Implementing a new command consists of these general steps:

  1. 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.

  2. 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.

  3. 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:

  1. Command implementation for AdminCommand
  2. Command implementation for TaskCommand
  3. Package command implementation

1. Command implementation for admin command

  1. Create admin command definition
  2. Create admin command provider
  3. Create 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.

1c. Create admin command

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

  1. Create task command definition
  2. Create task command provider
  3. Create 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>

The command framework invokes all of a step's execute() methods, whether or not the parameters are required or supplied. The step's execute() logic should determine what to do.

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:

Table 8. Table step example
Contact typeContact address
home phonexxx-xxx-xxxx
work phoneyyy-yyy-yyyy
e-mail addressxxx@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);
   }
}

2c. Create task command

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"/>


Considerations for wsadmin

How to invoke

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.

Obtain online help

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 -interactive is 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.

Guidelines

The information, code samples, and recommendations included in this section are provided for reference as you begin to work with these commands.

Supported parameter types

Table 9. Supported parameter types for scripting in WebSphere Application Server V6.0.x
Primitive data typesOther Java types
string
boolean
character
integer
long
byte
short
float
double
Javax.management.ObjectName
Java.net.URL

Table 10. Supported parameter types for scripting in WebSphere Application Server V6.1.x
Primitive data typesOther 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}

Supported return types

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.

Table 11. Supported parameter types for wsadmin
Primitive data typesOther 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

Conventions

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.
  • 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.
  • 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).
  • 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.

Conclusion

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.


Resources

Learn

Get products and technologies

About the authors

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.

Vishwanath Venkataramappa is a senior software engineer with IBM working on WebSphere Application Server development in Austin. Vishwanath worked on the WebSphere security team before joining the WebSphere system administration team, where he works primarily on WebSphere configuration.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=445593
ArticleTitle=IBM WebSphere Developer Technical Journal: Administrative Command Framework Programming Guide for WebSphere Application Server
publish-date=10252006
author1-email=leighw@us.ibm.com
author1-email-cc=
author2-email=jchang3@us.ibm.com
author2-email-cc=
author3-email=amylin@us.ibm.com
author3-email-cc=
author4-email=alexh@us.ibm.com
author4-email-cc=
author5-email=vish@us.ibm.com
author5-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers