Interface COM.ibm.jaws.mofw.CommandOn
All Packages  Class Hierarchy  This Package  Previous  Next  Index

Interface COM.ibm.jaws.mofw.CommandOn

public interface CommandOn
extends Object
A CommandOn object contains a procedure. Its methods allow its target object and parameters to be set, its invocation to be started, undone and redone, and its results to be obtained.

The basic use for a CommandOn object in OOD is to map a transition in a state-transition diagram. This object allows complex workflows to be modelled as well as give them Managed object properties like persistence, transactions and security.

Another use for a CommandOn object is to provide for asynchronous method invocations, where a CommandOn object is initialized in one thread, executed in another and the results examined in yet another.

Another use for a CommandOn object is to provide for compensating transactions on a method. That is, if an OP will provide CommandOn objects (with undo methods) representing update behaviors on an object, then BaseCollections can use them to provide for recoverability rather than store before images, etc.

Another use for CommandOn objects is to enable wrappering of legacy code that may not lend itself well to being decomposed into objects. Related CommandOn objects (those with similar targets or parameters) could be logically composed into higher level "application objects."

Another use for CommandOn objects is to manage secure distribution through a simple "command server" that expects that the AA has made command object classes available in a specified package. The name of the class is manufactured via data available in the IIOP message:

    interfaceName_methodName

If a class by this name cannot be found, then an exception result is returned via the IIOP result. A simple server could be written thusly:

     BaseCollection root = new BootStrapBC();
     IIOPPortIterator port = new IIOPPortIterator();
     IIOPMessageStream message;
     IIOPReplyStream result;
     while ((message = port.getNext()) != null)
     {
     // Get the reply stream for any kind of result
         result = message.createReply();
     // May want to do this in a separate thread...
         try {
         // Get the command instance from info in message
             String interfaceName = message.getInterface();
             String methodName = message.getMethod();
             Class commandClass = Class.forName(
                 interfaceName + "_" + methodName
             );
             CommandOn command = commandClass.newInstance();
         // Set the target and the parms
             command.setTarget(root.resolve(message.getKey(), interfaceName));
             command.setParms(message);
         // Invoke the command and send the results 
             command.doCmd();
             command.getResult(result);
             result.send();
         }
         catch (Throwable e) 
         {
         // Send the exception
             result.setException(e);
             result.send();
         }
     }              

CommandOn objects like the above can be easily generated by an AA for any method on a Java object:

    interface Trip {
         Reservation addReservation(
            TravelService t,
            Date startDate,
            short duration,
            Member m
         );
    }

Would result in:

    interface Trip_addReservation implements CommandOn {
        private Trip target = null;
        private TravelService t = null;
        private Date startDate = null;
        private short duration = 0;
        private Member m = null;
        private Reservation result = null;
        private Throwable error = null;
        private short state = 0;
        public Trip_addReservation(
            TravelService t,
            Date startDate,
            short duration,
            Member m
        ) 
        {
           setParms(t, startDate, duration, m);
        }
        public void setParms(
            TravelService t,
            Date startDate,
            short duration,
            Member m
        )
        { 
            this.t = t; 
            this.startDate = startDate; 
            this.duration = duration;
            this.m = m;
            result = null;
            state = 1;
        }
        public void setParms(InputEDStream parmStream)
        {
            t = (TravelService)parmStream.readManaged(null, "TravelService");
            startDate = (Date)parmStream.readObject("Date");
            duration = parmStream.readShort();
            m = (Member)parmStream.readManaged(null, "Member");
            state = 1;
        }
        public void setTarget(Object trip) 
        {
            target = (Trip)trip;
            if (state > 1) state = 1;
        }
        public void doCmd() 
        {
            if (state != 1 || target == null) throw new CommandOnNotReadyError();
            try {
                result = target.addReservation(t, startDate, duration, m);
                state = 2;
            }
            catch (Throwable e)
            {
               error = e;
               state = 4;
            }
        }
        public void undo()
        {
            if (state != 2) throw new CommandOnNotReadyError();
        // Replace the following with your own code...
            throw new NotSupportedException();
        // Don't forget to change the state to allow redo...
            state = 3;
        }
        public void redo()
        {
        // In the default implementation this if will always be true
        // because the undo() will always fail.  Some implementors
        // might change this to make do/redo equivalent (see doCmd()).
            if (state != 3) throw new CommandOnNotReadyError();
        // Replace the following with your own code, but the default
        // is to reexecute the do.
            result = target.addReservation(t, startDate, duration, m);
            state = 2; 
        }
        public Reservation getResult()
        {
            if (state == 4) throw error;
            if (state != 2) throw new CommandOnNotReadyError();
            return result;
        }
        public void getResult(OutputEDStream resultStream)
        {
            if (state == 4) throw error;
            if (state != 2) throw new CommandOnNotReadyError();
            resultStream.writeManaged(result);
        }
   }

