astonbitecode / j4rs

Java for Rust
Apache License 2.0
637 stars 36 forks source link

Pass enum into function #32

Closed sstubbs closed 3 years ago

sstubbs commented 3 years ago

Hi,

This is an amazing project. I am trying to dynamically change sql dialects using jooq. The following java code works:

var sql = "CREATE TABLE IF NOT EXISTS location_code (id UUID, country_code VARCHAR(2), code VARCHAR(20), place_name VARCHAR(180), admin_name1 VARCHAR(100), admin_code1 VARCHAR(20), admin_name2 VARCHAR(100), admin_code2 VARCHAR(20), admin_name3 VARCHAR(100), admin_code3 VARCHAR(20), latitude NUMERIC, longitude NUMERIC, accuracy SMALLINT, PRIMARY KEY (id));";

Configuration configuration = new DefaultConfiguration().set(SQLDialect.POSTGRES);

var query = 
DSL.using(configuration)
.parser()
.parse(sql);

query.attach(configuration.set(SQLDialect.MYSQL));

log.info(query.toString());

using j4rs I have the following working:

    let sql = "CREATE TABLE IF NOT EXISTS location_code (id UUID, country_code VARCHAR(2), code VARCHAR(20), place_name VARCHAR(180), admin_name1 VARCHAR(100), admin_code1 VARCHAR(20), admin_name2 VARCHAR(100), admin_code2 VARCHAR(20), admin_name3 VARCHAR(100), admin_code3 VARCHAR(20), latitude NUMERIC, longitude NUMERIC, accuracy SMALLINT, PRIMARY KEY (id));";

    let jvm = JvmBuilder::new().build()?;

    let rdbc_artifact = MavenArtifact::from("io.r2dbc:r2dbc-spi:0.9.0.M2");
    let steams_artifact = MavenArtifact::from("org.reactivestreams:reactive-streams:1.0.0");
    let jooq_artifact = MavenArtifact::from("org.jooq:jooq:3.15.1");
    jvm.deploy_artifact(&rdbc_artifact)?;
    jvm.deploy_artifact(&steams_artifact)?;
    jvm.deploy_artifact(&jooq_artifact)?;

    let postgres_dialect = jvm
        .chain(&jvm.create_instance("org.jooq.SQLDialect", &Vec::new())?)?
        .invoke("valueOf", &[InvocationArg::try_from("POSTGRES")?])?
        .collect();

    let configuration_instance = jvm
        .chain(&jvm.cast(
            &jvm.create_instance("org.jooq.impl.DefaultConfiguration", &Vec::new())?,
            "org.jooq.Configuration",
        )?)?
        // .invoke("set", &[InvocationArg::from(postgres_dialect)])?
        .collect();

    let converted_sql = jvm
        .chain(&jvm.create_instance("org.jooq.impl.DSL", &Vec::new())?)?
        .invoke("using", &[InvocationArg::try_from(configuration_instance)?])?
        .invoke("parser", &[])?
        .invoke("parse", &[InvocationArg::try_from(sql)?])?
        .collect();

    let converted_sql_string: String =
        jvm.to_rust(jvm.invoke(&jvm.cast(&converted_sql, "java.lang.Object")?, "toString", &[])?)?;

    print!("{:?}", converted_sql_string);

but when I uncomment the line:

// .invoke("set", &[InvocationArg::from(postgres_dialect)])?

I get the following error:

Exception in thread "main" org.astonbitecode.j4rs.errors.InvocationException: While invoking method set of Class org.jooq.Configuration
        at org.astonbitecode.j4rs.api.invocation.JsonInvocationImpl.invoke(JsonInvocationImpl.java:73)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.astonbitecode.j4rs.api.invocation.JsonInvocationImpl.invokeMethod(JsonInvocationImpl.java:179)
        at org.astonbitecode.j4rs.api.invocation.JsonInvocationImpl.invoke(JsonInvocationImpl.java:70)
Error: An Exception was thrown by Java... Please check the logs or the console.

I have tried various ways passing this enum value into the set function but am not having any luck. Some help with this would be greatly appreciated.

astonbitecode commented 3 years ago

It is not obvious, but you may use the enums like accessiing a static field of a class:

let dialect_enum_instance = jvm.static_class("org.jooq.SQLDialect")?;

let postgres_dialect = jvm.field(&dialect_enum, "POSTGRES")?;

This should be added in the README as well I guess...

astonbitecode commented 3 years ago

Documentation added. I guess this can be closed.

Thank you for reporting.