GEF Command creation and debugging tip

My particular GEF application has very complex and coordinated EditPolicy‘s. For example, on a LayoutEditPolicy‘s getAddCommand(), I have to dispatch other Requests and accumulate their resulting Commands. To be more concrete: when a child figure (and its associated component (model)) is moved from one figure to another there may be a set of other Requests that get fired off to perform functions such as changing the look of the child based on the new parent and adding and removing other children which provide context.

I following the advice of the GEF guru’s and modelled my application after the logic example. Unfortunately, the paradigm presented therein is not suitable for my situation for one primary reason: when “creating” Commands (I put that in quotes only to emphasize the fact that I’m talking about both construction and the calling of the appropriate setters) some of the elements may change at execution time due to other Commands that have been called.

For example:

LogicFlowEditPolicy.createAddCommand(...) {
AddCommand command = new AddCommand();
command.setChild((LogicSubpart)child.getModel());
command.setParent((LogicFlowContainer)getHost().getModel());
int index = getHost().getChildren().indexOf(after);
command.setIndex(index);
return command;
}

In my particular application the parent cannot be set when “creating” the Command since the component may be reparented (by other Commands) between the time that the Command is “created” and added to the CommandStack and the time that it is executed. Only on Command.execute() can the parent be retrieved from the child and be stored. (Note that the parent must be stored on Command.execute() for Command.undo() to function correctly. If Command.undo() was to retrieve the parent when it was called then that would obviously be the incorrect parent.)

Tracking down this situation was non-trival since there are two different factors that must be considered: when / where the Command was “created” and when / where the Command was executed. In my case, the “created” part was the most important. But as most of you know, the various EditPolicy methods are called quite frequently and it’s very very very hard to determine which Command “create” is the one that is actually added to the CommandStack and executed. (If you don’t already know, the various EditPolicy methods are also called to make sure that you can do something such as when components are selected ComponentEditPolicy.createDeleteCommand(..) is called to ensure that the component is deletable (i.e. Command.canExecute() is called). In this case the Command retrieved from ComponentEditPolicy.createDeleteCommand(..) is never actually exectued. (The Command from ComponentEditPolicy.createDeleteCommand(..) is only exectued when the DeleteAction occurs.) This can be very confusing the first time you stumble across it.)

To get around this problem of knowing which Command is actually executed and where it was “created” from, I used the following trick:

In the constructor of my Command I did the following:

public SomeConcreteCommand() {
...
this.constructionException = new Exception();
}

(where constructionException is declared as private Exception constructionException). Then in execute() I did the following:

public void execute() {
...
constructionException.printStackTrace(...);
...
}

What this does is allow me to see the stacktrace of where the Command was “created” only when it is executed.

(I should mention of completeness that this technique for storing an Exception() is very heavy weight and will affect performance. This is only suitable for development / debugging and should not be kept for production code.)

In summary: There may be cases in which some elements of a Command cannot be set when “created”. These elements can be retrieved and stored when Command.execute() is called. To facilitate debugging Commands it may be useful to store an Exception created on construction of the Command and display the stacktrace of the Exception when Command.execute() is called.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s