All Packages Class Hierarchy This Package Previous Next Index
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); } }
public abstract void setParms(InputEDStream parmStream) throws EDStreamFormatError
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.
InputEDStream
which contains the
in and inout parameter values.
public abstract void setTarget(Object object) throws InvalidTargetError
object
which represents the target of the
command.
public abstract Object getTarget()
object
that was set as the target.
public abstract int getState()
integer
representing the state where
0=parms needed, 1=ready, 2=done, 3=undone, 4=error.
public abstract void doCmd() throws CommandOnNotReadyError
public abstract void undo() throws CommandOnNotReadyError
public abstract void redo() throws CommandOnNotReadyError
public abstract void getResult(OutputEDStream resultStream) throws CommandOnNotReadyError, EDStreamFormatError
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.
OutputEDStream
which can accept
the return type, out and inout parameter values.
All Packages Class Hierarchy This Package Previous Next Index