🏦 Transactions in Jakarta EE: The Bank Vault Story
Imagine you’re a bank manager. Every day, people move money between accounts. But here’s the scary part: what if the power goes out right in the middle of moving money? 😱
One person’s account shows money gone… but the other person never got it!
That’s why we have transactions — a special promise that says:
“Either EVERYTHING works perfectly, or NOTHING changes at all.”
Let’s explore how Jakarta EE makes this magic happen!
🎯 What You’ll Learn
graph TD A["Jakarta Transactions Overview"] --> B["Transaction Demarcation"] B --> C["Container-Managed Transactions"] C --> D["Transaction Attributes"] D --> E["Transaction Propagation"] E --> F["Bean-Managed Transactions"] F --> G["UserTransaction Interface"] G --> H["Transaction Rollback"]
📚 Jakarta Transactions Overview
What’s a Transaction?
Think of a transaction like a protective bubble around your work.
Real-life example: You’re buying ice cream 🍦
- You give money
- You get ice cream
Both steps MUST happen together. You can’t just give money and get nothing!
The ACID Promise
Transactions follow four magic rules (ACID):
| Letter | Meaning | Like… |
|---|---|---|
| A | Atomic | All-or-nothing (like a bubble) |
| C | Consistent | Rules never break |
| I | Isolated | Others can’t see half-done work |
| D | Durable | Once done, it stays done forever |
Example: Moving $100 from Mom to Dad’s account:
// This is ONE transaction (atomic)
momsAccount.withdraw(100); // Step 1
dadsAccount.deposit(100); // Step 2
// Both work, or NEITHER works!
🎬 Transaction Demarcation
What Does “Demarcation” Mean?
“Demarcation” is just a fancy word for drawing a line.
It answers: “Where does my transaction START and END?”
Think of it like putting your toys in a magic circle ⭕:
- Inside the circle = one transaction
- Outside = not part of it
Two Ways to Draw the Line
| Approach | Who Draws? | Difficulty |
|---|---|---|
| Container-Managed | The server does it FOR you | Easy! 😊 |
| Bean-Managed | YOU do it yourself | More control 🎮 |
🤖 Container-Managed Transactions (CMT)
Let the Robot Help!
Imagine you have a robot helper 🤖 that automatically:
- Starts your transaction when you begin work
- Ends it when you finish
- Fixes problems if something breaks
That’s Container-Managed Transactions!
How to use it: Just add @Stateless or @Stateful to your class:
@Stateless
public class BankService {
public void transferMoney(
Account from,
Account to,
int amount) {
// Transaction starts automatically!
from.withdraw(amount);
to.deposit(amount);
// Transaction ends automatically!
}
}
Magic! You didn’t write ANY transaction code. The container (robot) did it all!
Why CMT is Awesome
✅ Less code to write ✅ Fewer mistakes ✅ Server handles the hard stuff
🏷️ Transaction Attributes
Giving Instructions to Your Robot
Remember our robot helper? We can give it special instructions about HOW to handle transactions.
These instructions are called Transaction Attributes.
The 6 Magic Instructions
graph TD A["Transaction Attributes"] --> B["REQUIRED"] A --> C["REQUIRES_NEW"] A --> D["MANDATORY"] A --> E["NOT_SUPPORTED"] A --> F["SUPPORTS"] A --> G["NEVER"]
| Attribute | What It Means | Like… |
|---|---|---|
| REQUIRED | Use existing OR make new | “Join the party, or start one!” 🎉 |
| REQUIRES_NEW | ALWAYS make a brand new one | “I want my OWN party!” |
| MANDATORY | MUST have existing | “No party? I’m not coming!” 😤 |
| NOT_SUPPORTED | Pause any transaction | “No parties while I work” |
| SUPPORTS | Whatever, I’m flexible | “Party or not, I’m fine” 😊 |
| NEVER | Must NOT have transaction | “If there’s a party, I leave!” |
Example: Using REQUIRES_NEW
@Stateless
public class AuditService {
@TransactionAttribute(
TransactionAttributeType.REQUIRES_NEW)
public void logAction(String action) {
// This ALWAYS gets its own
// transaction - even if main
// transaction fails, log stays!
}
}
Why? Even if the bank transfer fails, we STILL want to record that someone tried!
🌊 Transaction Propagation
Passing the Bubble Along
When one method calls another method, what happens to the transaction?
It propagates (spreads) like ripples in water! 🌊
Example Story:
BankService.transfer()
└── starts transaction bubble 🫧
└── calls AccountService.withdraw()
└── bubble spreads here too! 🫧
└── calls AccountService.deposit()
└── bubble spreads here too! 🫧
└── bubble pops (transaction ends)
Visual Flow
graph TD A["transfer - starts TX"] --> B["withdraw"] A --> C["deposit"] B --> D["same TX bubble"] C --> D D --> E["TX commits or rolls back"]
All three methods share ONE transaction. If ANY fails, they ALL undo!
🎮 Bean-Managed Transactions (BMT)
Taking Control Yourself
Sometimes the robot isn’t enough. YOU want to decide exactly when transactions start and stop.
That’s Bean-Managed Transactions!
How to enable it:
@Stateless
@TransactionManagement(
TransactionManagementType.BEAN)
public class CustomBankService {
// Now YOU control everything!
}
When to Use BMT?
| Use BMT When… | Example |
|---|---|
| Need multiple transactions | Log first, then process |
| Complex timing required | Wait for user input |
| Fine-grained control | Partial commits needed |
🔑 UserTransaction Interface
Your Transaction Remote Control
When using BMT, you need a remote control to manage transactions.
That remote control is called UserTransaction!
The Three Magic Buttons
| Method | What It Does | Like… |
|---|---|---|
begin() |
Starts transaction | Press PLAY ▶️ |
commit() |
Saves everything | Press SAVE 💾 |
rollback() |
Undoes everything | Press UNDO ↩️ |
Complete Example
@Stateless
@TransactionManagement(
TransactionManagementType.BEAN)
public class ManualBankService {
@Resource
UserTransaction ut;
public void transfer(
Account from,
Account to,
int amount) {
try {
ut.begin(); // START! ▶️
from.withdraw(amount);
to.deposit(amount);
ut.commit(); // SAVE! 💾
} catch (Exception e) {
ut.rollback(); // UNDO! ↩️
}
}
}
Important Rules
⚠️ Always end what you start!
- Started with
begin()? Must callcommit()ORrollback() - Never leave a transaction hanging!
⏪ Transaction Rollback
The Magic Undo Button
Something went wrong? Rollback to the rescue!
A rollback is like pressing CTRL+Z — everything goes back to how it was before!
Three Ways to Rollback
1. Automatic (Runtime Exceptions)
public void transfer(int amount) {
if (amount < 0) {
// This causes automatic rollback!
throw new RuntimeException(
"Amount can't be negative!");
}
}
2. Manual with EJBContext
@Resource
EJBContext ctx;
public void transfer(int amount) {
if (somethingWrong) {
ctx.setRollbackOnly();
// Transaction will rollback
// when method ends
}
}
3. Manual with UserTransaction (BMT)
try {
ut.begin();
// do work...
ut.commit();
} catch (Exception e) {
ut.rollback(); // Explicit undo!
}
Checked vs Unchecked Exceptions
| Exception Type | Default Behavior | Example |
|---|---|---|
| Unchecked (RuntimeException) | Auto rollback ↩️ | NullPointerException |
| Checked (Exception) | NO rollback | IOException |
Want checked exceptions to rollback too?
@ApplicationException(rollback = true)
public class InsufficientFundsException
extends Exception {
// Now this WILL cause rollback!
}
🎯 Quick Summary
| Concept | Remember This |
|---|---|
| Transaction | Protective bubble: all-or-nothing |
| Demarcation | Where transaction starts/ends |
| CMT | Container handles it automatically |
| Attributes | Instructions for your robot helper |
| Propagation | Bubble spreads to called methods |
| BMT | You control with UserTransaction |
| UserTransaction | begin(), commit(), rollback() |
| Rollback | The magic undo button |
🧠 Key Takeaways
-
Transactions protect your data — like a bank vault protects money
-
CMT is easier — let the container do the work
-
BMT gives control — when you need it
-
Always handle failures — rollback is your friend!
-
Transaction attributes matter — choose the right one for your situation
🌟 You Did It!
You now understand how Jakarta EE keeps your data safe with transactions!
Remember: A transaction is just a promise that your data stays consistent, no matter what goes wrong.
“Either everything succeeds together, or nothing changes at all.”
That’s the power of transactions! 🚀
