DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux
  • Graceful Shutdown: Spring Framework vs Golang Web Services
  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4

Trending

  • Start Coding With Google Cloud Workstations
  • Designing for Sustainability: The Rise of Green Software
  • Next-Gen IoT Performance Depends on Advanced Power Management ICs
  • Building Resilient Networks: Limiting the Risk and Scope of Cyber Attacks
  1. DZone
  2. Coding
  3. Frameworks
  4. A Word on Spring @Transactional and Exceptions

A Word on Spring @Transactional and Exceptions

Spring's @Transactional is very popular among developers. Yet, many of them are unaware of its weird exception handling convention, which can lead to inconsistent data.

By 
Shamik Mitra user avatar
Shamik Mitra
·
Feb. 03, 17 · Tutorial
Likes (80)
Comment
Save
Tweet
Share
153.9K Views

Join the DZone community and get the full member experience.

Join For Free

A unit of work transaction either succeeds or fails and rolls back. So suppose we are dealing with transferring money from one account to another. Now, say money from one account is already debited but when it gets credited to another account, there was an exception. Obviously, the ideal scenario would be for the debited action to roll back. Otherwise, we're dealing with an inconsistent state (and some very angry account owners).

So if we use transactions in our business logic, we can ensure the logic under the transaction works as a unit and that it will roll back if anything is found to be wrong.

Either the unit of work completely succeeds or completely fails. There is no intermediate state. Now the question comes, "How we can handle a transaction?"

There are two ways to handle it:

  • BMT: Bean Managed Transaction

  • CMT: Container Managed Transaction

BMT

If we need a finer control over business logic or want to introduce savepoints, this type of technique should be adopted, where a bean provider has a responsibility to start, commit, and roll back the transaction.

CMT

If we want to delegate the responsibility to a container, we use this instead. Sometimes we call it a declarative transaction. We all know in Spring that, using the @Transactional annotation, we can adopt a declarative transaction technique.

A Weird Case

We're not going to go into configuration in this article. Instead, I'm going to warn you about some precautions you want to take while using @Transactional. Study the pseudo code below:

@Transactional
public void transferMoney(Account to, Account from, int amount) throws Exception {
    debiFromAccount(from, amount)
    creditToAccount(to, amount);
}

public debitFromAccount(Account from, int amount) {
    //do staff and debited money from data base
}

public creditToAccount(Account to, int amount) throws Exception {
    //do straff
    throw new Exception("Error during credit");
}

Now do a dry run:

  1. If Account from's initial balance is 1000

  2. Account to is 500

  3. Transfer amount is 100

  4. Afterward, an error occurred in creditToAccount(Account to,int amount)

What will be the output you expect?

To: 500

From: 1000

After all, I use @Transactional. If there's an exception, it should be rolled back, right?

But unfortunately, it left an inconsistent state.

Our output is:

To: 500

From: 900

What's going on here?

Let me clear this up for you. @Transactional only rolls back transactions for unchecked exceptions. For checked exceptions and their subclasses, it commits data. So although an exception is raised here, because it's a checked exception, Spring ignores it and commits the data to the database, making the system inconsistent.

The Spring documentation says:

While the EJB default behavior is for the EJB container to automatically roll back the transaction on a system exception (usually a runtime exception), EJB CMT does not roll back the transaction automatically on an application exception (that is, a checked exception other than java.rmi.RemoteException). While the Spring default behavior for declarative transaction management follows EJB convention (roll back is automatic only on unchecked exceptions), it is often useful to customize this.

Pay attention to the last line: “it is often useful to customize this.” So how can we customize it?

It's very simple, just use the following with @Transactional:

@Transactional(rollbackFor = Exception.class)

So if you throw an Exception or a subclass of it, always use the above with the @Transactional annotation to tell Spring to roll back transactions if a checked exception occurs.

Spring Framework

Published at DZone with permission of Shamik Mitra, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux
  • Graceful Shutdown: Spring Framework vs Golang Web Services
  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!