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:
@Autowired
private DialogWindows dialogWindows;
@Autowired
private DataManager dataManager;
@ViewComponent
private DataGrid<OrderItem> orderItemsDataGrid;
@Subscribe("orderItemsDataGrid.create")
public void onOrderItemsDataGridCreate(final ActionPerformedEvent event) {
OrderItem orderItem = dataManager.create(OrderItem.class);
orderItem.setOrder(getEditedEntity());
dialogWindows.detail(orderItemsDataGrid)
.newEntity(orderItem)
.withParentDataContext(getViewData().getDataContext())
.open();
}
@Subscribe("orderItemsDataGrid.edit")
public void onTasksDataGridEdit(final ActionPerformedEvent event) {
OrderItem selectedItem = orderItemsDataGrid.getSingleSelectedItem();
if (selectedItem == null) {
return;
}
dialogWindows.detail(orderItemsDataGrid)
.editEntity(selectedItem)
.withParentDataContext(getViewData().getDataContext())
.open();
}
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.
Regards,
Dmitriy