Il est très commun d’utiliser les transactions Spring dans nos projets, il est donc important de savoir quand celles-ci altéreront notre base de données.
On va voir via des exemples ce qui déclenche un rollback et comment customiser ce comportement.
On va prendre en compte dans cet article les méthodes qui sont transactionnelles via l’annotation @Transactional uniquement (et pas de façon programmatique).
Les comportements par défaut
C’est très simple, par défaut une transaction est rollback si une Runtime Exception ou une Error est throw.
Exemple d’erreurs: OutOfMemoryError, StackOverflowError etc..
Les Checked Exceptions ne provoquent pas de rollback. Autrement dit, si une checked exception est throw dans votre méthode, votre base de données sera quand même modifiée.
Pour rappel, les checked exceptions sont des exceptions doivent être gérées obligatoirement (via un try/catch ou en l’indiquant dans la signature méthode). Il y a une erreur à la compilation si ce n’est pas le cas.
Modifier le comportement par défaut
On peut Rollback dans le cas de checked exceptions en précisant rollbackFor = <le type d’exception>.
Exemple:
@Override
@Transactional(rollbackFor = SQLException.class)
public void throwCheckedExceptionSpecifyingRollbackFor() throws SQLException {
throw new SQLException();
}
On peut faire l’inverse avec noRollbackFor = <le type d’exception>
@Override
@Transactional(noRollbackFor = NullPointerException.class)
public void throwRuntimeExceptionSpecifyingNoRollbackFor() {
throw new NullPointerException();
}
On aurait alors
@SpringBootTest
public class RollbackTest {
@Autowired
private DemoBean demoBean;
@SpyBean
private PlatformTransactionManager transactionManager;
@Test
void shouldNotRollbackForCheckedWithRollbackFor() {
// SQLException is a CheckedException
// the method is annotated with @Transactional(rollbackFor = SQLException.class)
assertThatExceptionOfType(SQLException.class)
.isThrownBy(() -> demoBean.throwCheckedExceptionSpecifyingRollbackFor());
assertThatTransactionHasBeenRolledBack();
}
@Test
void shouldNotRollbackForRuntimeExceptionWithRollBackFor() {
// NPE is a RuntimeException
// the method is annotated with @Transactional(noRollbackFor = NullPointerException.class)
assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> demoBean.throwRuntimeExceptionSpecifyingNoRollbackFor());
assertThatTransactionHasBeenCommitted();
}
private void assertThatTransactionHasBeenCommitted() {
verify(transactionManager, times(1)).commit(any());
verify(transactionManager, times(0)).rollback(any());
}
private void assertThatTransactionHasBeenRolledBack() {
verify(transactionManager, times(0)).commit(any());
verify(transactionManager, times(1)).rollback(any());
}
}
Dans une application Spring, sauf exceptions, les Beans sont proxifiés. En d’autres mots, on n'interagit pas directement avec eux et ce mécanisme est à la base de l’AOP.
Beaucoup de mécanismes s'appuient sur l’AOP (les Transactions par exemple) et connaître la façon dont sont proxifiés les beans est important pour prédire et comprendre certains comportements.
La documentation S...
Prérequis
Il faut que vous ayez déjà installé un JDK. Exécutez la commande:
java --version
Si vous avez bien un output de ce type avec cette commande, vous pouvez continuer.
Dans le cas contraire, il faudra installer un JDK.
...
Introduction
Vous avez diagnostiqué une fuite mémoire et vous voulez corriger le problème.
Si vous utilisez IntelliJ, vous avez à disposition dans votre IDE un outil puissant qui vous permettra de diagnostiquer la source du problème et vérifier vot...
Introduction
JaCoCo est un outil très connu dans le monde Java qui permet de générer des rapports de code coverage au format xml et html.
L’intérêt sera souvent de donner le rapport au format xml à d’autres outils (Codecov ou Sonar par exemp...