0

I use spring 4.3.9.RELEASE

Some configs and code:

@Configuration
@EnableTransactionManagement
public class PersistenceContext {

    @Autowired
    private DbConfiguration dbConfiguration;

    @Bean(destroyMethod = "close")
    public DataSource dataSource() {

        final BoneCPDataSource dataSource = new BoneCPDataSource();

        dataSource.setDriverClass(dbConfiguration.getDriverClassName());
        dataSource.setJdbcUrl(dbConfiguration.getUrl());
        dataSource.setUsername(dbConfiguration.getUsername());
        dataSource.setPassword(dbConfiguration.getPassword());
        dataSource.setIdleConnectionTestPeriodInMinutes(dbConfiguration.getIdleConnectionTestPeriod());
        dataSource.setIdleMaxAgeInMinutes(dbConfiguration.getIdleMaxAgeInMinutes());
        dataSource.setMaxConnectionsPerPartition(dbConfiguration.getMaxConnectionsPerPartition());
        dataSource.setMinConnectionsPerPartition(dbConfiguration.getMinConnectionsPerPartition());
        dataSource.setPartitionCount(dbConfiguration.getPartitionCount());
        dataSource.setAcquireIncrement(dbConfiguration.getAcquireIncrement());
        dataSource.setStatementsCacheSize(dbConfiguration.getStatementsCacheSize());

        return dataSource;
    }

    @Bean(name = "txManager")
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

servlet:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

    <context:annotation-config/>

    <context:component-scan base-package="ru.org.*"/>

    <tx:annotation-driven transaction-manager="txManager" />

    <mvc:annotation-driven />
</beans>

WebConfig:

    @Configuration
    @EnableScheduling
    @EnableWebMvc
    @ComponentScan({"ru.org.*"})
    @EnableTransactionManagement
    public class WebConfig extends WebMvcConfigurerAdapter {


        @Bean
        public MainHandler mainHandler() {
            return new MainHandler();
        }
    }

handler:

public class MainHandler extends AbstractUrlHandlerMapping {

    @Autowired
    private DataSource dataSource;

    protected Object getHandlerInternal(final HttpServletRequest request) throws Exception {
        transactionalTest();
    }

    @Transactional(transactionManager = "txManager")
    private void transactionalTest() {

        final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.execute("INSERT INTO marks(score) VALUES (1);");
        jdbcTemplate.execute("IN3ERT INTO marks(score) VALUES (1);");
    }
}

It throws an exception but no rollback happened.

Also I tried to use rollbackFor-param and throws exactly that exception.

Any ideas?

Artem
  • 505
  • 5
  • 22
  • 2
    That transactionalTest method should be in your service class. That's the class with `@Service` annotation – Perry Jul 24 '17 at 08:59
  • how have you annotated your `MainHandler ` class? – Sergii Getman Jul 24 '17 at 09:06
  • 1
    `@Transactional` does not work on private methods https://stackoverflow.com/questions/4396284/does-spring-transactional-attribute-work-on-a-private-method – alfcope Jul 24 '17 at 09:14
  • I've add @Service annotation and make transactionalTest method public, but it still doesn't work – Artem Jul 24 '17 at 09:18
  • 1
    Spring AOP is proxy based (by default) and as such only calls INTO the object pass through the proxy and will have AOP added. Internal method calls, regardless of the modifier of the method, don't pass through the proxy and won't have AOP applied. Which is also explained in the second answer of https://stackoverflow.com/questions/4396284/does-spring-transactional-attribute-work-on-a-private-method which @alfcope linked you to. – M. Deinum Jul 24 '17 at 10:31

1 Answers1

1

There are two major rules of @Transaction annotation you must keep in mind

  1. @Transaction will work if the annotated method is not declared in the same class that invokes it (True for default Spring Proxy AOP).
  2. @Transaction will work if annotated on a public method. It will always be ignored if the method is private, protected or package-visible.

So what you should do

Delcare a public transactionalTest() method in a @Service annotated class and then call it in MainHandler class

Perry
  • 312
  • 1
  • 4
  • 12