'@Transactional doesn't rollback by calling an External method that throw an RuntimeException
I'm playing with Spring and the @Transactional annotation. I'm doing a simple experiment to test the behaviour of this annotation. These are my super simple java classes:
my domain:
package com.xxx.springdemo.transactionalAnnotation.domain;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
@Data
@Entity
public class Counter {
@Id
int id;
int count = 0;
}
my service:
package com.xxx.springdemo.transactionalAnnotation.services;
import com.xxx.springdemo.transactionalAnnotation.domain.Counter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class TransactionalService {
public void throwException(Counter counter) {
counter.setCount(1);
throw new RuntimeException("Runtime exception");
}
public void dontThrowException(Counter counter) {
counter.setCount(2);
}
}
and my controller:
package com.xxx.springdemo.transactionalAnnotation.controllers;
import com.xxx.springdemo.transactionalAnnotation.domain.Counter;
import com.xxx.springdemo.transactionalAnnotation.services.TransactionalService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class TransactionController {
private final TransactionalService transactionalService;
@GetMapping("test-transactional")
public void testTransactional() {
Counter counter = new Counter();
try {
transactionalService.throwException(counter);
} catch (Exception e) {
System.out.println("Exception caught: " + e.getMessage());
}
System.out.println("Variable hasn't changed (counter = " + counter.getCount() + ")");
}
@GetMapping("test-transactional-2")
public void testTransactionalWithoutException() {
Counter counter = new Counter();
try {
transactionalService.dontThrowException(counter);
} catch (Exception e) {
System.out.println("Exception caught: " + e.getMessage());
}
System.out.println("Variable changed (counter = " + counter.getCount() + ")");
}
}
The code should be self-explanatory. I expect to have printed:
Variable hasn't changed (counter = 0)
in case the test-transactional endpoint is called. What I get instead is:
Variable hasn't changed (counter = 1)
This means that in the service method throwException the count property isn't rollbacked after the exception is thrown.
P.S. this is my build.gradle file:
plugins {
id 'org.springframework.boot' version '2.6.2'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
