OptimisticLockException on emailService.sendEmail

I found this in my logs today. Probably a jmix issue, because I don’t do anything with the SendingMessage entity in my code here:

javax.persistence.OptimisticLockException: Exception [EclipseLink-5010] (Eclipse Persistence Services - 2.7.9.6-jmix): org.eclipse.persistence.exceptions.OptimisticLockException
Exception Description: The object [io.jmix.email.entity.SendingMessage-b23c0f7e-3a56-75e1-0216-8cd780749a90 [detached]] cannot be merged because it has changed or been deleted since it was last read. 
Class> io.jmix.email.entity.SendingMessage
        at org.eclipse.persistence.internal.jpa.EntityManagerImpl.mergeInternal(EntityManagerImpl.java:650) ~[org.eclipse.persistence.jpa-2.7.9-6-jmix.jar!/:na]
        at org.eclipse.persistence.internal.jpa.EntityManagerImpl.merge(EntityManagerImpl.java:625) ~[org.eclipse.persistence.jpa-2.7.9-6-jmix.jar!/:na]
        at io.jmix.eclipselink.impl.JmixEntityManager.internalMerge(JmixEntityManager.java:479) ~[jmix-eclipselink-1.2.0.jar!/:na]
        at io.jmix.eclipselink.impl.JmixEntityManager.merge(JmixEntityManager.java:118) ~[jmix-eclipselink-1.2.0.jar!/:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
        at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311) ~[spring-orm-5.3.15.jar!/:5.3.15]
        at com.sun.proxy.$Proxy221.merge(Unknown Source) ~[na:na]
        at io.jmix.email.impl.EmailDataProviderImpl.lambda$updateStatus$2(EmailDataProviderImpl.java:116) ~[jmix-email-1.2.0.jar!/:na]
        at org.springframework.transaction.support.TransactionOperations.lambda$executeWithoutResult$0(TransactionOperations.java:68) ~[spring-tx-5.3.15.jar!/:5.3.15]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.15.jar!/:5.3.15]
        at org.springframework.transaction.support.TransactionOperations.executeWithoutResult(TransactionOperations.java:67) ~[spring-tx-5.3.15.jar!/:5.3.15]
        at io.jmix.email.impl.EmailDataProviderImpl.updateStatus(EmailDataProviderImpl.java:115) ~[jmix-email-1.2.0.jar!/:na]
        at io.jmix.email.impl.EmailerImpl.persistAndSendEmail(EmailerImpl.java:208) ~[jmix-email-1.2.0.jar!/:na]
        at io.jmix.email.impl.EmailerImpl.sendEmail(EmailerImpl.java:92) ~[jmix-email-1.2.0.jar!/:na]
...

Calling code:

emailService.sendEmail(
    EmailInfoBuilder.create()
        .setAddresses(sysUser.email)
        .setSubject(subject)
        .setBody(body)
        .build()
)

As far as I understand, it could happen if there was a long delay while sending this email (more than jmix.email.sending-timeout-sec), so the async sending task could pick up this SendingMessage and updated its status while the main thread was waiting.

If you don’t use asynchronous email sending, better set jmix.email.use-default-quartz-configuration property to false to avoid starting useless quartz job.