22 Nov 2014

Populating Dirty Entities while VO execution

As we know entity based view objects don't store the data themselves. The view object rows are backed up by the entity instances stored in the entity cache. When the VO execution process is being performed the framework runs over the fetched result set, creates view object rows, creates blank entity instances for each VO row, populates these entities with the fetched data and adds them to the entity cache.  Very roughly this process can be represented on the following diagram:



But what is going to happen if the entity cache already contains entities being fetched? Furthermore, how is the framework going to perform VO execution if those entities are modified by a user? On one hand users need to get recent data from the datasource, on the other hand the modified and uncommitted data shouldn't be lost. The following diagram shows how this magic works:



When the framework adds a new entity to the entity cache it checks whether there is already an entity with the same primary key in the entity cache. If such entity is found then the framework merges the old entity and the new entity. It is supposed that the new entity contains more recent data and this data should be applied to the old entity attributes. However, the framework doesn't change attributes of the old entity if they contain modified and uncommitted data. Note, in this example the user has changed the first name from John to Frank. On the other hand the last name has been changed in the data source from Stone to Gordon. So, we can see how John Stone turned into Frank Gordon.

One important thing should be mentioned here. When the framework merges modified entities it tries to verify the consistency. In other words it checks whether the dirty entity has not been modified by another user in the datasource. By default it compares values of all entity attributes and if it finds any differences it's going to raise an exception "Another user has changed the row with primary key ...". So, in this particular example we are likely to run into that exception, unless we have explicitly marked which attributes should by checked to verify the consistency. We can do that by setting up the  "Change Indicator" property of the entity attribute. If an entity contains any change indicator attributes then only those attributes participate in the consistency verification process. For sure, in our example we should mark as change indicators some other attributes, but not last name.



Since the old entity in the entity cache contains already updated data, there is no need in the new entity anymore. The view row is backed up now by the old entity and the new entity just becomes garbage which is going to be collected by the GC.

The situation can be more complicated when the user has modified entities, but they are not in the entity cache. This could be possible if the user's application module has been borrowed by another user and all the transactional data has been passivated to the passivation storage. Definitely before VO execution the framework is going to restore and activate all that stuff back. When the framework restores dirty entities from the passivation storage it is able to populate only modified attributes, since  values of those attributes only have been passivated. In order to get values of the rest of the attributes from the datasource the framework invokes findByPrimaryKey method on the entity definition instance. Once a restored entity instance has been prepared in this way it is going to be put in the entity cache. The rest of the process is exactly the same as we have considered already.

That's it!