0

I try to use h2 with r2dbc using the docker container oscarfonts/h2. By default when using this container, we have to use tcp protocol,

When I try to use it with r2dbc. I get the clear following error message :

Retrying to get database connection due class java.lang.IllegalArgumentException: protocol option tcp is unsupported (file, mem)

The doc r2dbc h2 says it should work with the tcp protocol. Does it?

Using spring boot 2.3.0.RELEASE and r2dbc version accordingly.

Xavier Bouclet
  • 922
  • 2
  • 10
  • 23

3 Answers3

0

R2DBC H2 is a tiny wrapper around the H2 database. This means that the entire infrastructure uses the same implementation of H2 as JDBC does which is all blocking.

Therefore you should not use H2 via TCP when using R2DBC but rather use a different database (MySQL, MariaDB, Postgres, SQL Server) with a proper non-blocking I/O implementation.

mp911de
  • 17,546
  • 2
  • 55
  • 95
  • I would like that but I do use another DB SQL : Server and H2 is for testing purpose only. I would have prefer to use test container but some trouble with our ci and the official mssql docker container prevent me to do that. So I tried to use testcontainer with h2 in the ci and with mssql localy. – Xavier Bouclet Jun 04 '20 at 01:11
  • May be, it can help: https://github.com/spring-projects/spring-data-r2dbc/issues/269 – GtdDev Jul 09 '20 at 23:10
0

No, it's not possible.

If you will use something like spring.r2dbc.url=r2dbc:h2:tcp://... You will get IllegalArgumentException: protocol option tcp is unsupported (file, mem)

Use either file or mem

Sources:

enter image description here

as u can see there are builder.file and builder.inMemory usagesavailable only, but not builder.tcp:

enter image description here

Maksim Kostromin
  • 3,273
  • 1
  • 32
  • 30
-1

Just been banging my head to the wall with this and wanted to share the conclussion:

dependencies being used:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.2</version>
    <relativePath />
</parent>

<dependencies>
    <dependency>
        <groupId>io.r2dbc</groupId>
        <artifactId>r2dbc-h2</artifactId>
    </dependency>

    <!-- and something to provide spring beans -->

</dependencies>

application.properties

spring.r2dbc.url=r2dbc:h2:tcp://localhost:9090/mem:mydb
# also works for file-based h2db 
# spring.r2dbc.url=r2dbc:h2:tcp://localhost:9090/file./oreport
spring.r2dbc.username=sa
spring.r2dbc.password=

This bean will create the H2ConnectionFactory instance you need.

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import io.r2dbc.h2.H2ConnectionConfiguration;
import io.r2dbc.h2.H2ConnectionFactory;

@ConditionalOnProperty("spring.r2dbc.url")
@ConditionalOnExpression("#{'${spring.r2dbc.url}'.substring(0,12) matches 'r2dbc:h2:tcp'}")
@Configuration
public class H2Config {

    /**
     * As of 2021-08-06 the latest r2dbc-h2 version is 0.8.4.RELEASE and, even when
     * tcp connections where enabled, there's still no auto-configuration. This Bean
     * helps that.
     * 
     * @see <a href="https://github.com/r2dbc/r2dbc-h2/issues/86">r2dbc-h2
     *      Issue#86</a>
     */
    @Bean
    public H2ConnectionFactory h2ConnectionFactory(@Value("${spring.r2dbc.url}") String url,
            @Value("${spring.r2dbc.username}") String username, @Value("${spring.r2dbc.password}") String password) {
        url = url.substring("r2dbc:h2:".length());
        return new H2ConnectionFactory(
                H2ConnectionConfiguration.builder().url(url).username(username).password(password).build());
    }
}

Best regards

Fradantim

Fradantim
  • 31
  • 1
  • 6