Skip to content

Committing a Rolled-Back Object#10899

Open
MarkvanMents wants to merge 11 commits intodevelopmentfrom
MvM-DatabasesAndMemory
Open

Committing a Rolled-Back Object#10899
MarkvanMents wants to merge 11 commits intodevelopmentfrom
MvM-DatabasesAndMemory

Conversation

@MarkvanMents
Copy link
Copy Markdown
Collaborator

No description provided.

Copy link
Copy Markdown
Collaborator Author

@MarkvanMents MarkvanMents left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the comments @basdebakker
I've tried to address them in 89a5f33 - please let me know if it needs more clarification.


| Option | Behavior |
| --- | --- |
| Rollback (default) | All changes are reverted to the state before the microflow started, the microflow aborts, and a system error message is shown. |
Copy link
Copy Markdown
Contributor

@lvanengelen-mx lvanengelen-mx Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a system error message is only shown if the error is not caught using error handling on a higher level and is allowed to bubble up.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in ff31fe7

Copy link
Copy Markdown
Contributor

@lvanengelen-mx lvanengelen-mx Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some feedback after our discussion:

All changes are reverted to the state before the microflow started, the microflow aborts,

'the microflow': is it the microflow in which the error handling is defined or the microflow that is called by the Call Microflow action on which error handling is defined.

and a system error message is shown unless custom error handling is added in a microflow which called this one

I would phrase it as cause -> effect, something like: 'if the error is not handled, a system error message is shown'

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in c920e2e

| Option | Behavior |
| --- | --- |
| Rollback (default) | All changes are reverted to the state before the microflow started, the microflow aborts, and a system error message is shown. |
| Custom with rollback | All changes are reverted to the state before the microflow started, an error flow is followed, and the microflow's subsequent behavior depends on whether the error handling flow ends with an error or end event. |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'All changes ... state before the microflow started' might be a bit ambiguous here.

In the following setup (client request triggers MF1, MF1 triggers MF2, MF2 triggers MF3, which fails)

request -> MF1
MF1: Start -> ... database stuff ... -> call MF2 Rollback -> End
MF2: Start -> ... more database stuff ... -> call MF3 Custom with rollback
MF3: FAIL

all database operations in 'database stuff' and 'more database stuff' are reverted. If MF1 did 'call MF2 Custom without rollback' instead, only 'more database stuff' is reverted.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If MF1 did 'call MF2 Custom without rollback' instead, only 'more database stuff' is reverted.

But aren't we talking about Custom with rollback here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I just wanted to indicate how the call MF2 error handling configuration influences to which state the database is rolled back. This, to indicate that you do not know to what level the data is rolled back in the case of nested transactions. It could be to the database state at the start of the microflow calling the failing action (i.e. the start of MF2) or a database state at another level entirely.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But doesn't it always end up in the state before this MF is called - the error propagation might then change it again - but for an instant when this particular MF errors the rollback will only go as far as the calling microflow and then work out what to do with the error there?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I fully understand, probably because I am not 100% sure about what you mean by state. In the following:

request -> MF1
MF1: S -> A1 -> Call MF2 Rollback -> E
MF2: S -> A2 -> Call MF3 Custom with rollback -> E
MF3: S -> FAIL

when the Call MF3 fails, execution continues in its error flow (execution state) while the database resets to the last savepoint, which is all the way to the start of MF1.

So we should probably be careful with the word 'state' as well :-)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to simplify - customers will need to look at the examples for the full picture.
c920e2e

1. An error occurs, the microflow ends and data in the database is rolled back to the savepoint.
1. You perform a **Commit object(s)** on the object again, but the changes are not written to the database because:

* The object in memory still has your changes
Copy link
Copy Markdown
Contributor

@lvanengelen-mx lvanengelen-mx Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless any other changes were made after the first commit, I do not think this is correct. As the commit succeeded, the changes were applied to the object in memory and the object does not have changes. It's just that the earlier changes are now the current values. I.e. rolling back this object would keep the same values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the next bullet point covers it? Or combine with it?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combined bullets in ff31fe7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, 'the object in memory still has changes' here can mean two things:

  • the attributes have the same value as those that you set, but the original values are still there as well. I.e. rolling back this object will undo your changes
  • the attributes have the same value as those that you set and the original values are the same. I.e. rolling back this object will keep the same values as the values you set.

Copy link
Copy Markdown
Collaborator Author

@MarkvanMents MarkvanMents left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comprehensive review.
Resolved some of these (I hope) - there are still two discussions outstanding where I'm not sure what best to say.
Can you have another look and see if there are still changes I need to make.
Thanks for all your work so far.

| Option | Behavior |
| --- | --- |
| Rollback (default) | All changes are reverted to the state before the microflow started, the microflow aborts, and a system error message is shown. |
| Custom with rollback | All changes are reverted to the state before the microflow started, an error flow is followed, and the microflow's subsequent behavior depends on whether the error handling flow ends with an error or end event. |
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But doesn't it always end up in the state before this MF is called - the error propagation might then change it again - but for an instant when this particular MF errors the rollback will only go as far as the calling microflow and then work out what to do with the error there?