Method Index

 o doCmd()
Use this method to execute the command after the target and parameters have been set.
 o getResult(OutputEDStream)
Use this to "generically" get the results of executing a method.
 o getState()
Use this method to get the current "state" of the command.
 o getTarget()
Use this method to get the context against which the command was executed when the target was set by some other method (e.g.
 o redo()
Use this method to redo the function of an undo.
 o setParms(InputEDStream)
Use this method to set parameters "generically" from an InputEDStream.
 o setTarget(Object)
Use this method to set a context for the command.
 o undo()
Use this method to reverse the effects of a doCmd().

Methods

 o setParms
  public abstract void setParms(InputEDStream parmStream) throws EDStreamFormatError
Use this method to set parameters "generically" from an InputEDStream.

Usually, an OP/AA will make a special subclass with a specific signature tailored to the method represented by the CommandOn object. Therefore, many clients will simply use those specific methods. However, some implementations (e.g. ORBs and OA's) will be getting the parameter data "from the wire" (i.e. an IIOP stream).

Another case where this form could be useful to a client is when a special user interface stream has been built that marshalls values straight from a panel.

Parameters:
parmStream - the InputEDStream which contains the in and inout parameter values.
Throws: EDStreamFormatError
is thrown if the InputEDStream does not contain the in and inout parameters of the method represented by the command.
 o setTarget
  public abstract void setTarget(Object object) throws InvalidTargetError
Use this method to set a context for the command. Usually the implementor will narrow the object to the specific target type so a casting exception may be thrown by some implementations.
Parameters:
object - the object which represents the target of the command.
 o getTarget
  public abstract Object getTarget()
Use this method to get the context against which the command was executed when the target was set by some other method (e.g. in a dispatchAll() on a QueryableCollection or a dispatch() on a KeyedCollection).
Returns:
the object that was set as the target.
 o getState
  public abstract int getState()
Use this method to get the current "state" of the command.
Returns:
an integer representing the state where 0=parms needed, 1=ready, 2=done, 3=undone, 4=error.
 o doCmd
  public abstract void doCmd() throws CommandOnNotReadyError
Use this method to execute the command after the target and parameters have been set. To execute the command again requires that either the setTarget or the setParms be set. There is also the expectation that the doCmd will capture any of the "natural" exceptions of the associated code in order to throw them on the getResult() call.
Throws: CommandOnNotReadyError
is thrown when a setParms() and setTarget() must preceed a doCmd().
 o undo
  public abstract void undo() throws CommandOnNotReadyError
Use this method to reverse the effects of a doCmd(). This may not be supported on some commands, so expect an exception.
Throws: CommandOnNotReadyError
is thrown when an undo() is invoked prior to a doCmd() (or redo() after another undo()).
 o redo
  public abstract void redo() throws CommandOnNotReadyError
Use this method to redo the function of an undo. This may not be supported on some commands, so expect an exception.
Throws: CommandOnNotReadyError
is thrown when an redo() is invoked prior to a undo() after a do().
 o getResult
  public abstract void getResult(OutputEDStream resultStream) throws CommandOnNotReadyError, EDStreamFormatError
Use this to "generically" get the results of executing a method. Most subclasses will probably have a specific getResult for the return type, but some commands, especially CORBA style (with inout and outs beyond just a return value) do not map well to specific return types. In this case, and in the case of special UI streams, the generic form is quite useful.

If the doCmd resulted in an exception (thrown by the code itself), the getResult will actually throw that exception to enable a reply thread different from the doCmd thread to process the exception.

Parameters:
resultStream - the OutputEDStream which can accept the return type, out and inout parameter values.
Throws: CommandOnNotReadyError
is thrown when an getResult() is invoked prior to a doCmd() (or a redo() after an undo()).
Throws: EDStreamFormatError
is thrown if the OutputEDStream cannot accept the return type, inout, and out values of the command.

All Packages  Class Hierarchy  This Package  Previous  Next  Index