Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Creating a Microflow

Microflows are the server-side logic of a Mendix application. They’re comparable to functions or methods in traditional programming. In this page you’ll create a microflow that accepts parameters, creates an object, commits it to the database, and returns it.

Create a simple microflow

This microflow takes a name and price, creates a Product object, commits it, and returns it:

CREATE MICROFLOW MyModule.CreateProduct(
    DECLARE $Name: String,
    DECLARE $Price: Decimal
)
RETURN MyModule.Product
BEGIN
    CREATE $Product: MyModule.Product (
        Name = $Name,
        Price = $Price,
        IsActive = true
    );
    COMMIT $Product;
    RETURN $Product;
END;

Let’s walk through each part:

PartMeaning
MyModule.CreateProductFully qualified microflow name
DECLARE $Name: StringInput parameter – a string value passed by the caller
RETURN MyModule.ProductThe microflow returns a Product entity object
BEGIN ... ENDThe microflow body
CREATE $Product: MyModule.Product (...)Creates a new Product object in memory and sets its attributes
COMMIT $ProductPersists the object to the database
RETURN $ProductReturns the committed object to the caller

Save this to a file (e.g., create-product-mf.mdl) and execute:

mxcli check create-product-mf.mdl
mxcli exec create-product-mf.mdl -p app.mpr

Verify the microflow

Use DESCRIBE MICROFLOW to see the generated MDL:

mxcli -p app.mpr -c "DESCRIBE MICROFLOW MyModule.CreateProduct"

This shows the full microflow definition, including parameters, activities, and the return type.

Understanding variables

All variables in MDL start with $. There are two contexts where you declare them:

Parameters (in the signature):

CREATE MICROFLOW MyModule.DoSomething(
    DECLARE $Customer: MyModule.Customer,
    DECLARE $Count: Integer
)

Local variables (inside BEGIN…END):

BEGIN
    DECLARE $Total: Integer = 0;
    DECLARE $Message: String = 'Processing...';
    DECLARE $Items: List of MyModule.Item = empty;
END;

For entity parameters, do not assign a default value – just declare the type:

-- Correct: entity parameter with no default
DECLARE $Customer: MyModule.Customer

-- Wrong: entity parameter with = empty
DECLARE $Customer: MyModule.Customer = empty

Retrieving objects

Use RETRIEVE to fetch objects from the database:

CREATE MICROFLOW MyModule.GetActiveProducts()
RETURN List of MyModule.Product
BEGIN
    RETRIEVE $Products: List of MyModule.Product
        FROM MyModule.Product
        WHERE IsActive = true;
    RETURN $Products;
END;

To retrieve a single object, add LIMIT 1:

RETRIEVE $Product: MyModule.Product
    FROM MyModule.Product
    WHERE Name = $SearchName
    LIMIT 1;

Conditional logic

Use IF ... THEN ... ELSE ... END IF for branching:

CREATE MICROFLOW MyModule.UpdateProductStatus(
    DECLARE $Product: MyModule.Product
)
RETURN Boolean
BEGIN
    IF $Product/Price > 0 THEN
        CHANGE $Product (IsActive = true);
        COMMIT $Product;
        RETURN true;
    ELSE
        LOG WARNING 'Product has no price set';
        RETURN false;
    END IF;
END;

Looping over a list

Use LOOP ... IN ... BEGIN ... END LOOP to iterate:

CREATE MICROFLOW MyModule.DeactivateProducts(
    DECLARE $Products: List of MyModule.Product
)
RETURN Boolean
BEGIN
    LOOP $Product IN $Products
    BEGIN
        CHANGE $Product (IsActive = false);
        COMMIT $Product;
    END LOOP;
    RETURN true;
END;

Note: the list $Products is a parameter. Never create an empty list variable and then loop over it – accept the list as a parameter instead.

Error handling

Add ON ERROR to handle failures on individual activities:

COMMIT $Product ON ERROR CONTINUE;

Options are CONTINUE (ignore the error and proceed), ROLLBACK (roll back the transaction and continue), or an inline error handler block:

COMMIT $Product ON ERROR {
    LOG ERROR 'Failed to commit product';
    RETURN false;
};

Organizing with folders

Place microflows in folders using the FOLDER keyword:

CREATE MICROFLOW MyModule.CreateProduct(
    DECLARE $Name: String,
    DECLARE $Price: Decimal
)
RETURN MyModule.Product
FOLDER 'ACT'
BEGIN
    CREATE $Product: MyModule.Product (
        Name = $Name,
        Price = $Price,
        IsActive = true
    );
    COMMIT $Product;
    RETURN $Product;
END;

This places the microflow in the ACT folder within the module, following the common Mendix convention of grouping microflows by type (ACT for actions, VAL for validations, SUB for sub-microflows).

Common mistakes

Every flow path must end with RETURN. If your microflow has IF/ELSE branches, each branch needs its own RETURN statement (or the return can come after END IF if both branches converge).

COMMIT is required to persist changes. CREATE and CHANGE only modify the object in memory. Without COMMIT, changes are lost when the microflow ends.

Entity parameters don’t use = empty. Declare them with just the type. Assigning = empty is for list variables inside the microflow body, not for parameters.