1. An error occurs, the microflow ends and data in the database is rolled back to the savepoint.
1. You perform a **Commit object(s)** on the object again, but the changes are not written to the database because:

* The object in memory still has your changes
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combined bullets in ff31fe7


| Option | Behavior |
| --- | --- |
| Rollback (default) | All changes are reverted to the state before the microflow started, the microflow aborts, and a system error message is shown. |
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in ff31fe7

Copy link
Copy Markdown
Collaborator Author

@MarkvanMents MarkvanMents left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @basdebakker and @lvanengelen-mx
I've tried to clarify things after my discussion with Leroy in these commits: https://github.com/mendix/docs/pull/10899/changes/23debd16bc93f77be2831a1c26d06c541ac3cd31..6aba2b817fcc7015908d2dc90198d8eff665aaae

I also have one outstanding question where I am not sure which statement is more accurate.

I hope these changes take us towards more clarity. Please let me know what you think.

Mark

When you commit an object which is in memory, all changes to the database values are saved. Once it is committed, you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.

However, a Mendix commit is not the same as a database commit. For an object of a persistable entity, the saved value is not committed to the database until the microflow and any microflows from which it is called, complete. This means that errors in a microflow can initiate a rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object is rolled back to the value it had at the start of the microflow. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
However, a Mendix commit is not the same as a database (SQL) COMMIT. When you use a **Commit object(s)** activity, Mendix actually performs an INSERT or UPDATE on the database. For an object of a persistable entity, the database COMMIT is not performed until the microflow and any microflows from which it is called, complete. This means that, although a retrieve from the database by the end-user's app will see the updated version of the object, the updated object will not be seen globally by other end-users until the microflows end.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a contradiction between this statement and Line 210 of error-handling-in-microflows (which I pulled in from the Mx8 documentation as people said it was useful). In what circumstances does the current end-user continue to see their changes?

If they have uncommitted changes, are these stored in the client and still available if they start a transaction and retrieve the object? Or are they lost if they aren't committed?

This statement implies that the changes continue to be visible to the user even outside the microflow (e.g. if you retrieve into a data container) whereas line 210 of error-handling-in-microflows says the changed data is only visible within the microflow.

I guess this one is more accurate otherwise a Change Object with Commit: No and Refresh in Client: Yes wouldn't work?

Can you confirm?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That line 210 says:

To ensure that every end-user or process can only see persisted data, data changed in a microflow is only available within that microflow. None of the changes made inside the microflow will be available outside the microflow, not even to the end-user that initiated the microflow. The information will only be available to all end-users of the application once the microflow has successfully completed all the activities.

I do not fully understand what this is meant to say. Changes made by the user in the client are (ephemerally) stored there and applied on in-memory objects when calling a microflow. So the end-user has access to the changes, because they are in the browser.

In what circumstances does the current end-user continue to see their changes?

As long as they do not refresh the page and the changes are not committed, these are stored in the client and passed to the runtime when necessary, where they become in-memory objects. When the microflow re-retrieves such an object from the database, this is another copy in memory with the same object id. By itself, this does not interfere with the changes in the client.

However, if the Refresh in Client setting is used on the object retrieved from the database, the runtime will tell the client in the response that it should update its state cache with the retrieved object for that id. This will remove the original change.

Returning the retrieved object as the microflow return value keeps the change.

To be honest, I was not 100% sure about the behavior in these 3 scenarios, so I reproduced them in a test project.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the investigation. I think there is too much to add to the documentation here, but I have tried to clarify line 210 of error-handling-in-microflows.md in this suggestion: https://github.com/mendix/docs/pull/10899/changes#r3074354106

### Committing Objects

When you commit an object, all changes to the current values are saved. This means that you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.
When you commit an object which is in memory, all changes to the database values are saved. Once it is committed, you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.
Copy link
Copy Markdown
Contributor

@lvanengelen-mx lvanengelen-mx Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all changes to the database values are saved

Do you mean all changes form the in-memory object are saved to the database? Or after the in-memory changes are saved to the database, the database values and in-memory object are in sync? The latter is not necessarily true if some other changes were committed earlier by some other user.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something like:

When you commit an object which is in memory, its changes are saved to the database. The object is now unchanged and a roll back will have no effect.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest:

Suggested change
When you commit an object which is in memory, all changes to the database values are saved. Once it is committed, you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.
When you commit an object which is in memory, changes to the values are saved in the database. Once it is committed, you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.

But I want to specifically talk about Rollback object as this is different from the rollback which occurs with an error.

However, a Mendix commit is not the same as a database (SQL) COMMIT. When you use a **Commit object(s)** activity, Mendix actually performs an INSERT or UPDATE on the database. For an object of a persistable entity, the database COMMIT is not performed until the microflow and any microflows from which it is called, complete. This means that, although a retrieve from the database by the end-user's app will see the updated version of the object, the updated object will not be seen globally by other end-users until the microflows end.

Another consequence of this is that, in contrast to an explicit **Rollback object** call, errors in a microflow can initiate a rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object is rolled back to the value it had at the start of the microflow. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
Another consequence of this distinction is that, in contrast to an explicit **Rollback object** call, which rolls back to the last Mendix commit, errors in a microflow can initiate a database rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object in the database is rolled back to the value it had at the last savepoint. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
Copy link
Copy Markdown
Contributor

@lvanengelen-mx lvanengelen-mx Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... the value of the object in the database is rolled back to the value it had at the last savepoint

Explicitly mention that the in-memory changes are kept?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Another consequence of this distinction is that, in contrast to an explicit **Rollback object** call, which rolls back to the last Mendix commit, errors in a microflow can initiate a database rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object in the database is rolled back to the value it had at the last savepoint. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
Another consequence of this distinction is that, in contrast to an explicit **Rollback object** call, which rolls back to the last Mendix commit, errors in a microflow can initiate a database rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object in the database is rolled back to the value it had at the last savepoint. The object in memory will, however, keep any changes to the values. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.

@@ -118,29 +125,31 @@ When you work on an object in memory, Mendix records whether the object has been
* If you commit an object which is then rolled back due to an error, committing the object again will not write the latest version to the database. You can understand this as the following sequence (see [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for a more detailed discussion of how rollbacks work during error handling):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you commit an object which is then rolled back due to an error

Should we say instead that not the object is rolled back but the transaction is rolled back to the last savepoint?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea:

Suggested change
* If you commit an object which is then rolled back due to an error, committing the object again will not write the latest version to the database. You can understand this as the following sequence (see [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for a more detailed discussion of how rollbacks work during error handling):
* If you commit an object and the transaction is then rolled back due to an error, committing the object again will not write the latest version to the database. You can understand this as the following sequence (see [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for a more detailed discussion of how rollbacks work during error handling):

1. An error occurs after the **Commit object(s)** has successfully sent changes to the database, the microflow ends and data in the database is rolled back to the savepoint.
1. You change your object in memory – it is marked as changed.
1. You perform a **Commit object(s)** activity which sends the changes to the database – the object in memory is marked as unchanged.
1. An error occurs after the **Commit object(s)** has successfully sent changes to the database the microflow ends and data in the database is rolled back to the savepoint.
Copy link
Copy Markdown
Contributor

@lvanengelen-mx lvanengelen-mx Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make it more explicit that the error occurs in another action after the commit?

Our implementation of commit could be seen as Prologue > Database Commit > Epilogue Any error in Epilogue should restore the object to its original state, as that is the contract of the Commit action. So this scenario is really about errors in the activity after the commit.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make it more explicit:

Suggested change
1. An error occurs after the **Commit object(s)** has successfully sent changes to the database – the microflow ends and data in the database is rolled back to the savepoint.
1. An error occurs in an activity after the **Commit object(s)** activity has successfully sent changes to the database – the microflow ends and data in the database is rolled back to the savepoint.

1. An error occurs after the **Commit object(s)** has successfully sent changes to the database the microflow ends and data in the database is rolled back to the savepoint.
1. You perform a **Commit object(s)** on the object again, but the changes are not written to the database because:

* The object in memory still has your changes but it was marked as unchanged after your previous commit
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid 'changes' here, as that implies that it is still in a changed state. Maybe 'committed values' is better?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

Suggested change
* The object in memory still has your changes but it was marked as unchanged after your previous commit
* The object in memory still has the updated values but it was marked as unchanged after your previous commit

* The **Commit object(s)** activity does not see the changed marker and so does not recognize that your object in memory has changes which need to be written.

If you want to keep the changes in the latest version you will have to work around this behavior.
If you want to keep the changes in the version which is in memory, you will have to work around this behavior by creating a new object which contains the changes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt that creating a new object is correct in general: you probably want it to be the same (i.e. with same object id) object. What would work is update any attribute value (even to its current value). That will mark the in-memory object as changed for the database. Not sure if we want to recommend that to users though...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

Suggested change
If you want to keep the changes in the version which is in memory, you will have to work around this behavior by creating a new object which contains the changes.
If you want to keep the changes in the version which is in memory, you will have to work around this behavior by modifying the object again.

Is this vague enough? I feel like having said that the developer still has the modified version we need to suggest a solution that doesn't involve throwing the changes away and having to do the whole process (which may having involved end-user input) all over again.

Mendix mimics this behavior for non-persistable entities. This means that:

* Performing a commit on a non-persistable entity means that you cannot use a **Rollback object** activity to go back to the previous values
* If an error occurs in a microflow, and you have error handling which does a rollback, the values roll back to the state a the previous savepoint.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the values roll back to the state a the previous savepoint.

The database values roll back to the state of the previous savepoint. But as non-persistable entities are not stored in the database, this does not matter for non-persistable entities.

Database rollback and object rollback are unrelated concepts. In-memory objects do not roll back on failure.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is there no difference for Non-persistable entities between custom with rollback and custom without rollback. They will both behave as custom without rollback? Perhaps I could say that.

Suggested change
* If an error occurs in a microflow, and you have error handling which does a rollback, the values roll back to the state a the previous savepoint.
* If an error occurs in a microflow, and you have custom error handling, it will always act as a custom without rollback as persistable entities do not have a separate state in the database.

### Autocommit and Associated Objects {#autocommit-and-associated-objects}

When an object is committed through a default **Save** button, a commit activity, or web services, it always triggers the commit events. The platform also evaluates all associated objects. To guarantee data consistency, the platform may also autocommit associated objects.
When an object in memory is committed through a default **Save** button, a commit activity, or web services, it always triggers the commit events. The platform also evaluates all associated objects. To guarantee data consistency, the platform may also autocommit associated objects.
Copy link
Copy Markdown
Contributor

@lvanengelen-mx lvanengelen-mx Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it always triggers the commit event

Maybe make it explicit that this also holds when the object is not marked as changed (and therefore no actual database save will take place)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this, although true, is too much detail. I think "it always" is enough?

### Autocommit and Associated Objects {#autocommit-and-associated-objects}

When an object is committed through a default **Save** button, a commit activity, or web services, it always triggers the commit events. The platform also evaluates all associated objects. To guarantee data consistency, the platform may also autocommit associated objects.
When an object in memory is committed through a default **Save** button, a commit activity, or web services, it always triggers the commit events. The platform also evaluates all associated objects. To guarantee data consistency, the platform may also autocommit associated objects.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The platform also evaluates all associated objects.

What does this mean?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question - I don't actually know what it does but it has some sort of consistency check on all the associated objects. Not sure what else to say here.

An error event defines where a microflow will stop and throw an error that occurred earlier. If you call a microflow, you may want to know whether any errors occurred within the microflow or not. This event throws the error again, so the caller of the microflow can catch them. When you use this event, all database actions within the current transaction will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).
An error event defines where a microflow will stop and throw a new error based on the error that occurred earlier. If you call a microflow, you may want to know whether any errors occurred within the microflow or not.

When you use this event, it creates a new error with the same information as the original error. Because this is a new error, even if the error that occurred earlier was caught **without rollback**, all database actions within the current transaction will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).
Copy link
Copy Markdown
Contributor

@lvanengelen-mx lvanengelen-mx Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all database actions within the current transaction will be rolled back

Do you mean 'since the last savepoint' (considering transaction is only on the outer level)? Or don't we make that distinction here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - we are trying to avoid using "transaction". Would it be best to say "all database actions within the microflow?". I don't want to start talking about savepoints as we are only talking about how we exit the microflow here.

Should I say

Suggested change
When you use this event, it creates a new error with the same information as the original error. Because this is a new error, even if the error that occurred earlier was caught **without rollback**, all database actions within the current transaction will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).
When you use this event, it creates a new error with the same information as the original error. Because this is a new error, even if the error that occurred earlier was caught **without rollback**, all database actions within the current microflow will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).

Comment on lines +31 to +32
| Rollback (default) | Reverts all changes, aborts the microflow, and returns the error to the calling microflow. |
| Custom with rollback | Reverts all changes and follows the error flow. |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverts all changes

Should we make it explicit that this about database changes and that it reverts changes to the state of the last savepoint? Using 'all' might indicate all changes in the request?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea:

Suggested change
| Rollback (default) | Reverts all changes, aborts the microflow, and returns the error to the calling microflow. |
| Custom with rollback | Reverts all changes and follows the error flow. |
| Rollback (default) | Reverts all database changes, aborts the microflow, and returns the error to the calling microflow. |
| Custom with rollback | Reverts all changes and follows the error flow. |

It is important to know that when a microflow is started by an end-user (for example, by clicking a button), a savepoint is always created at the very beginning of the microflow. This is the case for **Microflow 1** in all the following examples. Knowing how savepoints are created and function is key to understanding how error handling works.

In the following subsections, we introduce the functionality of each error handling option using simple examples.
In the following subsections, we introduce the functionality of each error handling option using simple examples. In the examples we have an activity which generates the error. In a real app, however, an error can be generated by any activity. Any changes which happen within the activity which fails will not be applied (for example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept). The error handling only applies to activities which happened before the activity which errors.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the examples we have an activity which generates the error. In a real app, however, an error can be generated by any activity.

I do not see the contrast between 'an activity' and 'any activity'. Maybe change 'an activity' to 'a Microflow call action' or 'a specific activity'?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. How about:

Suggested change
In the following subsections, we introduce the functionality of each error handling option using simple examples. In the examples we have an activity which generates the error. In a real app, however, an error can be generated by any activity. Any changes which happen within the activity which fails will not be applied (for example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept). The error handling only applies to activities which happened before the activity which errors.
In the following subsections, we introduce the functionality of each error handling option using simple examples. In the examples we have an microflow call which generates the error. In a real app, however, an error can be generated by any activity. Any changes which happen within the activity which fails will not be applied (for example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept). The error handling only applies to activities which happened before the activity which errors.

