kapua
kapua copied to clipboard
Write retry mechanism fails on eclipslink >=2.7.13
Describe the bug
do NOT bump the eclipselink dependency to version 2.7.13 or more (current version: 2.7.14). It breaks the transaction retry mechanism currently in place to support randomly generated entities ids - albeit in a very rare corner case situation.
The retry mechanism in Kapua
Currently Kapua implements a mechanism to generate random ids for entities, in order to avoid information disclosure on ids (as would happen with an incremental. This is implemented using the @PrePersists annotation on AbstractKapuaEntity:
/**
* Before create action sets the {@link KapuaEntity} {@link #id}, {@link #createdBy} and {@link #createdOn}.
*
* @since 1.0.0
*/
@PrePersist
protected void prePersistsAction() {
setId(new KapuaEid(IdGenerator.generate()));
setCreatedBy(KapuaSecurityUtils.getSession().getUserId());
setCreatedOn(new Date());
}
Together with a retry mechanism in the create method of the KapuaEntityJpaRepository
:
When persisting the entity, if a constraint violation exception is thrown (line 109) then an attempt is made to find existing entities with the same id already present in the database (line 111). If an entity is found (meaning the conflict is on the entity's id), then a specific KapuaEntityExistsException
exception is thrown (line 117).
Such exception is intercepted in JpaTxContext.isRecoverableException
:
which signals to the TxManagerImpl
that the entire transaction can be attempted again:
(commit at line 53 fails, method isRecoverableException
invoked at line 58, line 64 check whether there are still attempt possible - if there are we return to the beginning of the loop at line 48).
The problem
If you are persisting two conflicting entities in the same transaction, the second one fails - the KapuaEntityJpaRepository
searches for an entity with the same id, finds the first one persisted in the same transaction and notifies the conflict, triggering a the generation of a new (hopefully unique) id for the second entity.
This does not work in eclipselink version >=2.7.13 : in this version of the library, the first entity is NOT found by the entitymanager. In other words, entities not yet persisted in the same transaction are NOT retrieved by the entitymanger. Either this is a problem to be notified to eclipselink, or kapua's behaviour must be altered accordingly.
The problem was introduced by this PR (1843), which attempts to fix Issue 1596
To Reproduce Steps to reproduce the behavior:
- Bump eclipslink to 2.7.13 or 2.7.14
- Run
IdGeneratorTest.collideOnNameNotId
Expected behavior The test should pass, conflict on id within the same transaction should trigger a transaction repeat attempt.