Bonjour,

J'ai une application Spring Boot on ne peut plus classique.

J'ai une classe annotée @Service dans laquelle j'ai une méthode annotée @Transactional. Le but étant que si ça pète, peut-importe le type d'exception jetée, un rollback soit fait.
Malheureusement, aucun rollback n'est fait.

Je vous mets un peu de code :

Le service :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Service("ppService")
public class PlanProgresServiceImpl implements PlanProgresService
{
    @Resource
    private DeploiementDAO deploiementDao;
 
    ...
 
    @Override
    @Transactional(rollbackFor = TechnicalErrorException.class)
    public Set<String> deployer(PlanProgresType planProgresType, List<Integer> listIdUo, boolean sharepoint, Campagne campagne)
            throws TechnicalErrorException
 
        ...
 
        createDeploiement(deploiement);
 
        throw new TechnicalErrorException("temporary exception to test the transactional behavior");
    }
 
 
    @Override
    public void createDeploiement(Deploiement deploiement)
    {
        deploiementDao.save(deploiement);
    }
}
Le DAO :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
public interface DeploiementDAO extends CrudRepository<Deploiement, Integer>
{
    List<Deploiement> findByUniteOperationnelle(UniteOperationnelle uo);
}
Comme vous pouvez le constater, j'ai forcé une exception pour tester le comportement transactionnel de la méthode. Mais malgré tout, la ligne est toujours inséré en base de données (une BDD PostgreSQL).

J'ai décidé d'afficher un log des transactions en ajoutant la ligne suivante à mon fichier application.yml :
logging.level.org.springframework.transaction.interceptor: TRACE
Et cela me donne la trace suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
2017-05-02 19:38:24.449 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2017-05-02 19:38:24.450 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
Je trouve ça étrange, juste avant l'exception, on m'indique que la sauvegarde du déploiement est commité ?
En regardant le code de SimpleJpaRepository, je constate que la méthode save() est transactionnelle. Ce qui explique les deux lignes ci-dessus :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
@Transactional
public <S extends T> S save(S entity) {
 
    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}
Du coup, comment puis-je rendre ma méthode transactionnelle ?

Ce que j'ai essayé :

  • Ajouter @EnableTransactionManagement à une classe @Configuration
  • Lancer une RuntimeException au lieu d'une "checked exception"
  • Mettre "Exception.class" au lieu de "TechnicalErrorException.class" dans le rollbackFor de @Transactional