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
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Building a CRUD Application With Spring and SimpleJdbcMapper
  • How to Marry MDC With Spring Integration
  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux

Trending

  • Beyond the Wall of Charts: How Advanced Observability Displaced the Telemetry Dashboard
  • Beyond @Transactional: Solving the Dual-Write Problem in Distributed Microservices
  • Introduction to Error Prone: How to Catch Bugs at Compile Time
  • Rebuilding Elasticsearch Under Load: Unsafe Watermarks and a Sampling Blind Spot

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  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 
Shaamik Mitraa
·
Feb. 03, 17 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
154.9K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

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 Shaamik Mitraa. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Building a CRUD Application With Spring and SimpleJdbcMapper
  • How to Marry MDC With Spring Integration
  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

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 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook