Why Doesn’t Rollback Happen in Self-Invocation with @Transactional? You annotate a method with @Transactional. An exception occurs. You expect a rollback. But the data is still committed. If this happens in Spring Framework, one common reason is self-invocation. What Is Self-Invocation? Self-invocation happens when a method inside a class calls another method of the same class. At first glance, this seems perfectly fine. But here’s the hidden problem. Why Rollback Doesn’t Happen: Spring applies @Transactional using a proxy mechanism. -When a method is called from outside the class, the call goes through Spring’s proxy. -The proxy starts the transaction and manages rollback. However, when a method calls another method inside the same class: -The call happens directly within the object. -It bypasses Spring’s proxy. -Spring never intercepts the call. -The transaction is never started. And if no transaction was started, rollback cannot happen. The Real Reason: Rollback doesn’t fail because of the exception. Rollback fails because Spring never got the chance to manage that internal method call. No proxy interception → No transaction → No rollback. Key Takeaway: @Transactional is not just an annotation. It works only when the method call goes through Spring’s proxy. #Java #SpringBoot #SpringFramework #BackendDevelopment #SoftwareEngineering #Microservices #AOP #Transactional
Transactional Rollback Fails in Self-Invocation with Spring
More Relevant Posts
-
🚀 Spring Annotation-Based Configuration (Beginner Friendly Guide) If you’re starting with Spring, understanding how the IOC container works is super important. Let’s break it down with a simple example 👇 👉 1. Main Class (Entry Point) import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { // Step 1: Load Spring configuration file ApplicationContext container = new ClassPathXmlApplicationContext("applicationContext.xml"); // Step 2: IOC container is ready and beans are created automatically System.out.println("IOC Container Loaded Successfully ✅"); } } 👉 2. applicationContext.xml (Configuration File) <beans xmlns="https://lnkd.in/d858D-Nk" xmlns:xsi="https://lnkd.in/dNJZbNmc" xmlns:context="https://lnkd.in/dEDWzfEq" xsi:schemaLocation=" https://lnkd.in/d858D-Nk https://lnkd.in/dbit7sVK https://lnkd.in/dEDWzfEq https://lnkd.in/daN7U-FT"> <!-- Scan this package for annotations --> <context:component-scan base-package="org.annotationbasedconfiguration"/> </beans> 💡 What does this mean? ✔️ Spring reads the XML file ✔️ Scans the given package ✔️ Finds classes with annotations like: @Component @Service @Repository ✔️ Automatically creates objects (Beans) and manages them 🎯 Why use an Annotation-Based Approach? ✅ Less XML configuration ✅ Cleaner code ✅ Easy to manage ✅ Industry standard approach 👉 Simple Understanding: "Just add annotations in your class, and Spring will create & manage objects for you." #Java #SpringFramework #Beginners #BackendDevelopment #IoC #DependencyInjection #CodingJourney
To view or add a comment, sign in
-
If your domain is mostly String, int, and BigDecimal, you will likely ship more avoidable bugs. For Java and Spring teams, this is a common trap: primitive obsession (a domain model built from raw primitives). It feels productive because JSON serialization and JPA (Java Persistence API) mapping often just work. The cost shows up later as duplicated validation, unclear intent, and easy-to-swap parameters. Rule of thumb: promote a field to a type when it carries meaning beyond its raw representation. Example: In a checkout flow, you have BigDecimal amount and a String discount. One endpoint treats discount as 10 (10%), another treats it as 0.10. Then a third place rounds differently. Introduce a PercentDiscount value object that accepts one representation, normalizes it, and enforces invariants (range, scale, rounding). Now "10 vs 0.10" is not a recurring debate. It is a constructor rule. When a field should become a type: - You validate the same rule in more than one place (invariants). - You keep normalizing or formatting it (behavior). - It has multiple representations (cents vs dollars, case-insensitive codes). - It is easy to mix up with other fields of the same primitive. - It is part of the ubiquitous language (Money, OrderId, EmailAddress). Trade-off: more types means more boundary plumbing. In Spring, you may need Jackson configuration (for example, @JsonCreator and @JsonValue) and JPA mapping (AttributeConverter or @Embeddable). What is one field in your codebase that is still a String, but should be a type? Inspiration: https://lnkd.in/dEarQAaW #java #ddd #architecture #programming #cleancode #clean #code
To view or add a comment, sign in
-
-
💡 The "LGTM" Trap: Why Your Code Reviews Might Be Failing Your Team We’ve all been there. You’re staring at a 500-line Pull Request, you’re behind on your own sprint tasks, and you’re tempted to just hit "Approve" because the build passed. But here is the hard truth: A "Looks Good To Me" without a deep dive is a missed opportunity for mentorship and technical debt prevention. In Java development, a great code review isn't just about finding syntax errors; it’s about ensuring the long-term health of the codebase. Here’s my 3-step checklist for a high-impact review: * Check for Side Effects: Is that "simple" change in the Service layer going to trigger an N+1 query problem in Hibernate elsewhere? * Readability over Cleverness: If I can’t understand the logic of a Stream pipeline or a nested Lambda in 30 seconds, it probably needs a refactor or a comment. * The "Future-Proof" Test: Does this implementation follow our architectural patterns, or is it a "quick fix" that we’ll be rewriting in six months? Code reviews are a conversation, not a critique. Let’s treat them like the collaborative superpower they are. How do you handle large PRs? Do you have a "limit" on how many lines you'll review at once? Let’s discuss in the comments! 👇 #JavaDevelopment #CodeReview #SoftwareEngineering
To view or add a comment, sign in
-
🚨 Code Review is not a rubber stamp. If a review only catches formatting, naming, or missing semicolons, the linter should have done that already. Real backend code review is about preventing production problems before they happen. When I open a Pull/Merge Request, these are the things I look for first: 1️⃣ Memory & Resource Leaks • Large objects staying in memory longer than needed • Loading the whole file or too much content into memory for processing. • Collections that can grow without bounds • Streams, files, or DB connections not properly closed Small leaks rarely fail immediately. They slowly become production incidents under load. 2️⃣ Database Efficiency • Fetching full JPA entities when only a few columns are needed • Sequential DB calls that could be batched or parallelized • Hidden N+1 queries inside loops Many “slow APIs” are not compute problems. They are query problems hiding behind ORM abstractions. 3️⃣ Execution Safety • Recursive logic without guaranteed termination • Deep call chains that could cause stack exhaustion • Blocking operations in critical paths Code that works in tests can still fail under real concurrency. 4️⃣ Observability If this fails at 3 AM in production, will we know why? • Are logs meaningful or just noise? • Do we have trace IDs or request correlation? • Can we identify the failing step quickly? Debugging without observability is guesswork. 5️⃣ Failure Handling • What happens if a downstream service times out? • Are timeouts, retries, or fallbacks defined? • Or will threads just hang until the system degrades? Resilience is rarely added later. It must be designed early. 6️⃣ The 6-Month Test If another developer reads this code six months from now, will they understand it immediately? Readable code reduces future bugs. Complex code guarantees them. A code review is not about approving code. It’s about asking: “Is this safe to run in production?” 💬 What is the first red flag that makes you request changes in a Pull Request? #SoftwareEngineering #CodeReview #BackendDevelopment #Java #SpringBoot #SystemDesign #CleanCode
To view or add a comment, sign in
-
-
What happens when an exception is thrown inside a finally block? • We all learn early that finally always executes • But there’s a dangerous edge case many developers miss Consider this: • An exception occurs in the try block • Control moves to finally • Another exception is thrown inside finally What Java actually does: • The exception from finally overrides the original exception • The original exception is silently lost • Debugging becomes painful because the real cause disappears Why this is risky: • You think cleanup is handled safely • But the real failure gets masked Real-world scenario: • DB query fails → exception thrown • finally tries to close the connection • close() throws another exception • You only see the cleanup failure, not the DB issue Best practices: • Never throw new exceptions from finally • Keep finally simple and safe • Use try-with-resources whenever possible • Log inside finally, don’t propagate Key takeaway: • finally is for cleanup — not logic, not errors, not control flow If this surprised you, you’re not alone. #Java #ExceptionHandling #BackendDevelopment #CleanCode #LearningInPublic
To view or add a comment, sign in
-
💡 Understanding Collection-Based Dependency Injection in Spring When we talk about Dependency Injection (DI) in Spring, most of us think about injecting a single object. But did you know you can inject multiple beans at once using collections? 🤔 Let’s break it down in a simple way 👇 🔹 What is Collection-Based DI? Instead of injecting one object, Spring can inject a list, set, or map of beans into your class. 👉 This is useful when you have multiple implementations of the same interface. 🔹 What’s Happening Here? ✅ Spring scans all beans of type PaymentService ✅ It collects them into a List ✅ Injects them automatically into PaymentProcessor 🔹 Other Supported Collections You can also use: ✔ List<Interface> ✔ Set<Interface> ✔ Map<String, Interface> → Key = bean name Example: Map<String, PaymentService> paymentMap; 🔹 Why is this Useful? ✔ Helps implement strategy pattern easily ✔ Avoids manual bean selection ✔ Makes code more flexible & scalable 🔹 Pro Tip 🚀 Spring injects collections in a specific order if you use @Order or @Priority. 🔚 Summary Collection-based DI = Inject multiple beans → Handle dynamically → Write cleaner code If you're learning Spring deeply, this concept is a game changer when building scalable systems 🔥 #Java #SpringBoot #DependencyInjection #BackendDevelopment #CleanCode
To view or add a comment, sign in
-
-
Hi everyone 👋 📌 Spring Boot Annotation Series Part 19 – @PutMapping The @PutMapping annotation is used to handle HTTP PUT requests in a Spring Boot application. It is part of the Spring Framework and is mainly used to update existing resources in REST APIs. 🔹 What is @PutMapping? @PutMapping is a shortcut for: @RequestMapping(method = RequestMethod.PUT) It makes the code cleaner and more readable. 🔹 When Do We Use PUT? ✔ To update existing data ✔ To replace a resource completely ✔ When operation should be idempotent Example use cases: Update user details Update product information Modify order status 🔹 Important Concept – Idempotency PUT is idempotent ✔ That means: Calling the same PUT request multiple times → Result will remain the same. Unlike POST ❌ (which may create multiple records). 🔹 In Simple Words @PutMapping handles update operations in REST APIs. When a PUT request hits the URL, Spring updates the existing resource. #SpringBoot #Java #RESTAPI #BackendDevelopment #InterviewPreparation #LearningInPublic
To view or add a comment, sign in
-
I lost 4 hours debugging a production issue. No errors. No failed logs. Everything looked “correct”. The bug? A single annotation I’ve used hundreds of times. — Trap 1 — Internal call trap I had a method calling another @Transactional method in the same class. Looked clean. Felt correct. Was completely broken. public void placeOrder() { processPayment(); // @Transactional } The transaction never started. Spring works through proxies. Internal method calls bypass the proxy. So the annotation is effectively ignored. I learned this after data was partially written in production with no clear reason. Fix: Move the transactional method to a separate @Service class. — Trap 2 — rollbackFor is not optional By default, Spring only rolls back on RuntimeException. I threw a checked exception once. Everything committed. No rollback. No warning. Just inconsistent data. @Transactional(rollbackFor = Exception.class) This should not be optional. Write it every time. — Trap 3 — readOnly = true Most people skip this on read queries. I did too. Until performance issues showed up under load. Without it: unnecessary write locks no DB-level optimizations risk of accidental flush @Transactional(readOnly = true) public List getUsers() { ... } Takes 2 seconds to add. Costs hours if ignored. — All three have one thing in common: They fail silently. That’s what makes them dangerous. — How I debug this now Enable: spring.jpa.show-sql=true logging.level.org.springframework.tx=DEBUG Watch for: → missing transactions → unexpected commits → no rollback on failure Catch it in dev. Not prod. Save this. You won’t remember it today. You’ll need it in production. Which one have you already been hit by?😅 #SpringBoot #Java #BackendDevelopment #SoftwareEngineering #JavaDeveloper #TechContent #DevTips #LearnToCode #CodeNewbie #DevelopersLife #SpringFramework #Microservices #SystemDesign #Coding #Programming #Transactional #CleanCode #BackendEngineer #JavaTips #SpringBootTips
To view or add a comment, sign in
-
-
Spring Core Modules Spring Core is the heart of the Spring Framework. It provides: • IoC (Inversion of Control) • Dependency Injection (DI) • Bean Lifecycle Management • Application Context Instead of creating objects manually, Spring manages them for us. This improves: Loose coupling Testability Maintainability Scalability ============================ Simple Example (Without Spring) ============================ class Engine { void start() { System.out.println("Engine started"); } } class Car { Engine engine = new Engine(); / Tight coupling void drive() { engine.start(); } } Here, Car is tightly coupled to Engine ================================ With Spring (Dependency Injection) ================================ @Component class Engine { void start() { System.out.println("Engine started"); } } @Component class Car { private final Engine engine; @Autowired public Car(Engine engine) { this.engine = engine; } void drive() { engine.start(); } } Spring injects the dependency. Car does not create Engine - Spring provides it. That’s the power of IoC. --------------------------------------------------------------- Spring Core is not just a framework feature. It’s a design philosophy - write loosely coupled code and let the container manage object lifecycle. Tomorrow: Bean Lifecycle & ApplicationContext deep #Java #SpringFramework #SpringBoot #BackendDevelopment #Microservices #LearningInPublic
To view or add a comment, sign in
-
Spring and Boot always have struck me as unusual names for a framework. Someday I'll have to ask someone about the history behind those choices. There's no doubt though that Spring Boot is the play in the Enterprise Java space, and I'm pleased to present Testing Spring Boot Applications by Daniel Garnier-Moiroux as one of our newest additions to the Manning Early Access Program. Spring Boot With Microservices #Spring #Boot #Java Manning Publications Co. https://lnkd.in/gTmQxJ97
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development