Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for R2DBC #121

Open
lukaszweg opened this issue Oct 6, 2020 · 11 comments
Open

Support for R2DBC #121

lukaszweg opened this issue Oct 6, 2020 · 11 comments
Labels
type: task A general task

Comments

@lukaszweg
Copy link

Hello is there way to use zonky with R2DBC? I tried many things, but nothing help at all. Maybe it is possible to set port? Because as I see hostname, password and username name are always same and problem is with port which changing all time, not allowing to set url in properties

@tomix26
Copy link
Collaborator

tomix26 commented Oct 7, 2020

Hey, thanks for the question. This library is strongly based on JDBC, so note it needs to be present on the classpath, at least in the test scope. Otherwise, there should be no other problem and it should be enough to create an adapter between JDBC and R2DBC projects. Check the example below.

The only thing to keep in mind is that the injected data source is actually an AOP proxy and the target database may change over time. This happens when the database is refreshed via @FlywayTest annotation. So it is necessary to detect it and create a new connection factory if that happens.

public class EmbeddedPostgresConnectionFactory implements ConnectionFactory {

    private final DataSource dataSource; // an AOP proxy with a changing target database

    private volatile BaseDataSource config; // the last instance of the target database
    private volatile PostgresqlConnectionFactory factory;

    public EmbeddedPostgresConnectionFactory(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    private PostgresqlConnectionFactory connectionFactory() {
        BaseDataSource freshConfig;
        try {
            freshConfig = dataSource.unwrap(BaseDataSource.class);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        if (factory == null || config != freshConfig) { // checks if the target database has changed or not
            config = freshConfig;
            factory = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
                    .host(freshConfig.getServerName())
                    .port(freshConfig.getPortNumber())
                    .username(freshConfig.getUser())
                    .password(freshConfig.getPassword())
                    .database(freshConfig.getDatabaseName())
                    .build());
        }

        return factory;
    }

    @Override
    public Publisher<io.r2dbc.postgresql.api.PostgresqlConnection> create() {
        return connectionFactory().create();
    }

    @Override
    public ConnectionFactoryMetadata getMetadata() {
        return connectionFactory().getMetadata();
    }
}
@RunWith(SpringRunner.class)
@AutoConfigureEmbeddedDatabase(beanName = "dataSource")
public class EmptyDatabaseIntegrationTest {
    
    @Configuration
    static class Config {
        
        @Bean
        public ConnectionFactory connectionFactory(DataSource dataSource) {
            return new EmbeddedPostgresConnectionFactory(dataSource);
        }
    }

    @Autowired
    private ConnectionFactory connectionFactory;

    @Test
    public void testMethod() {
        // some testing code...
        Mono.from(connectionFactory.create())
                .flatMapMany(connection -> Flux.from(connection
                        .createBatch()
                        .add("select * from player")
                        .add("select * from player")
                        .execute()))
                .as(StepVerifier::create)
                .expectNextCount(2)
                .verifyComplete();
    }
}

@tomix26
Copy link
Collaborator

tomix26 commented Oct 7, 2020

I will try to implement this functionality to one of the next releases.

@tomix26 tomix26 added the type: task A general task label Oct 7, 2020
@tomix26
Copy link
Collaborator

tomix26 commented Oct 7, 2020

Let me know if the solution described above works.

@tomix26 tomix26 added the status: waiting-for-feedback We need additional information before we can continue label Oct 7, 2020
@bfrggit
Copy link

bfrggit commented Mar 24, 2021

@tomix26 I tested your posted version of EmbeddedPostgresConnectionFactory and it works for me. Only a nit that freshConfig.getServerName() and freshConfig.getPortNumber() are deprecated now. Also my IDE warns that the two overriding methods do not have @NonNullApi when the overridden methods are.

@tomix26
Copy link
Collaborator

tomix26 commented Mar 26, 2021

@bfrggit Ok, thanks for the info 👍

@tomix26 tomix26 removed the status: waiting-for-feedback We need additional information before we can continue label Mar 26, 2021
@SalyczeQ
Copy link

Hello,
is this still planned to be implemented in new releases? :)

@tomix26
Copy link
Collaborator

tomix26 commented Nov 14, 2021

Hi, maybe sometime in the future. Now it doesn't have enough priority for me. However, you can still use the example above, or prepare a pull request on your own. Any help is welcome 😉

@neeru-bhaskar
Copy link

neeru-bhaskar commented Oct 31, 2022

@tomix26 Can you post the complete code. I am trying to test my r2dbc application using zonky embedded postgres. I could not get the above example work for me.

@tomix26
Copy link
Collaborator

tomix26 commented Nov 12, 2022

@neeru-bhaskar I'm sorry, but R2DBC is not yet supported. I did my best in the example above.

@d-wire
Copy link

d-wire commented Jul 31, 2023

Where is the class BaseDataSource in your example coming from? Trying to figure out which dependency I'm missing since I don't seem to be able to import that class.

@tomix26
Copy link
Collaborator

tomix26 commented Aug 3, 2023

Where is the class BaseDataSource in your example coming from? Trying to figure out which dependency I'm missing since I don't seem to be able to import that class.

BaseDataSource is a class of the postgres jdbc driver. As I mentioned at the beginning of this conversation:

This library is strongly based on JDBC, so note it needs to be present on the classpath, at least in the test scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: task A general task
Projects
None yet
Development

No branches or pull requests

6 participants