Search code examples
javaspringhibernatetransactionalatomic

Unable to rollback a transaction on a checked exception


The following service fails to rollback persisting the Foo object if an IllegalStateException is thrown although I have marked MyServiceImpl as @Transactional(rollbackFor = IllegalStateException.class). I have also tried to mark the upload method as @Transactional(rollbackFor = IllegalStateException.class), still the problem persists and my Database state would be inconsistent if an IllegalStateException would occur :

@Service
@Transactional
public class MyServiceImpl implements IMyService{
    @Autowired
    private IFooService fooService;
    @Autowired
    private IBarService barService;

    @Override
    @Transactional(rollbackFor = IllegalStateException.class, propagation = Propagation.REQUIRED)
    public void upload(Foo foo, Bar bar) throws IllegalStateException{
       try{
        fooService.addFoo(foo);//foo object is persisted in the DB whether the upload call would succeed or fail (i.e. throws an IllegalStateException)
        if(!check(bar))
            throw new IllegalStateException("The object bar is not valid");
        barService.addBar();
      } catch(Exception e){
           e.printStackTrace();
      }
    }

    //This method simply validates the input Bar object
    private boolean check(Bar bar){
        //source code omitted       
    }   
}

@Service
@Transactional
public class FooServiceImpl implements IFooService{
    @Autowired
    private IFooDao fooDao; 

    @Override
    @Transactional(propagation = Propagation.REQUIRED) 
    public void addFoo(final Foo foo){
        fooDao.addFoo(foo);
    }   
}

@Service
@Transactional
public class BarServiceImpl implements IBarService{
    @Autowired
    private IBarDao barDao;

    @Override
    @Transactional(propagation = Propagation.REQUIRED) 
    public void addBar(final Bar bar){
        barDao.addBar(bar);
    }
}

public class Foo implements Serializable{
    private int id;
    //source code omitted
}

public class Bar implements Serializable{
    private int id;
    private Foo foo;
    //source code omitted
}

My DataSource config :

@Bean(name="dataSource")
public ComboPooledDataSource getDataSource() throws PropertyVetoException{
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setDriverClass(env.getProperty("db.driverClass"));
    dataSource.setJdbcUrl(env.getProperty("db.jdbcUrl"));
    dataSource.setUser(env.getProperty("db.user"));
    dataSource.setPassword(env.getProperty("db.password"));
    dataSource.setMaxPoolSize(50);
    dataSource.setMinPoolSize(5);
    dataSource.setMaxConnectionAge(1800);
    dataSource.setMaxIdleTime(1800);        
    dataSource.setAutoCommitOnClose(false);
    dataSource.setInitialPoolSize(5);       
    return dataSource;
}

How can I solve this please?

UPDATE : Source code updated and try/catch clause added.


Solution

  • It took me a while to spot the reason why the rollback fails. Thanks to ben75's answer. In fact, the source code I provided was not really complete. I forgot to add the try/catch clause within the upload method. This is what did really prevent the transaction from being rollbacked although the IllegalStateException is thrown. In addition to that, I don't need to specify the propagation level since it is REQUIRED by default.