Entity Log
Entity Log is a mechanism for monitoring changes made to JPA entities within a system. It records changes in entity attributes and provides a user interface for querying and displaying details regarding the changes:
-
What entity instance was changed.
-
Old and new values of changed attributes.
-
When the entity was changed.
-
Which user changed the entity.
Registering Changes
Entity Log automatically monitors changes made to JPA entities upon saving through DataManager or EntityManager. It is not operational when native SQL is utilized.
Another approach is utilizing the EntityLog
bean to log changes in entities directly from your application code. In this case, invoke registerCreate()
, registerModify()
and registerDelete()
methods with the auto
parameter set to false
. When the entity log is called automatically by the framework, this parameter is set to true
.
Setting Up Entity Log
To be able to use the administrative UI at runtime, a user must have the entity-log resource role provided by the Audit add-on.
|
You can configure the entity log in the Audit → Entity Log view. Switch to the Setup tab:
To establish entity log configuration, click the Create button.
Choose the entity from the Name drop-down list and select the attributes for auditing.
The Auto checkbox determines whether the system logs changes when EntityLog
is invoked with the auto = true
parameter (triggered by entity listeners).
The Manual checkbox determines whether the system logs changes when EntityLog
is invoked with the auto = false
parameter.
The Export and Import actions allow you to export and import configurations in JSON or ZIP format.
Also, you can set up entity log by entering some records in the database if you want to include the configuration to the database initialization.
Logging configuration involves the LoggedEntity
and LoggedAttribute
entities, which correspond to the AUDIT_LOGGED_ENTITY
and AUDIT_LOGGED_ATTR
tables.
LoggedEntity
specifies the entity types to be logged.
LoggedAttribute
defines the entity attribute to be logged and contains a link to the LoggedEntity
and the attribute name.
To configure logging for a specific entity, insert the corresponding entries into the AUDIT_LOGGED_ENTITY
and AUDIT_LOGGED_ATTR
tables.
For instance, in the following example, logging changes to the phone
attribute of the Customer
entity is configured during database initialization:
<changeSet id="1" author="audit">
<insert tableName="AUDIT_LOGGED_ENTITY">
<column name="ID" value="0a6ba81c-a8b9-bc8f-3829-53a6cef48871"/>
<column name="CREATED_BY" value="admin"/>
<column name="CREATE_TS" valueDate="2024-02-21T14:57:25.339"/>
<column name="NAME" value="Customer"/>
<column name="AUTO" value="true"/>
<column name="MANUAL" value="true"/>
</insert>
</changeSet>
<changeSet id="2" author="audit">
<insert tableName="AUDIT_LOGGED_ATTR">
<column name="ID" value="8e6e9825-1381-5299-e704-eadf1b96996e"/>
<column name="CREATE_TS" valueDate="2024-02-21T14:57:25.339"/>
<column name="CREATED_BY" value="admin"/>
<column name="ENTITY_ID" value="0a6ba81c-a8b9-bc8f-3829-53a6cef48871"/>
<column name="NAME" value="phone"/>
</insert>
</changeSet>
Viewing Entity Log
To access the content of the entity log, navigate to the View tab within the Audit → Entity Log view. Configure the required filters to locate specific log entries.
Additionally, you can access the log entries for a particular entity from any application view.
Log entries are stored in the AUDIT_ENTITY_LOG
table corresponding to the EntityLogItem
entity. Changed attribute values are stored in the CHANGES
column and are converted to instances of EntityLogAttr
entity.
For instance, in the following example, an Order
detail view displays data grids containing the entity log information.
Below is an excerpt from the view’s XML descriptor:
<data>
<instance id="orderDc"
class="com.company.demo.entity.Order">
<fetchPlan extends="_base"/>
<loader/>
</instance>
<collection id="entityLogItemsDc"
class="io.jmix.audit.entity.EntityLogItem"> (1)
<fetchPlan extends="_local"/>
<loader id="entityLogItemsDl" readOnly="true">
<query>
<![CDATA[select e from audit_EntityLog e
where e.entityRef.entityId = :entityOrder]]>
</query>
</loader>
<collection id="entityLogAttrDc" property="attributes"/> (2)
</collection>
</data>
<facets>
<dataLoadCoordinator auto="true"/>
</facets>
<actions>
<action id="saveAction" type="detail_saveClose"/>
<action id="closeAction" type="detail_close"/>
</actions>
<layout>
<formLayout id="form" dataContainer="orderDc">
<datePicker id="dateField" property="date"/>
<textField id="productField" property="product"/>
<textField id="amountField" property="amount"/>
<textField id="priceField" property="price"/>
</formLayout>
<formLayout>
<dataGrid id="entityLogItemsDataGrid"
dataContainer="entityLogItemsDc"> (3)
<columns>
<column property="eventTs"/>
<column property="username"/>
<column property="type"/>
</columns>
</dataGrid>
<dataGrid id="entityLogAttrsDataGrid"
dataContainer="entityLogAttrDc"> (4)
<columns>
<column property="name"/>
<column property="oldValue"/>
<column property="value"/>
</columns>
</dataGrid>
</formLayout>
<hbox id="detailActions">
<button id="saveAndCloseBtn" action="saveAction"/>
<button id="closeBtn" action="closeAction"/>
</hbox>
</layout>
1 | Loading a collection of EntityLogItem into the entityLogItemsDc data container. |
2 | Loading associated EntityLogAttr instances into the entityLogAttrDc data container. |
3 | Binding a data grid to the entityLogItemsDc container. |
4 | Binding a data grid to the entityLogAttrDc container. |
Order
view controller looks like this:
@ViewComponent
private CollectionLoader<EntityLogItem> entityLogItemsDl;
@Subscribe(id = "orderDc", target = Target.DATA_CONTAINER)
public void onOrderDcItemChange(final InstanceContainer.ItemChangeEvent<Order> event) { (1)
entityLogItemsDl.setParameter("entityOrder",event.getItem().getId());
entityLogItemsDl.load();
}
1 | In the ItemChangeEvent handler of the orderDc container, a parameter is set to the dependent loader and it is triggered. |