It is important to know that when a microflow is started by an end-user (for example, by clicking a button), a savepoint is always created at the very beginning of the microflow. This is the case for **Microflow 1** in all the following examples. Knowing how savepoints are created and function is key to understanding how error handling works.

In the following subsections, we introduce the functionality of each error handling option using simple examples.
In the following subsections, we introduce the functionality of each error handling option using simple examples. In the examples we have an activity which generates the error. In a real app, however, an error can be generated by any activity. Any changes which happen within the activity which fails will not be applied (for example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept). The error handling only applies to activities which happened before the activity which errors.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling only applies to activities which happened before the activity which errors.

Isn't this redundant? I can't see what the alternative would be.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this because someone pointed out that people could think that if something like a change object with commit fails on the commit part, people might think that the change object bit of the activity still happens. This is supposed to say that nothing that happens within the activity will still be kept.


{{% alert color="warning" %}}
Rollback does not mark any uncommitted objects as changed. See [How Commits Work](/refguide/committing-objects/#how-commits-work) in *Commit Object(s)* to see the implications of this.
After a rollback, previously committed objects remain marked as unchanged in memory, even though their database state has been reverted. See [How Commits Work](/refguide/committing-objects/#how-commits-work) in *Commit Object(s)* to see the implications of this.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a rollback

Explicit 'database rollback'?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should say that here. Mendix uses the term "Rollback" not "Database Rollback" and I think we should be consistent with that. Unless you want to change the UX and say "Custom with Database Rollback" for the error handling option?

### Error Handling - Custom without Rollback

In this example, the error handling in **Microflow 2** is set to **Custom with rollback** and the error handling flow ends with an end event.
Setting **Custom without rollback** will not stop data changes within the activity which failed from being rolled back. For example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will not stop data changes within the activity which failed from being rolled back.

I find this sentence difficult to understand. Maybe interpreting this as 'rolling back' assumes too much. E.g. if the error handling is configured on a Call microflow action, then some of its side effects might be undone, some might not. In the given example of Call REST Service nothing is 'rolled back' per se, it's just that the return value is discarded.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same thing as I tried to say before. How about:

Suggested change
Setting **Custom without rollback** will not stop data changes within the activity which failed from being rolled back. For example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept.
Setting **Custom without rollback** will not stop data changes within the actual activity which failed being lost. For example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept.


{{% alert color="info" %}}
Using custom error handling without rollback and ending the error handling flow with an error event here makes it possible to create a custom log message with details about the **NewOrder** (if you used error handling with rollback, the information about the **NewOrder** would not be available when creating the custom log message). However, after logging this message, everything will still be rolled back.
Using custom error handling without rollback and ending the error handling flow with an error event here makes it possible to create a custom log message with details about the **NewOrder** (if you used error handling with rollback, the information about the **NewOrder** would not be available when creating the custom log message). However, after logging this message, everything will still be rolled back as the error event is not handled in **Microflow 1**.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(if you used error handling with rollback, the information about the NewOrder would not be available when creating the custom log message)

I do not understand why this would be the case. The database state is rolled back to the savepoint, but the data in the NewOrder object should still be available.

I have asked it within my team, waiting for response.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have no idea why this data would not be available. I tried within a test project, and I can read the attributes from the object. Or is it meant that retrieving the data from the database won't show the changed values? Which would be logical, as they were rolled back 😃

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to log the information while you still have the object in context. So you can't error and then log it in the calling microflow. That is what this is saying: you can do the custom error handling to log information from the object, and then rethrow the error. But it sounds like there is a confusion about what is being rolled back here. Perhaps we can make it clearer:

Suggested change
Using custom error handling without rollback and ending the error handling flow with an error event here makes it possible to create a custom log message with details about the **NewOrder** (if you used error handling with rollback, the information about the **NewOrder** would not be available when creating the custom log message). However, after logging this message, everything will still be rolled back as the error event is not handled in **Microflow 1**.
Using custom error handling and ending the error handling flow with an error event here makes it possible to create a custom log message with details about the **NewOrder**. However, after logging this message, everything will still be rolled back as the error event is not handled in **Microflow 1**.


{{% alert color="info" %}}
This doesn't prevent two end-users editing the same object. Two end-users can read the same object and change it. However, neither will see the changes that the other has made. They can both commit the changes and the change committed second will be applied.
This doesn't prevent two end-users editing the same object. Two end-users can read the same object and change it. However, neither will see the changes that the other has made. They can both commit the changes and the change committed second will overwrite the changes committed first.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can both commit the changes and the change committed second will overwrite the changes committed first.

Or it might error out, depending on whether optimistic locking is enabled.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - this was written before optimistic locking was introduced. Perhaps we should say:

Suggested change
This doesn't prevent two end-users editing the same object. Two end-users can read the same object and change it. However, neither will see the changes that the other has made. They can both commit the changes and the change committed second will overwrite the changes committed first.
This doesn't prevent two end-users editing the same object. Two end-users can read the same object and change it. However, neither will see the changes that the other has made. They can both commit the changes and the result depends on whether [optimisti locking](/refguide/optimistic-locking/) in implemented.
* Without optimistic locking, the change committed second will overwrite the changes committed first.
* WIth optimistic locking, the change committed second will throw an error.

Copy link
Copy Markdown
Collaborator Author

@MarkvanMents MarkvanMents left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Responded to error-events.md and error-handling-in-microflows.md
Please let me know if suggestions are good.
Will look at committing-objects.md in separate review.

An error event defines where a microflow will stop and throw an error that occurred earlier. If you call a microflow, you may want to know whether any errors occurred within the microflow or not. This event throws the error again, so the caller of the microflow can catch them. When you use this event, all database actions within the current transaction will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).
An error event defines where a microflow will stop and throw a new error based on the error that occurred earlier. If you call a microflow, you may want to know whether any errors occurred within the microflow or not.

When you use this event, it creates a new error with the same information as the original error. Because this is a new error, even if the error that occurred earlier was caught **without rollback**, all database actions within the current transaction will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - we are trying to avoid using "transaction". Would it be best to say "all database actions within the microflow?". I don't want to start talking about savepoints as we are only talking about how we exit the microflow here.

Should I say

Suggested change
When you use this event, it creates a new error with the same information as the original error. Because this is a new error, even if the error that occurred earlier was caught **without rollback**, all database actions within the current transaction will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).
When you use this event, it creates a new error with the same information as the original error. Because this is a new error, even if the error that occurred earlier was caught **without rollback**, all database actions within the current microflow will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).

Comment on lines +31 to +32
| Rollback (default) | Reverts all changes, aborts the microflow, and returns the error to the calling microflow. |
| Custom with rollback | Reverts all changes and follows the error flow. |
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea:

Suggested change
| Rollback (default) | Reverts all changes, aborts the microflow, and returns the error to the calling microflow. |
| Custom with rollback | Reverts all changes and follows the error flow. |
| Rollback (default) | Reverts all database changes, aborts the microflow, and returns the error to the calling microflow. |
| Custom with rollback | Reverts all changes and follows the error flow. |

It is important to know that when a microflow is started by an end-user (for example, by clicking a button), a savepoint is always created at the very beginning of the microflow. This is the case for **Microflow 1** in all the following examples. Knowing how savepoints are created and function is key to understanding how error handling works.

In the following subsections, we introduce the functionality of each error handling option using simple examples.
In the following subsections, we introduce the functionality of each error handling option using simple examples. In the examples we have an activity which generates the error. In a real app, however, an error can be generated by any activity. Any changes which happen within the activity which fails will not be applied (for example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept). The error handling only applies to activities which happened before the activity which errors.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. How about:

Suggested change
In the following subsections, we introduce the functionality of each error handling option using simple examples. In the examples we have an activity which generates the error. In a real app, however, an error can be generated by any activity. Any changes which happen within the activity which fails will not be applied (for example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept). The error handling only applies to activities which happened before the activity which errors.
In the following subsections, we introduce the functionality of each error handling option using simple examples. In the examples we have an microflow call which generates the error. In a real app, however, an error can be generated by any activity. Any changes which happen within the activity which fails will not be applied (for example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept). The error handling only applies to activities which happened before the activity which errors.

It is important to know that when a microflow is started by an end-user (for example, by clicking a button), a savepoint is always created at the very beginning of the microflow. This is the case for **Microflow 1** in all the following examples. Knowing how savepoints are created and function is key to understanding how error handling works.

In the following subsections, we introduce the functionality of each error handling option using simple examples.
In the following subsections, we introduce the functionality of each error handling option using simple examples. In the examples we have an activity which generates the error. In a real app, however, an error can be generated by any activity. Any changes which happen within the activity which fails will not be applied (for example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept). The error handling only applies to activities which happened before the activity which errors.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this because someone pointed out that people could think that if something like a change object with commit fails on the commit part, people might think that the change object bit of the activity still happens. This is supposed to say that nothing that happens within the activity will still be kept.


