objectbox-java icon indicating copy to clipboard operation
objectbox-java copied to clipboard

Support initialization magic (transformer) for plain Kotlin projects

Open thanhhai08sk opened this issue 6 years ago • 3 comments

Issue Basics

  • ObjectBox version (are using the latest version?): 1.5.0
  • Reproducibility: always

Reproducing the bug

Description

I want to extract a common module (all objectBox usage are here) from and Android app so that it can be used for TornatoFX app (Kotlin) as well. When I set up the module as an Android library module, the Android app run fine but when I try to remove all the Android related stuff, gradle build produces logs like this:

Warning: cursor transformer did not find entity class org.de_studio.diary.appcore.data.objectBox.TodoOB

When I run the app, I can't put entity with ToMany relation into the box. I can't attach to the box as well:

java.lang.IllegalArgumentException: io.reactivex.exceptions.OnErrorNotImplementedException: lateinit property places has not been initialized

Seems like only entities with relation include in the logs.

I read the document, tried many way but can't get rid of the warning. Below is my module's settings.gradle file. Did I miss anything?

Code

apply plugin: 'java-library'
apply plugin: 'application'
apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'net.ltgt.apt-idea'
apply plugin: 'io.objectbox'

kapt {
    arguments {
        arg("objectbox.debug", true)
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    api "io.reactivex.rxjava2:rxjava:2.1.1"
    api "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    api 'com.artemzin.rxjava:proguard-rules:1.2.10.0'
    api 'com.jakewharton.timber:timber:4.5.1'
    api 'com.jakewharton.rxrelay2:rxrelay:2.0.0'
    api 'com.gojuno.koptional:koptional:1.2.0'
    api 'com.gojuno.koptional:koptional-rxjava2-extensions:1.2.0'
    api 'net.danlew:android.joda:2.9.9.1'
    api 'com.google.code.gson:gson:2.8.0'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

    api "io.objectbox:objectbox-kotlin:$objectboxVersion"
    kapt "io.objectbox:objectbox-processor:$objectboxVersion"

    implementation "io.objectbox:objectbox-java:$objectboxVersion"
}

tasks.withType(JavaCompile) {
    options.compilerArgs += [ "-Aobjectbox.debug=true" ]
}

sourceSets {
    main {
        java {
            srcDir 'src/main/java'
            srcDir 'build/generated/source/kapt/main'
        }
    }
}

sourceCompatibility = "1.8"
targetCompatibility = "1.8"

Please let me know if you need more information. I will make a sample project if needed. Thanks!

thanhhai08sk avatar Apr 28 '18 11:04 thanhhai08sk

ObjectBox currently does not support "initialization magic" of relation fields/properties for plain-Kotlin projects, only for Android+Kotlin or plain-Java projects.

Try to initialize them yourself similar as described for local unit tests:

@Entity
public class Customer {
    // normally transformer would add init code, but need to manually for local unit tests
    ToOne<Order> lastOrder = new ToOne<>(this, Customer_.lastOrder);
    ToMany<Order> orders = new ToMany<>(this, Customer_.orders);
    // normally transformer would add field, but need to manually for local unit tests
    transient BoxStore __boxStore;
    ...
}

Or use an Android library module instead. -ut

greenrobot-team avatar Apr 30 '18 13:04 greenrobot-team

Didn't know about the magic before. Thanks for helping me out!

thanhhai08sk avatar May 01 '18 10:05 thanhhai08sk

To support this we need to know where to hook up our transformer tasks and which inputs/outputs to use. For Android Local Unit tests we do per variant:

testVariant.javaCompile.dependsOn(transformTask)
transformTask.mustRunAfter(variant.javaCompile)

and use variant.javaCompile.destinationDir and kotlinCompile.destinationDir as input/output.

We can get the Kotlin compile task at runtime by name, the naming scheme is promised in the docs. (Also here.)

Currently the Kotlin spec has no official docs on how the compiler works and how tasks are set up. This leaves inspecting the Kotlin plugin source.

We should support mixed Java/Kotlin as well as Kotlin only projects. IIRC the plugin sets up tasks differently if there is no Java plugin.

Update: Interesting part in Kotlin2JvmSourceSetProcessor#doTargetSpecificProcessing. Done for each source set (sourceSets?all{ }).

-ut

greenrobot-team avatar May 14 '18 09:05 greenrobot-team