EntityListener makes trouble in a screen controller

Hello, I use the method beforeCommit() in my EntityListener. When I change an entity press the button save and then make some changes in the entity and press the button save again I get an exception:

Exception Description: The object [entity.adress.AddressTable-032b1bca-e652-4dc7-bdeb-b841db49f801 [detached]] cannot be merged because it has changed or been deleted since it was last read.
Class> entity.adress.AddressTable

How can I avoid this trouble? Thank you.
My listener:

@Component(“enerstroymain_AddressTableChangedListener”)
public class AddressTableChangedListener {
@Inject
private AddressSearcher addressSearcher;
@Inject
private TransactionalDataManager tsDm;
@Inject
private PostalcodeSearcher postalcodeSearcher;

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void beforeCommit(EntityChangedEvent<AddressTable, UUID> event) {
    addrobjList.clear();
    if (event.getType() != EntityChangedEvent.Type.DELETED) {
        AddressTable addressTable = tsDm.load(event.getEntityId())
                .view("edit")
                .one();
  			addressTable.setPostalcode(postalcodeSearcher.getPostalcode(addressTable));
                   tsDm.save(addressTable);
                }
            }
}

Hi,
What platform version are you using?
Starting from 7.1.0, DataManager always returns the last instance saved within the transaction, so the optimistic lock exception should not occur. See the issue.

Regards,
Konstantin

Thank you for the answer. We use platform 7.1.2.
We don’t have problems with datamanager it really always return the latest version of an entity. The main problem is that situation which I described takes place in the EntityChangedListener and I don’t have an opportunity to return a new version of the entity from listener into a screen’s controller. Or maybe I use the EntityChangedListener in the wrong way?

Normally screens commit data through DataManager, that’s why I mentioned it. And in this case the screen gets back the latest saved instance, no matter how many listeners changed the entity during saving.

Maybe your screen commits to a custom service?

The sceen makes commit via super.commitChanges() method.

public void onWindowCommitBtnClick() {
super.commitChanges();
}

I think that problem with Listener because when I turn off it everything works properly. As far as I understand, all trouble in the tsDm.save(addressTable); method. This method returns a committed entity but I don’t have an opportunity to return the committed entity to the screen controller.

This is very interesting. As I said before, we have taken special measures to always return the latest saved in the transaction instance, no matter how many listeners reloaded and saved the entity. Perhaps it doesn’t work in some situation. I would be happy to see it in a test project.

During making the test project I found cod which makes the problem:

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void beforeCommit(EntityChangedEvent<AddressTable, UUID> event) {
addrobjList.clear();
if (event.getType() != EntityChangedEvent.Type.DELETED) {
AddressTable addressTable = tsDm.load(event.getEntityId())
.view(“edit”)
.one();
addressTable.setKorpus(“666”);
Street street = metadata.create(Street.class);
street.setStreetName(“newStreet”);
addressTable.setStreet(dataManager.commit(street));
tsDm.save(addressTable);
}
}

The main problem is further using created Street. Unfortunately, I can’t use tsBm.save() for the Street, because, I use the created Street in a list of created Street in a bean.
I am confused with this part of code, as far as I understand dataManager.commit() should return the latest version of an entity and this exception should not happen? Or I do something wrong? Thank you.

I don’t see any problems in the code you have shown. Could you provide the whole test project?

Also, please always use triple backtics to format code here on the forum. Your message is really hard to read.

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
// ...

image

Sorry, for the backtics. I found the source of trouble. I get this exception via mistakenly twice called method

transactionalDataManager.save(entity)

in the

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void beforeCommit(EntityChangedEvent<AddressTable, UUID> event)

So Datamanager works properly. Thank you for your help.

Thanks for the information on the cause.
But you still use > instead of backtics for the code.