One-to-many relation updated at entity level not data container


I made a small project in order to practice cuba 7 new api.

There is a CarEntry entity with a one-to-many composition to CarEntryDocument, property named documents.

The CarEntryCalculator is called in the editor each time a CarEntry property changes, which updates the documents property directly. Then I have the following issues.

When the documents in the CarEntry are updated, the Table bound to the documents property does not refresh itself, so generated document list does not appear.

Then if I try to save I will have the infamous ‘not marked as CASCADE PERSIST’ issue, I guess that both issues are related.

Michael (233.1 KB)


I reproduced the issue on a much smaller project : Car entity with one-to-many relationship ‘documents’ to list of Document, which is populated by CarCalculator when any of Car property changes in the editor.

In order to reproduce the issue, create new Car through CarEditor, set a name, press Enter, the documents table is not updated, and if you try to save you get ‘not marked cascade PERSIST’ issue.

My understanding is that CollectionPropertyContainer should observe entity and detect the change in list of documents, then updates itself accordingly which should then update the table.

Seems it does not happen this way, so I guess I have to propagate the change myself, like resynchronizing the nested CollectionPropertyContainer with the ‘documents’ property of entity, and if so how.

I would appreciate any help.

Michael (77.5 KB)

If you create new entities (or load them from DB) and want the screen to track their changes and commit changes into the database - in CUBA 7 you need to merge them to the DataContext:

Thanks @AlexBudarov, it works.

On a sidenote, is there a more elegant coding style than the code below ?

@Subscribe(id = "carDc", target = Target.DATA_CONTAINER)
    public void onCarDcItemPropertyChange(InstanceContainer.ItemPropertyChangeEvent<Car> event) {
        if (inCalc)
        inCalc = true;
        new CarCalculator().compute(event.getItem());
        EntitySet set = dataContext.merge(event.getItem().getDocuments());
        Collection<Document> docs = new ArrayList<>();
        set.forEach(e -> docs.add((Document) e));
        inCalc = false;

Not sure what is more elegant, but you could also use setItems() method to replace the whole collection in the container and related property of the entity:

    new CarCalculator().compute(event.getItem());
    Set<Document> trackedDocs = event.getItem().getDocuments().stream()
            .map(document -> dataContext.merge(document))