kapua icon indicating copy to clipboard operation
kapua copied to clipboard

Write retry mechanism fails on eclipslink >=2.7.13

Open dseurotech opened this issue 1 year ago • 0 comments

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:

image

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:

image

which signals to the TxManagerImpl that the entire transaction can be attempted again:

image

(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:

  1. Bump eclipslink to 2.7.13 or 2.7.14
  2. Run IdGeneratorTest.collideOnNameNotId

Expected behavior The test should pass, conflict on id within the same transaction should trigger a transaction repeat attempt.

dseurotech avatar Feb 01 '24 08:02 dseurotech