A very old error.
If in a composition showed in a detail view the column has filterable=“true”, an IllegalArgumentException is thrown.
Attached you find a project, where you see this error by trying to edit one catalog entry.
If you change in
catalog-detail-view.xml
in the typeDataGrid
<column property="catalog" filterable="true"/>
to <column property="catalog" filterable="false"/>
there is no error.
The filterable property created a DataGridHeaderFilter component instead of a standard header.
This problem occurs because in this case a CollectionPropertyContainer named as typeDc is used for the child collection (and as dataGriddataContainer source).
This container is nested in the original catalogDc and doesn’t have its own dataLoader.
The dataLoader is required for DataGridHeaderFilter, because this component works through modifying a JPQL query.
In fact, this problem is related not only with DataGridHeaderFilter, but also with other component that use the dataLoader: pagination, genericFilter, propertyFilter etc.
All of the listed components require dataLoader during initialization, because their operating principle is also based on modifying a JPQL query.
The error message is correct. In fact, null is passed as a parameter to the DataGridHeaderFilter constructor. This can be seen by opening the exception details and looking at the stacktrace.
There is one way to solve this problem.
Possible solution:
In general, there is a workaround for this problem: define a separate collection container.
I will show you an example of the Order → OrderItems(1:M) data model
<data>
<instance id="orderDc"
class="com.company.master.entity.Order">
<fetchPlan extends="_base">
<property name="customer" fetchPlan="_instance_name"/>
</fetchPlan>
<!-- instead of this collection -->
<!--<collection id="orderItemsDc" property="orderItems"/>-->
<loader id="orderDl"/>
</instance>
<!-- define this one -->
<collection id="orderItemsDc" class="com.company.master.entity.OrderItem">
<loader>
<query>
<![CDATA[select e from OrderItem e where e.order = :container_orderDc]]>
</query>
</loader>
</collection>
</data>
In this case, a collection of OrderItem entities will be loaded where order attribute is the current Order that opened for editing.
However, this approach has problems.
Problems
This method has two significant problems:
When trying to create a new element of a child entity, the parent entity will not be assigned to this element.
You can still manually assign the parent entity when creating a child element. However, this will create a new problem.
Let’s imagine that we create a new Order and want to create OrderItems for it right away. In this case, the parent set for new OrderItems will be null. And this is wrong.
Fixing problems
All these problems are solved by passing the parent DataContext to the child entity details views. This can be done as follows:
Here I simply override the default implementation of the actions to pass the parent DataContext.
You can do the sample for your CategoryDetailView view. This way you can take advantage of all the component that use query modification in their implementation.