Skip to content
Archive of entries posted on March 2011

Creating standard exceptions

One of things I really miss in X++ is any reasonable way to handle exceptions. AX doesn’t know exceptions as objects, it has only an enumeration type Exception and, morover, programmers should basically throw only Error, UpdateConflict and UpdateConflictNotRecovered explicitely, which effectively prevents any handling based on the type of exception.

We can hardly do anything with X++ features, but there is another thing related to objects of exception, which is resolvable: Many exceptions can be qualified as exceptions of the same standard type (e.g. an unexpectedly empty field in a buffer), but one still must find/remember a suitable error message for each such type. I would appreciate something like in C#:

throw new ArgumentNullException("itemId");
//Exception message:
//Value cannot be null.
//Parameter name: itemId

Simply, not to care about the exact error message and to have to remember the right type of exception only.

I made one experimental implementation (link to .xpo at the end) – please note that it is more an illustration to think about than a completed library of exceptions.

Originally I started with a bit more complicated design, but is crystalized to a very simple interface during the refactoring. Basic usage looks like this:

throw exception(new ArgumentEmptyException('_itemId'));

Quite readable, isn’t it?

The exception is a method in the Global class, equivalent to the error() method, but accepting a single parameter only – an object of the SysException type. As error(), it returns a value of the Exception enumeration type, which is subsequently used in the throw statemement.

The base of the exception hierarchy is the SysException class. It has the following main members:

class SysException
    new() //parameterless constructor
    str message() //returns error message
    Exception show() //write exception to infolog

SysException contains a basic implementation so the derived exceptions don’t need to override any methods (although they should). The class of exception in the following example declares nothing but extends SysException:

throw exception(new DeveloperIsDumbheadException());
//Infolog: Exception of type 'DeveloperIsDumbheadException' was thrown.

Exceptions can provide their own text by overriding the message() method.

public str message(){ return "Oops"; }

In fact, SysException has two more properties, HelpUrl and InfoAction. They can be set either by accessor methods or by using a method chaining. My effort was to allow to set all properties by accessor methods, but make it unnecessary.

//using a usual accessor method
SysException ex = new DeveloperIsDumbheadException();
throw exception(ex);
//the same thing via a method chaining
throw exception(new DeveloperIsDumbheadException().withHelpUrl(""));

Constructors of derived classes can accept optional parameters, as in the case of ArgumentEmptyException mentioned at the beginning.

In the following example you can find all derived exceptions contained in the .xpo. There is not many of them, because they only served for the architecture verification so far.

//Infolog: Value of parameter '_userId' is not valid.
throw exception(new ArgumentException("_userId"));
//Infolog: Parameter '_userId' cannot be empty.
throw exception(new ArgumentEmptyException("_userId"));
//Infolog: Field EmplId must be filled in.
throw exception(new FieldEmptyException(fieldStr(EmplTable, EmplId)));
switch (numberSeqModuleEnumValue)
    //(...) processing of known elements
    default: //invalid value or value not known at the time of program writing
        //Infolog: Enum element 'PRODCOM' is not valid.
        throw exception(new InvalidEnumException(numberSeqModuleEnumValue));

It’s clear that my goal wasn’t to replace all exception throwing – if you need a specialized error message, use the same approach as before. But if you are throwing a “standardized” exception, you can use an object of SysException type and don’t bother with the construction of the error message. Potentially you will also be able to change the label on a single place, to log a specific type of errors and so on.

The source code is available here.

Just a note, most of these exceptions use hard-coded texts and not labels and the .xpo contains two standard objects: classes Global and SysInfoAction_Editor.

Independent transaction in AX

Sometimes we need to write some data into a database independently on the currently running DB transaction. For example, we want to log some state occurred in the application, however any exception could cause a rollback of the whole transaction, including the log entry. It could look as follows:

LogTable logTable;
logTable.Message = "Something happens";
//some following code in the same transaction throws an exception
throw Exception::Error;

It can be resolved quite easily. We need to create a separate database connection and possibly our own transaction. The modification of the preceding code would look as follows:

LogTable logTable;
UserConnection connection = new UserConnection();
//use another connection
//beginning of the independent transaction
logTable.Message = "Something happens";
//this exception doesn't affect the logTable entry
throw Exception::Error;

MySQL Workbench

In pursuance of application design or an existing system analysis I sometimes need to draw entity-relationship diagrams. Diagrams are more illustrative than tables or word descriptions and they help especially with things involving relations (foreign keys, delete actions etc.)

For this purpose I tried to find an easy to use piece of software with a sufficiently benevolent license (to be able to use it everywhere). I’ve ended with MySQL Workbench Community Edition and I’m absolutely satisfied – all what I need can be created by few clicks, it looks nice and the software is under GPL license.

See the (fictitious) example:

AX TFS WorkItems

After some delays I’ve finally published my extension of AX for linking of Team Foundation Server work items during checkin.

See more on this page.