Adding new entity to data container programmatically

Hi
I am trying to create a test project and stuck with adding an entity programmatically.

in Platform 6.10x we can do as follows:

ProjectProduct product = metadata.create(ProjectProduct.class);
product.setProdSize(unit.getSize());
product.setProjectBlock(block);
product.setPropertyType(unit.getPropertyType());
product.setProject(getEditedEntity());
product.setUnitNo(block.getName()+"-"+unitNo);

projectProductDs.addItem(product);

In V7, i dont see anything like below
projectProductDc.addItem(product);

Therefore, what is the way to perform it in V7? Sorry, I tried to find it in the documentation but might have missed.

Hi @mortozakhan,

I think the best way is to subscribe to a DataContext event:

    @Subscribe(target = Target.DATA_CONTEXT)
    protected void onPreCommit(DataContext.PreCommitEvent event) {
        ProjectProduct product = metadata.create(ProjectProduct.class);
        product.setProdSize(unit.getSize());
        product.setProjectBlock(block);
        product.setPropertyType(unit.getPropertyType());
        product.setProject(getEditedEntity());
        product.setUnitNo(block.getName()+"-"+unitNo);

        event.getModifiedInstances().add(product);
    }

Alternatively, you may use addPreCommitListener in the datacontext object:

    @Inject
    private DataContext dataContext;

    @Subscribe
    protected void onInit(InitEvent event) {
        dataContext.addPreCommitListener(preCommitEvent -> {
            ProjectProduct product = metadata.create(ProjectProduct.class);
            product.setProdSize(unit.getSize());
            product.setProjectBlock(block);
            product.setPropertyType(unit.getPropertyType());
            product.setProject(getEditedEntity());
            product.setUnitNo(block.getName()+"-"+unitNo);

            preCommitEvent.getModifiedInstances().add(product);
        });
    }

Regards.

Hi
Thanks.
But think is, I want to add those entities after the user has done some update in different datasource and this is updated on that basis. This will be user’s choice of action when the user want to update it by clicking a button for example. It is neither at init time nor before commit.

Hi,

Take a look at the docs: Data Context

If I understood, what you want is:

        ProjectProduct product = metadata.create(ProjectProduct.class);
        product.setProdSize(unit.getSize());
        product.setProjectBlock(block);
        product.setPropertyType(unit.getPropertyType());
        product.setProject(getEditedEntity());
        product.setUnitNo(block.getName()+"-"+unitNo);

        dataContext.merge(product);
        dataContext.commit();

Pay attention because commit will update all the tracked entities in the dataContext (or just delegate changed entities to the parent dataContext, if it has one).

Thanks Peterson but I don’t want to commit at this stage until the user hit’s the commit button (i.e. OK button).

I have figured it out later that the default datasource injection needs to be modified to old way like this

@Inject
    private CollectionDatasource<ProjectProduct, UUID> ProjectProductsDs;

Could you try something like this:

projectProductDc.getMutableItems().add(product);

Thank may work! I shall test it. Thank you so much.

What Peterson said works with one minor change.
You have to use the returned entity from the merge.
Otherwise you will get:

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST:

Final working example:

@Inject
private DataContext dataContext;
...
OrderDetail orderDetail = metadata.create(OrderDetail.class);
orderDetail.setOrder(getEditedEntity());
orderDetail.setProduct(product);
orderDetail.setProductName(product.getName());
OrderDetail orderDetailMerged = dataContext.merge(orderDetail);
orderDetailLinesDc.getMutableItems().add(orderDetailMerged);