AX2012: Events (I)

One of new concepts in Dynamics AX 2012 are events and event handling. It was announced in advance that it will be possible to “hang” an event handler before and after every method, so let’s take a look at what it means in practice.

New Event Handler SubscriptionYou can choose New Event Handler Subscription in the context menu on methods on classes and tables (that’s true for both instant and static methods but not for display and edit methods). It creates a subnode of the method, named EventHandler1 by default.

Event Handler

Event Handler Subscription PropertiesEvent Handler Subscription defines a class and a method to call, whether it will be called before or after the handled method and whether the calling class is implemented in X++ or in .NET.

Pre-event handler is allowed to read and modify input parameters of the method; post-event handler can read and modify a return value. In both cases it’s possible to work with the object state (if the calling method is instant).

A single method can combine pre- and post-events and can contain more than one method for handling each type of event. So it’s possible to have three event handlers called before the method and two handlers called after its end. Handlers are called sequentially and its order is defined by the order of AOT nodes.

Handlers

A handler can be created by selecting New > Pre- or post-event handler from the context menu on a class. What is created is a completely normal method, so it can be also written manually, from a template etc.
A handler is a public static method with return type of void (dealing with a return value works in another way; see later). It accepts one parameter of XppPrePostArgs type or it has the same parameters as the handled method. The usage of XppPrePostArgs is more complicated and it disallow run-time parameter checks, but it makes lots of important properties available.

The declaration doesn’t distinguish between pre-event and post-event handlers, therefore a single handler can be used both before and after the handled methods. Obviously, not all functions make sense in both contexts – e.g. return value setting has no effect in a pre-event handler. Whether a handler is called as a pre- or post-event handler can be determined by XppPrePostArgs.getCalledWhen(). (And I would personally recommend to clearly manifest that a particular handler is intended for a single case only, e.g. by Debug::assert(_args.getCalledWhen() == XppEventHandlerCallerWhen::Post);.)

Pre-event handler

Pre-event handler in AX2012 represents a method called before the handled method. It’s called after an evaluation of method header (setting of default parameter values) but before running of method body.
It allows to read and modify method parameters and to work with the state of the object, e.g. to call parm* methods.

Example: handler declaration

//handler of run() method
public static void runHandler() //same parameters as run() = none
public static void runHandler(XppPrePostArgs _args) 
 
//handler of run(int _iteration) method
public static void runHandler(int _iteration) //same parameters as run()
public static void runHandler(XppPrePostArgs _args)

Example: Working with parameters in XppPrePostArgs

public static void runHandler(XppPrePostArgs _args)
{
    //getting value - by parameter name
    int iteration = _args.getArgs('_iteration');
    //getting value - by parameter order
    int iteration = _args.args().valueIndex(1);
 
    if (iteration > 100)
    {
        //setting parameter value
        _args.setArg('_iteration', 100);
    }
}
Post-event handler

Post-event handlers run after the end of the handled method, but before returning the value and control to the calling code. So a handler is allowed to read the return value (e.g. for logging) and possibly to change it. It can also work with the state of the calling object (see the example).

public static void validatePostHandler(XppPrePostArgs _args)
{
    SomeTable someTable;
 
    //Read return value
    if (_args.getReturnValue())
    {
        //Get calling object
        someTable = _args.getThis();
 
        if (someTable.SomeField == '')
        {
            warning("Missing value");
            //Set return value of the original method
            _args.setReturnValue(false);
        }
    }
}

Debugging

Naturally, you can insert breakpoints to the handling methods, however you can also step in the code, for example you can go into a post-event handler from the closing bracket on the handled method, using Step Into (F11).

Conclusion

I’m not sure what was the primary motivation for creating this functionality, in any case it allows us to reduce dependencies between objects and perform some types of changes in classes or tables without changes in their code. And where is no change in code, there cannot be a code conflict (conflicts on the AOT node level are much easier to resolve).

Events in Dynamics AX 2012 offers much more possibilities – I’ll try to pick up the thread as soon as possible.

3 Comments

  1. As I have pointed out on my blog, it is VERY important people rename the name of that handle subscription. Please do not leave this as “EventHandler1”, that cancels out the model store / event handler benefits.

  2. I absolutely agree, good names are crucial in all cases.
    However my picture above just illustrates the text “[subnode is] named EventHandler1 by default”.

Comments are closed.