Tyler Murry
Tyler Murry

Reputation: 2815

@Transactional method not rolling back when surrounded by a try-catch

I have a process that iterates through a list of events and saves them to a table. If a particular event throws an exception, I need to be able to rollback that event's transactions with the database without effecting the flow through the other events.

To achieve this, I have the following setup:

public class EventService
{
    public void processEvents()
    {
        List<Event> events = getEvents();

        foreach(Event event : events)
        {
            try
            {
                processEvent(event);
            }
            catch(Exception e)
            {
                // log the exception and continue processing additional events
            }
        }
    }

    @Transactional
    public void processEvent(Event event)
    {
        // Process event and insert rows into database
        // Some event will throw a runtime exception
    }
}

However, this is not rolling back the event if there is an exception thrown.

Is there a way to achieve what I'm trying to do here?

Upvotes: 2

Views: 1298

Answers (4)

PNS
PNS

Reputation: 19905

You could also try a "pure Java" approach, if "manual" rollback is possible:

public void processEvents()
{
    List<Event> events = getEvents();

    boolean rollback = false;

    for (Event event : events)
    {
        try
        {
            processEvent(event);
        }
        catch (Exception e)
        {
            // log the exception and continue processing additional events
            rollback = true;
        }
        finally
        {
            if (rollback)
            {
                ...               // "Manually" roll back the transaction
                rollback = false; // Deactivate rolling back
            }
        }

    }
}

Upvotes: 0

JustinKSU
JustinKSU

Reputation: 4989

If you call a method within the same class, Spring AOP does not have a chance to intercept the method. Therefore the @Transactional annotation is ignored. Trying moving the processEvent method to another class that is Spring injected.

Upvotes: 5

dhamibirendra
dhamibirendra

Reputation: 3046

You will need to define your process Event with Propagation.REQUIRES_NEW and rollbackFor = Exception.class as below:

@Transactional(propagation=Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
public void processEvent(Event event)
    {
        // Process event and insert rows into database
        // Some event will throw a runtime exception
    }

Refer Spring Transcation

Upvotes: 5

Vaelyr
Vaelyr

Reputation: 3176

Have you tried rollbackFor value on your transaction method?

@Transactional(rollbackFor = YourException.class)
    public void processEvent(Event event)
    {
        // Process event and insert rows into database
        // Some event will throw a runtime exception
    }

Upvotes: 1

Related Questions