Autocommitted Objects Mystery

3
I have a user that reports occasionally creating a Customer and associated Order today, and then when he logs in tomorrow, the Customer he created (and the Order) is gone. In my app logs, I find the following: Nov 24 15:57:18 127.0.0.1 tr10000: WARNING - Core: (1/4) Some autocommitted objects still existed on logout for session 'userid'. Nov 24 15:57:18 127.0.0.1 tr10000: WARNING - Core: (2/4) Autocommitted objects are newly created objects which were not yet committed, but are inserted into the database because an associated object was committed. Nov 24 15:57:18 127.0.0.1 tr10000: WARNING - Core: (3/4) Autocommitted objects should explicitly have been committed, please check your model and apply the necessary changes. The autocommitted objects have been deleted from the database to prevent database corruption.Number of autocommitted objects per type which still existed for this session: Nov 24 15:57:18 127.0.0.1 tr10000: WARNING - Core: (4/4) - Customer.Customer: 1 object(s). This hasn't occurred with any other users, nor can I recreate it myself. Can someone give me any ideas about how to track down what's happening? Also, I haven't seen any reference to autocommitted objects before. How can this happen in Mendix? What did I do in my model that resulted in autocommitted objects? Thanks, Mike
asked
3 answers
8

Auto-committed objects are objects that have not explicitly been committed to the database themselves, but are referred by other objects that have been committed to the database.

Say you have a typical domain model with a Customer entity and an Order entity where there is a reference from Order to Customer (so a Customer can have multiple Orders). Performing the following activities in a microflow will lead to an auto-committed Customer object:

  1. Create a Customer object.
  2. Create an Order object.
  3. Change the Order object so that it refers to the Customer object.
  4. Commit the Order object to the database.

(Note: steps 2-4 could be implemented using a single 'Create' action that also sets the reference and commits the object.)

Now, when committing the Order object to the database, the Runtime also wants to commit the reference to the Customer object, as that data is a part of the Order object. But because the Customer object has not been committed yet, storing its ID as a value in the database would lead to a "corrupt" database. The Customer's ID would be stored, but there would be no Customer record with that ID.

To mitigate this problem, the Customer object is automatically committed to the database when such a situation occurs. However, this commit is done without validations and without executing events, so the Customer object might not be valid yet. Hence the status 'auto-committed'.

We expect auto-committed objects to be committed later on. This could even be in the same microflow, but it could also be after the user completes the current action (e.g. pressing the 'Save' button in a page when adding a new customer with a new order). When the auto-committed object is not committed later on, this is basically a bug in your application. Hence the warning messages that you see in the Runtime log.

When the user that created the auto-committed object signs out, the auto-committed objects for that user are deleted (if any) and a warning is logged if such objects existed. Any references from committed objects to auto-committed objects are cleared, so that the database remains in a consistent state. So in the example above, when the user signs out the Customer object is deleted and the reference from the Order object to the Customer object is cleared.

So to solve the problem (and the warnings) you need to examine your model and see if you can think of ways that the Order can be committed while the Customer is not. If you make sure that cannot happen anymore, the auto-committed objects should disappear as well.

answered
3

Hi Benny, Bas,

Our log contains thousands of auto committed clean up warnings. This

" When the auto-committed object is not committed later on, this is basically a bug in your application. "

Is not completely true. Because users can navigate away, hit a menu item, click the browser back button and so on. There is absolutely no way you can prevent users from doing is and so creating auto committed objects that will never be committed.

Also there are some side problems. In your example imagine that committing the order will update the stock of the product connected to the order. This happens in the before commit. Also the order has a before/after delete event that updates the stock of the product again when the orders gets removed.

Let's assume that there is delete behavior between the customer and order. The auto-committed customer will be removed by session destroy. It also deletes the order (auto-committed object clean up respecting delete behavior works from Mendix 5.6.0). But auto-committed removal doesn't execute the BDE event of order. So now your stock volume of the product is corrupt.

Situations like these happens al the times, and instead of preventing data corruption, auto committed object is for one of our applications (an application for non professional users (who often navigate away assuming that everything is saved)) a main cause of data corruption.

To prevent this kind of corruption I can only think of the following possibilities:

  • Simulate the old Mendix behavior: when leaving the from, let the user know that he have to save or cancel in other words: force users to make a choose to save or cancel. Unfortunately I think this is no longer possible in Mendix 5.
  • Directly commit certain object in the after create event. Of course you have to implement your own cancel logic.
  • Before session removal retrieve the auto committed objects (is this possible in Java?) and commit them.

Any other ideas? This is really a serious problem of which I'm sure occurs in many applications, but probably not everybody is aware of it..

answered
0

About the three possibilities Herbert mentioned: 1. Simulate the old Mendix behavior: I tried that to implement, it's possible to a certain extent, but not 100% safe, so in the end I didn't choose for this option. 2. Directly commit created objects: I NEVER do that; ONLY when the user explicitly activate the save button I want to commit such objects to prevent issues like you mentioned. So only at that point I fire change-events, or in your example update the stock of the product and so on. The downside sometimes is some redesigning of the workflow, but still I think the best way to handle this, as long as there are no better options at hand. 3. Before session removal retrieve the auto committed objects: in my case that's not necessary

answered