Environment
Jmix version: 3.0.1
Bug Description
Performance problem. When the filter state is restored from URL query parameters and the operation of a condition in the URL differs from the one stored in the current configuration, the view fires a redundant intermediate data load before the final one — two loads per navigation instead of one.
Mechanics: GenericFilterUrlQueryParametersBinder.updatePropertyCondition applies the operation from the URL to the live condition component (configurationComponent.setOperation(...)). The operation-change listener registered by GroupFilter.add does not distinguish this programmatic call from a user gesture and unconditionally invokes GroupFilter.apply(); for the delegated root group its apply() skips recomposition but still calls dataLoader.load() (there is no isAttached() check, unlike SingleFilterComponentBase.apply()). The restore then finishes with its own composition and load. Value changes do not add loads (UiComponentUtils.setValue is not a client-side change).
The intermediate load runs the full pipeline — the SELECT, the pagination count query, entity materialization by the fetch plan, row-level security — and its result is immediately discarded. For a view whose query takes ~400 ms, opening a deep link pays roughly double. The condition of the discarded load also differs from the final one, so on large tables it may hit a worse query plan than the final load itself.
The gap is reached with default settings whenever a user changes a condition operation (conditions added by the user and saved configurations have operationEditable = true by default) and the URL is then reopened — F5, browser Back, a bookmark, a link shared with a colleague.
Steps To Reproduce
-
A list view with a GenericFilter bound to the data loader and an urlQueryParameters facet with the genericFilter binder; a configuration whose condition has an editable operation, e.g.:
<configurations>
<configuration id="byStatus" name="By status">
<propertyFilter property="status" operation="EQUAL" operationEditable="true"/>
</configuration>
</configurations>
-
Count data loads, e.g. with a PostLoadEvent listener on the loader, or enable SQL logging.
-
Select the configuration, pick a value, change the operation (= → <>): the URL now carries ..._genericFilterCondition=property:status_not-equal_....
-
Open the resulting URL in a fresh tab (or press F5).
Current Behavior
Two data loads. With a load journal on the view:
Loads: 2 — load #1: AND[status not_equal OPEN] | load #2: AND[status not_equal OPEN, AND[status not_equal OPEN]]
The same URL with the matching operation (..._equal_...) produces one load — the only difference between the two URLs is the operation token.
Expected Behavior
One data load per navigation: the restore applies the URL state as a single composition and loads once.
Notes
Environment
Jmix version: 3.0.1
Bug Description
Performance problem. When the filter state is restored from URL query parameters and the operation of a condition in the URL differs from the one stored in the current configuration, the view fires a redundant intermediate data load before the final one — two loads per navigation instead of one.
Mechanics:
GenericFilterUrlQueryParametersBinder.updatePropertyConditionapplies the operation from the URL to the live condition component (configurationComponent.setOperation(...)). The operation-change listener registered byGroupFilter.adddoes not distinguish this programmatic call from a user gesture and unconditionally invokesGroupFilter.apply(); for the delegated root group itsapply()skips recomposition but still callsdataLoader.load()(there is noisAttached()check, unlikeSingleFilterComponentBase.apply()). The restore then finishes with its own composition and load. Value changes do not add loads (UiComponentUtils.setValueis not a client-side change).The intermediate load runs the full pipeline — the SELECT, the pagination count query, entity materialization by the fetch plan, row-level security — and its result is immediately discarded. For a view whose query takes ~400 ms, opening a deep link pays roughly double. The condition of the discarded load also differs from the final one, so on large tables it may hit a worse query plan than the final load itself.
The gap is reached with default settings whenever a user changes a condition operation (conditions added by the user and saved configurations have
operationEditable = trueby default) and the URL is then reopened — F5, browser Back, a bookmark, a link shared with a colleague.Steps To Reproduce
A list view with a
GenericFilterbound to the data loader and anurlQueryParametersfacet with thegenericFilterbinder; a configuration whose condition has an editable operation, e.g.:Count data loads, e.g. with a
PostLoadEventlistener on the loader, or enable SQL logging.Select the configuration, pick a value, change the operation (
=→<>): the URL now carries..._genericFilterCondition=property:status_not-equal_....Open the resulting URL in a fresh tab (or press F5).
Current Behavior
Two data loads. With a load journal on the view:
The same URL with the matching operation (
..._equal_...) produces one load — the only difference between the two URLs is the operation token.Expected Behavior
One data load per navigation: the restore applies the URL state as a single composition and loads once.
Notes