{{% alert color="warning" %}}
Rollback does not mark any uncommitted objects as changed. See [How Commits Work](/refguide/committing-objects/#how-commits-work) in *Commit Object(s)* to see the implications of this.
After a rollback, previously committed objects remain marked as unchanged in memory, even though their database state has been reverted. See [How Commits Work](/refguide/committing-objects/#how-commits-work) in *Commit Object(s)* to see the implications of this.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should say that here. Mendix uses the term "Rollback" not "Database Rollback" and I think we should be consistent with that. Unless you want to change the UX and say "Custom with Database Rollback" for the error handling option?

### Error Handling - Custom without Rollback

In this example, the error handling in **Microflow 2** is set to **Custom with rollback** and the error handling flow ends with an end event.
Setting **Custom without rollback** will not stop data changes within the activity which failed from being rolled back. For example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same thing as I tried to say before. How about:

Suggested change
Setting **Custom without rollback** will not stop data changes within the activity which failed from being rolled back. For example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept.
Setting **Custom without rollback** will not stop data changes within the actual activity which failed being lost. For example, if a [Call REST Service](/refguide/call-rest-action/) returns an error, any data the REST call retrieved will not be kept.


{{% alert color="info" %}}
Using custom error handling without rollback and ending the error handling flow with an error event here makes it possible to create a custom log message with details about the **NewOrder** (if you used error handling with rollback, the information about the **NewOrder** would not be available when creating the custom log message). However, after logging this message, everything will still be rolled back.
Using custom error handling without rollback and ending the error handling flow with an error event here makes it possible to create a custom log message with details about the **NewOrder** (if you used error handling with rollback, the information about the **NewOrder** would not be available when creating the custom log message). However, after logging this message, everything will still be rolled back as the error event is not handled in **Microflow 1**.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to log the information while you still have the object in context. So you can't error and then log it in the calling microflow. That is what this is saying: you can do the custom error handling to log information from the object, and then rethrow the error. But it sounds like there is a confusion about what is being rolled back here. Perhaps we can make it clearer:

Suggested change
Using custom error handling without rollback and ending the error handling flow with an error event here makes it possible to create a custom log message with details about the **NewOrder** (if you used error handling with rollback, the information about the **NewOrder** would not be available when creating the custom log message). However, after logging this message, everything will still be rolled back as the error event is not handled in **Microflow 1**.
Using custom error handling and ending the error handling flow with an error event here makes it possible to create a custom log message with details about the **NewOrder**. However, after logging this message, everything will still be rolled back as the error event is not handled in **Microflow 1**.


{{% alert color="info" %}}
This doesn't prevent two end-users editing the same object. Two end-users can read the same object and change it. However, neither will see the changes that the other has made. They can both commit the changes and the change committed second will be applied.
This doesn't prevent two end-users editing the same object. Two end-users can read the same object and change it. However, neither will see the changes that the other has made. They can both commit the changes and the change committed second will overwrite the changes committed first.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - this was written before optimistic locking was introduced. Perhaps we should say:

Suggested change
This doesn't prevent two end-users editing the same object. Two end-users can read the same object and change it. However, neither will see the changes that the other has made. They can both commit the changes and the change committed second will overwrite the changes committed first.
This doesn't prevent two end-users editing the same object. Two end-users can read the same object and change it. However, neither will see the changes that the other has made. They can both commit the changes and the result depends on whether [optimisti locking](/refguide/optimistic-locking/) in implemented.
* Without optimistic locking, the change committed second will overwrite the changes committed first.
* WIth optimistic locking, the change committed second will throw an error.

Copy link
Copy Markdown
Collaborator Author

@MarkvanMents MarkvanMents left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lvanengelen-mx
Thanks for the comprehensive review.
I've made some more suggestions in response to your review. Please let me know if you have any further points.
I've now responded to everything, I think. If nothing is too misleading, I'd like to publish what we have (as it is an improvement to what is already out there). We can always come back to this at a later date (I'm sure we will).

### Committing Objects

When you commit an object, all changes to the current values are saved. This means that you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.
When you commit an object which is in memory, all changes to the database values are saved. Once it is committed, you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest:

Suggested change
When you commit an object which is in memory, all changes to the database values are saved. Once it is committed, you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.
When you commit an object which is in memory, changes to the values are saved in the database. Once it is committed, you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.

But I want to specifically talk about Rollback object as this is different from the rollback which occurs with an error.

However, a Mendix commit is not the same as a database (SQL) COMMIT. When you use a **Commit object(s)** activity, Mendix actually performs an INSERT or UPDATE on the database. For an object of a persistable entity, the database COMMIT is not performed until the microflow and any microflows from which it is called, complete. This means that, although a retrieve from the database by the end-user's app will see the updated version of the object, the updated object will not be seen globally by other end-users until the microflows end.

Another consequence of this is that, in contrast to an explicit **Rollback object** call, errors in a microflow can initiate a rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object is rolled back to the value it had at the start of the microflow. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
Another consequence of this distinction is that, in contrast to an explicit **Rollback object** call, which rolls back to the last Mendix commit, errors in a microflow can initiate a database rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object in the database is rolled back to the value it had at the last savepoint. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Another consequence of this distinction is that, in contrast to an explicit **Rollback object** call, which rolls back to the last Mendix commit, errors in a microflow can initiate a database rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object in the database is rolled back to the value it had at the last savepoint. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
Another consequence of this distinction is that, in contrast to an explicit **Rollback object** call, which rolls back to the last Mendix commit, errors in a microflow can initiate a database rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object in the database is rolled back to the value it had at the last savepoint. The object in memory will, however, keep any changes to the values. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.

@@ -118,29 +125,31 @@ When you work on an object in memory, Mendix records whether the object has been
* If you commit an object which is then rolled back due to an error, committing the object again will not write the latest version to the database. You can understand this as the following sequence (see [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for a more detailed discussion of how rollbacks work during error handling):
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea:

Suggested change
* If you commit an object which is then rolled back due to an error, committing the object again will not write the latest version to the database. You can understand this as the following sequence (see [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for a more detailed discussion of how rollbacks work during error handling):
* If you commit an object and the transaction is then rolled back due to an error, committing the object again will not write the latest version to the database. You can understand this as the following sequence (see [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for a more detailed discussion of how rollbacks work during error handling):

1. An error occurs after the **Commit object(s)** has successfully sent changes to the database, the microflow ends and data in the database is rolled back to the savepoint.
1. You change your object in memory – it is marked as changed.
1. You perform a **Commit object(s)** activity which sends the changes to the database – the object in memory is marked as unchanged.
1. An error occurs after the **Commit object(s)** has successfully sent changes to the database the microflow ends and data in the database is rolled back to the savepoint.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make it more explicit:

Suggested change
1. An error occurs after the **Commit object(s)** has successfully sent changes to the database – the microflow ends and data in the database is rolled back to the savepoint.
1. An error occurs in an activity after the **Commit object(s)** activity has successfully sent changes to the database – the microflow ends and data in the database is rolled back to the savepoint.

1. An error occurs after the **Commit object(s)** has successfully sent changes to the database the microflow ends and data in the database is rolled back to the savepoint.
1. You perform a **Commit object(s)** on the object again, but the changes are not written to the database because:

* The object in memory still has your changes but it was marked as unchanged after your previous commit
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

Suggested change
* The object in memory still has your changes but it was marked as unchanged after your previous commit
* The object in memory still has the updated values but it was marked as unchanged after your previous commit

Mendix mimics this behavior for non-persistable entities. This means that:

* Performing a commit on a non-persistable entity means that you cannot use a **Rollback object** activity to go back to the previous values
* If an error occurs in a microflow, and you have error handling which does a rollback, the values roll back to the state a the previous savepoint.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is there no difference for Non-persistable entities between custom with rollback and custom without rollback. They will both behave as custom without rollback? Perhaps I could say that.

Suggested change
* If an error occurs in a microflow, and you have error handling which does a rollback, the values roll back to the state a the previous savepoint.
* If an error occurs in a microflow, and you have custom error handling, it will always act as a custom without rollback as persistable entities do not have a separate state in the database.

### Autocommit and Associated Objects {#autocommit-and-associated-objects}

When an object is committed through a default **Save** button, a commit activity, or web services, it always triggers the commit events. The platform also evaluates all associated objects. To guarantee data consistency, the platform may also autocommit associated objects.
When an object in memory is committed through a default **Save** button, a commit activity, or web services, it always triggers the commit events. The platform also evaluates all associated objects. To guarantee data consistency, the platform may also autocommit associated objects.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this, although true, is too much detail. I think "it always" is enough?

### Autocommit and Associated Objects {#autocommit-and-associated-objects}

When an object is committed through a default **Save** button, a commit activity, or web services, it always triggers the commit events. The platform also evaluates all associated objects. To guarantee data consistency, the platform may also autocommit associated objects.
When an object in memory is committed through a default **Save** button, a commit activity, or web services, it always triggers the commit events. The platform also evaluates all associated objects. To guarantee data consistency, the platform may also autocommit associated objects.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question - I don't actually know what it does but it has some sort of consistency check on all the associated objects. Not sure what else to say here.


While updating or creating your objects, you do not want other end-users to see updated information until your microflow has finished executing.

To ensure that every end-user or process can only see persisted data, data changed in a microflow is only available within that microflow. None of the changes made inside the microflow will be available outside the microflow, not even to the end-user that initiated the microflow. The information will only be available to all end-users of the application once the microflow has successfully completed all the activities.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To address https://github.com/mendix/docs/pull/10899/changes#r3063102012 and try to explain how information is isolated:

Suggested change
To ensure that every end-user or process can only see persisted data, data changed in a microflow is only available within that microflow. None of the changes made inside the microflow will be available outside the microflow, not even to the end-user that initiated the microflow. The information will only be available to all end-users of the application once the microflow has successfully completed all the activities.
To ensure that every end-user or process can only see persisted data, data changed and committed in a microflow is not made available to all end-users of the application until the top-level microflow has successfully completed all the activities. Before then, only the end-user running the microflow has access to the data.

When you commit an object which is in memory, all changes to the database values are saved. Once it is committed, you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.

However, a Mendix commit is not the same as a database commit. For an object of a persistable entity, the saved value is not committed to the database until the microflow and any microflows from which it is called, complete. This means that errors in a microflow can initiate a rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object is rolled back to the value it had at the start of the microflow. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
However, a Mendix commit is not the same as a database (SQL) COMMIT. When you use a **Commit object(s)** activity, Mendix actually performs an INSERT or UPDATE on the database. For an object of a persistable entity, the database COMMIT is not performed until the microflow and any microflows from which it is called, complete. This means that, although a retrieve from the database by the end-user's app will see the updated version of the object, the updated object will not be seen globally by other end-users until the microflows end.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the investigation. I think there is too much to add to the documentation here, but I have tried to clarify line 210 of error-handling-in-microflows.md in this suggestion: https://github.com/mendix/docs/pull/10899/changes#r3074354106

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants