Skip to content

Support for @Transactional and R2dbcTransactionManager in spring-test #31193

Closed as not planned
@AliAkbarMoeini

Description

@AliAkbarMoeini

Affects: 5.3.29

I have a Spring project that uses Spring Data R2DBC with Oracle driver, I created the required ConnectionFactory and ReactiveTransactionManager and I use @Transactional in the required methods. Spring correctly uses ReactiveTransactionManager instead of PlatformTransactionManager to manage these Spring-managed transactions and there is no problem. But it is different in tests, as we know if @Transactional is used in test cases, it is considered as Test-managed transactions and will be automatically rolled back after completion of the test.
although ConnectionFactory and ReactiveTransactionManager are configured correctly, Spring tries to use PlatformTransactionManager instead of ReactiveTransactionManager for Test-managed transactions. As a result, the following error is given:

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'myReactiveTransactionManager' is expected to be of type 'org.springframework.transaction.PlatformTransactionManager' but was actually of type 'org.springframework.r2dbc.connection.R2dbcTransactionManager'

After this issue, I searched a little in the spring-test code, and by examining the org.springframework.test.context.transaction.TransactionalTestExecutionListener class, I came to the conclusion that Spring only supports PlatformTransactionManager in the test environment.

Is my conclusion correct, and we should wait for the support of ReactiveTransactionManager in new versions of spring-test, or is there a problem with my configuration and usage?

This is similar to my ConnectionFactory and ReactiveTransactionManager configuration in the code environment:

@Configuration
@EnableR2dbcRepositories
public class OracleR2dbcConfig extends AbstractR2dbcConfiguration {

	public static final String MY_R2DBC_TRANSACTION_MANAGER = "myReactiveTransactionManager";
	public static final String MY_R2DBC_CONNECTION_FACTORY = "myReactiveConnectionFactory";

	@Bean(name = MY_R2DBC_CONNECTION_FACTORY)
	@Override
	public @NonNull ConnectionFactory connectionFactory() {
		ConnectionFactoryOptions options = ConnectionFactoryOptions.builder()
				.option(HOST, "localhost")
				.option(PORT, 1521)
				.option(USER, "user")
				.option(PASSWORD, "password")
				.build();
		return new OracleConnectionFactoryProviderImpl().create(options);
	}

	@Bean(name = MY_R2DBC_TRANSACTION_MANAGER)
	public ReactiveTransactionManager myTransactionManager(@Qualifier(MY_R2DBC_CONNECTION_FACTORY) ConnectionFactory connectionFactory) {
		return new R2dbcTransactionManager(connectionFactory);
	}

}

and this is ConnectionFactory and ReactiveTransactionManager configuration in the test environment:

@Configuration
@EnableR2dbcRepositories
public class H2R2dbcConfig extends AbstractR2dbcConfiguration {

	public static final String MY_R2DBC_TRANSACTION_MANAGER = "myReactiveTransactionManager";
	public static final String MY_R2DBC_CONNECTION_FACTORY = "myReactiveConnectionFactory";

	@Bean(name = MY_R2DBC_CONNECTION_FACTORY)
	@Override
	public @NonNull ConnectionFactory connectionFactory() {
		return ConnectionFactories.get("r2dbc:h2:mem:///testdb?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
	}


	@Bean(name = MY_R2DBC_TRANSACTION_MANAGER)
	public ReactiveTransactionManager myTransactionManager(@Qualifier(MY_R2DBC_CONNECTION_FACTORY) ConnectionFactory connectionFactory) {
		return new R2dbcTransactionManager(connectionFactory);
	}

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: dataIssues in data modules (jdbc, orm, oxm, tx)in: testIssues in the test modulestatus: duplicateA duplicate of another issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions