diff --git a/jee-7/src/main/java/com/baeldung/jta/AuditService.java b/jee-7/src/main/java/com/baeldung/jta/AuditService.java
new file mode 100644
index 0000000000..f9253b9d74
--- /dev/null
+++ b/jee-7/src/main/java/com/baeldung/jta/AuditService.java
@@ -0,0 +1,5 @@
+package com.baeldung.jta;
+
+public class AuditService {
+
+}
diff --git a/jta/pom.xml b/jta/pom.xml
index 9a58c57d22..89bdccf25e 100644
--- a/jta/pom.xml
+++ b/jta/pom.xml
@@ -1,46 +1,46 @@
- 4.0.0
- com.baeldung
- jta-demo
- 1.0-SNAPSHOT
- jar
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+ com.baeldung
+ jta-demo
+ 1.0-SNAPSHOT
+ jar
- JEE JTA demo
+ JEE JTA demo
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.0.4.RELEASE
-
-
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.4.RELEASE
+
+
-
- UTF-8
- UTF-8
- 1.8
-
+
+ UTF-8
+ UTF-8
+ 1.8
+
-
-
- org.springframework.boot
- spring-boot-starter-jta-bitronix
-
+
+
+ org.springframework.boot
+ spring-boot-starter-jta-bitronix
+
org.springframework.boot
spring-boot-starter-jdbc
-
- org.springframework.boot
- spring-boot-starter
-
+
+ org.springframework.boot
+ spring-boot-starter
+
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
org.hsqldb
@@ -49,40 +49,40 @@
-
-
- autoconfiguration
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- integration-test
-
- test
-
-
-
- **/*LiveTest.java
- **/*IntegrationTest.java
- **/*IntTest.java
-
-
- **/AutoconfigurationTest.java
-
-
-
-
-
-
- json
-
-
-
-
-
-
-
+
+
+ autoconfiguration
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-test
+
+ test
+
+
+
+ **/*LiveTest.java
+ **/*IntegrationTest.java
+ **/*IntTest.java
+
+
+ **/AutoconfigurationTest.java
+
+
+
+
+
+
+ json
+
+
+
+
+
+
+
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java
index 098a6f9e1f..4eb8071757 100644
--- a/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java
+++ b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java
@@ -1,8 +1,10 @@
package com.baeldung.jtademo.services;
+import com.baeldung.jtademo.dto.TransferLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
@@ -18,8 +20,14 @@ public class AuditService {
this.jdbcTemplate = jdbcTemplate;
}
- @Transactional
public void log(String fromAccount, String toAccount, BigDecimal amount) {
jdbcTemplate.update("insert into AUDIT_LOG(FROM_ACCOUNT, TO_ACCOUNT, AMOUNT) values ?,?,?", fromAccount, toAccount, amount);
}
+
+ public TransferLog lastTransferLog() {
+ return jdbcTemplate.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor) (rs) -> {
+ if(!rs.next()) return null;
+ return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3)));
+ });
+ }
}
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java
deleted file mode 100644
index acbef33427..0000000000
--- a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.baeldung.jtademo.services;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-import javax.transaction.UserTransaction;
-import java.math.BigDecimal;
-
-@Component
-public class BankAccountManualTxService {
- @Resource
- UserTransaction userTransaction;
-
- @Autowired
- @Qualifier("jdbcTemplateAccount")
- JdbcTemplate jdbcTemplate;
-
- public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) throws Exception {
- userTransaction.begin();
- jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE-? where ID=?", amount, fromAccountId);
- jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE+? where ID=?", amount, toAccountId);
- userTransaction.commit();
- }
-}
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java
index cd4aa253c5..a50628b109 100644
--- a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java
+++ b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java
@@ -3,6 +3,7 @@ package com.baeldung.jtademo.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
@@ -18,9 +19,15 @@ public class BankAccountService {
this.jdbcTemplate = jdbcTemplate;
}
- @Transactional
public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) {
jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE-? where ID=?", amount, fromAccountId);
jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE+? where ID=?", amount, toAccountId);
}
+
+ public BigDecimal balanceOf(String accountId) {
+ return jdbcTemplate.query("select BALANCE from ACCOUNT where ID=?", new Object[] { accountId }, (ResultSetExtractor) (rs) -> {
+ rs.next();
+ return new BigDecimal(rs.getDouble(1));
+ });
+ }
}
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java
index 8bef892ca2..2bec79b47e 100644
--- a/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java
+++ b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java
@@ -4,29 +4,42 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
+import javax.transaction.UserTransaction;
import java.math.BigDecimal;
@Service
public class TellerService {
private final BankAccountService bankAccountService;
private final AuditService auditService;
+ private final UserTransaction userTransaction;
@Autowired
- public TellerService(BankAccountService bankAccountService, AuditService auditService) {
+ public TellerService(BankAccountService bankAccountService, AuditService auditService, UserTransaction userTransaction) {
this.bankAccountService = bankAccountService;
this.auditService = auditService;
+ this.userTransaction = userTransaction;
}
@Transactional
public void executeTransfer(String fromAccontId, String toAccountId, BigDecimal amount) {
bankAccountService.transfer(fromAccontId, toAccountId, amount);
auditService.log(fromAccontId, toAccountId, amount);
+ BigDecimal balance = bankAccountService.balanceOf(fromAccontId);
+ if(balance.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new RuntimeException("Insufficient fund.");
+ }
}
- @Transactional
- public void executeTransferFail(String fromAccontId, String toAccountId, BigDecimal amount) {
+ public void executeTransferProgrammaticTx(String fromAccontId, String toAccountId, BigDecimal amount) throws Exception {
+ userTransaction.begin();
bankAccountService.transfer(fromAccontId, toAccountId, amount);
auditService.log(fromAccontId, toAccountId, amount);
- throw new RuntimeException("Something wrong, rollback!");
+ BigDecimal balance = bankAccountService.balanceOf(fromAccontId);
+ if(balance.compareTo(BigDecimal.ZERO) <= 0) {
+ userTransaction.rollback();
+ throw new RuntimeException("Insufficient fund.");
+ } else {
+ userTransaction.commit();
+ }
}
}
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java
index 21370cf034..7b818b3771 100644
--- a/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java
+++ b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java
@@ -43,17 +43,5 @@ public class TestHelper {
}
}
- public TransferLog lastTransferLog() {
- return jdbcTemplateAudit.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor) (rs) -> {
- if(!rs.next()) return null;
- return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3)));
- });
- }
- public BigDecimal balanceOf(String accountId) {
- return jdbcTemplateAccount.query("select BALANCE from ACCOUNT where ID=?", new Object[] { accountId }, (ResultSetExtractor) (rs) -> {
- rs.next();
- return new BigDecimal(rs.getDouble(1));
- });
- }
}
diff --git a/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java
index 68ce5531a1..2f72098c41 100644
--- a/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java
+++ b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java
@@ -1,9 +1,7 @@
package com.baeldung.jtademo;
import com.baeldung.jtademo.dto.TransferLog;
-import com.baeldung.jtademo.services.BankAccountManualTxService;
-import com.baeldung.jtademo.services.TellerService;
-import com.baeldung.jtademo.services.TestHelper;
+import com.baeldung.jtademo.services.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -25,7 +23,10 @@ public class JtaDemoUnitTest {
TellerService tellerService;
@Autowired
- BankAccountManualTxService bankAccountManualTxService;
+ BankAccountService accountService;
+
+ @Autowired
+ AuditService auditService;
@Before
public void beforeTest() throws Exception {
@@ -34,14 +35,13 @@ public class JtaDemoUnitTest {
}
@Test
- public void whenNoException_thenAllCommitted() throws Exception {
+ public void givenAnnotationTx_whenNoException_thenAllCommitted() throws Exception {
tellerService.executeTransfer("a0000001", "a0000002", BigDecimal.valueOf(500));
- BigDecimal result = testHelper.balanceOf("a0000001");
- assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
- assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
+ assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
+ assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
- TransferLog lastTransferLog = testHelper.lastTransferLog();
+ TransferLog lastTransferLog = auditService.lastTransferLog();
assertThat(lastTransferLog).isNotNull();
assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001");
assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002");
@@ -49,22 +49,39 @@ public class JtaDemoUnitTest {
}
@Test
- public void whenException_thenAllRolledBack() throws Exception {
+ public void givenAnnotationTx_whenException_thenAllRolledBack() throws Exception {
assertThatThrownBy(() -> {
- tellerService.executeTransferFail("a0000002", "a0000001", BigDecimal.valueOf(100));
- }).hasMessage("Something wrong, rollback!");
+ tellerService.executeTransfer("a0000002", "a0000001", BigDecimal.valueOf(100000));
+ }).hasMessage("Insufficient fund.");
- assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
- assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));
-
- assertThat(testHelper.lastTransferLog()).isNull();
+ assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
+ assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));
+ assertThat(auditService.lastTransferLog()).isNull();
}
@Test
- public void givenBMT_whenNoException_thenAllCommitted() throws Exception {
- bankAccountManualTxService.transfer("a0000001", "a0000002", BigDecimal.valueOf(100));
+ public void givenProgrammaticTx_whenCommit_thenAllCommitted() throws Exception {
+ tellerService.executeTransferProgrammaticTx("a0000001", "a0000002", BigDecimal.valueOf(500));
- assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(900));
- assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2100));
+ BigDecimal result = accountService.balanceOf("a0000001");
+ assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
+ assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
+
+ TransferLog lastTransferLog = auditService.lastTransferLog();
+ assertThat(lastTransferLog).isNotNull();
+ assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001");
+ assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002");
+ assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500));
+ }
+
+ @Test
+ public void givenProgrammaticTx_whenRollback_thenAllRolledBack() throws Exception {
+ assertThatThrownBy(() -> {
+ tellerService.executeTransferProgrammaticTx("a0000002", "a0000001", BigDecimal.valueOf(100000));
+ }).hasMessage("Insufficient fund.");
+
+ assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
+ assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));
+ assertThat(auditService.lastTransferLog()).isNull();
}
}