Realm-java: [Kotlin] annotation processor throws if the realm plugin is applied after kotlin

Created on 17 Oct 2017  Â·  19Comments  Â·  Source: realm/realm-java

Goal

Use a RealmList in Kotlin

Expected Results

I'm able to use a (Kotlin) String in a RealmList

Actual Results

Realm can't use Kotlin strings, saying:

Error:Element type of RealmList must be a class implementing 'RealmModel' or one of the 'java.lang.String', 'byte[]', 'java.lang.Boolean', 'java.lang.Long', 'java.lang.Integer', 'java.lang.Short', 'java.lang.Byte', 'java.lang.Double', 'java.lang.Float', 'java.util.Date'.

Also, using java.lang.String in a Kotlin file doesn't fix the error.

Steps & Code to Reproduce

  1. Setup new project
  2. Create realm object
  3. Add var list : RealmList<String> = RealmList()

See the error shown above

Version of Realm and tooling

Realm version(s): 4.0.0

Realm sync feature enabled: no

Android Studio version: 3.0.0RC1

Which Android version and device: n/a

T-Doc

Most helpful comment

@Marcel50506

The problem is caused by the order of applied plugins:

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'realm-android'

Change it to:

apply plugin: 'realm-android'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

Will solve the issue.

But it feels something is not right there since i got:

app: Original kapt is deprecated. Please add "apply plugin: 'kotlin-kapt'" to your build.gradle.
Processor path was modified by kapt. Previous value = configuration ':app:debugAnnotationProcessorClasspath'
Destination for generated sources was modified by kapt. Previous value = /tmp/5434/MyApplication3/app/build/generated/source/apt/debug
Note: Processing class SimpleObject
error: Element type of RealmList must be a class implementing 'RealmModel' or one of the 'java.lang.String', 'byte[]', 'java.lang.Boolean', 'java.lang.Long', 'java.lang.Integer', 'java.lang.Short', 'java.lang.Byte', 'java.lang.Double', 'java.lang.Float', 'java.util.Date'.
1 error

when the problem happens

I guess something needs to be updated in the realm plugin.

All 19 comments

Have you tried

@field:[Required]
var list : RealmList<String> = RealmList()

@Zhuinden

This doesn't make a difference

I don't know how we managed to miss this, and unfortunately solving it is not exactly easy. The problem is that the generic types are erased in the Java code from Kotlin (as javac strips them), so it looks like this:

// Kotlin
var list: RealmList<String> = RealmList();

// Java 
public RealmList list = new RealmList();

Which makes the annotation processor thinks the type is <Object> which is not supported.
The type information is encoded in Kotlins @Metadata annotation which unfortunately is very hidden.

The easiest approach would be to not throw an error in that case. It will get caught at runtime anyway, but throwing at compile time is much nicer.

For a quick fix, we should probably just ignore this check for now.

Actually, I might have been a bit to quick there (test before speaking next time 🙄 ) . This appears to work in a sample project, so not entirely sure why it doesn't work for you. Can you post your entire model class?

Also, what version of kapt are you using and how are you applying it?

Model class (SimpleObject.kt):

package com.example.myapplication

import io.realm.RealmList
import io.realm.RealmObject

open class SimpleObject : RealmObject() {
    var list : RealmList<String> = RealmList()
}

Compile time error:

Error:Element type of RealmList must be a class implementing 'RealmModel' or one of the 'java.lang.String', 'byte[]', 'java.lang.Boolean', 'java.lang.Long', 'java.lang.Integer', 'java.lang.Short', 'java.lang.Byte', 'java.lang.Double', 'java.lang.Float', 'java.util.Date'.
Error:org.gradle.api.internal.tasks.compile.CompilationFailedException: Compilation failed; see the compiler error output for details.

This compiles fine for me. Odd. Have you tried cleaning your project?

I've tried cleaning the project. To summarize my steps:

I was working on an older Kotlin project (with Realm 3.7.2 in Android Studio 3.0RC1), which I wanted to upgrade. I upgraded to 4.0.0, and everything went fine. When I tried to create a RealmList<String> the above mentioned compile time error occured.

Then I created a new Kotlin project in Android Studio (3.0RC1), included Realm-java 4.0.0 to the project build gradle and appied it in the app build gradle. Then created a new Kotlin class with the RealmList<String> variable and tried to compile, again resulting in the error.

As said, also cleaned the project, but the same problem occured.

I am away from my computer until thursday, so I can't check myself, but could it be that the Kotlin version makes a difference?

@Marcel50506 what is your kotlin version?
Also, i met some issues with Android Studio 3.0RC1. sometimes it doesn't refresh the dependencies after you change the realm to a different version. What i do to solve that:

  1. close all Android Studio instances
  2. ./gradlew --stop
  3. then try again

You problem looks very much like the Android Studio is still trying to use the 3.7.2 's annotation processor.

We got the same issue while using kapt3 ("apply "kotlin-kapt"), and it's gone using kapt1 (which should be deprecated)
Forget what I said, i messed up, the issue we got was when we tried with List instead of RealmList

@beeender The Kotlin version I use is 1.1.51.

In the sample project, I never used 3.7.2, and immediately used 4.0.0, so that can't be it.

Followed your instructions, stopping all Android Studio instances and stopping gradle, but after building it resulted in the same error still.

@Marcel50506 can you share you sample project somewhere? you can send it to [email protected] if you want to share it privately.

I've send a zipped version of the project.

Are you able to reproduce the issue on your system?

@Marcel50506

The problem is caused by the order of applied plugins:

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'realm-android'

Change it to:

apply plugin: 'realm-android'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

Will solve the issue.

But it feels something is not right there since i got:

app: Original kapt is deprecated. Please add "apply plugin: 'kotlin-kapt'" to your build.gradle.
Processor path was modified by kapt. Previous value = configuration ':app:debugAnnotationProcessorClasspath'
Destination for generated sources was modified by kapt. Previous value = /tmp/5434/MyApplication3/app/build/generated/source/apt/debug
Note: Processing class SimpleObject
error: Element type of RealmList must be a class implementing 'RealmModel' or one of the 'java.lang.String', 'byte[]', 'java.lang.Boolean', 'java.lang.Long', 'java.lang.Integer', 'java.lang.Short', 'java.lang.Byte', 'java.lang.Double', 'java.lang.Float', 'java.util.Date'.
1 error

when the problem happens

I guess something needs to be updated in the realm plugin.

Huh? realm-android always had to be applied last so that kapt could be Properly applied.

Changing the order of the plugins solves this problem, but it gives me another issue. This time it's runtime:

java.lang.IllegalArgumentException: User is not part of the schema for this Realm

It looks a lot like this issue: https://github.com/realm/realm-java/issues/5261

In some strange way, when returning the order of the plugins (and delete all RealmLists), and after cleaning the project, the not part of the schema error remains.

using classpath "io.realm:realm-gradle-plugin:4.0.0"

and plugins

apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'realm-android'

And following class

open class Person (
        var name: String? = null,
        var age: Int = 0,
        var birthDate: Date? = null,
        var parents: RealmList<Person>? = null,
        @field:LinkingObjects("parents") val childOf: RealmResults<Person>? = null,
        var phoneNumbers: RealmList<String>? = null
): RealmObject()

My code compiles just fine with Kotlin? :confused:

hmmm
apply plugin: 'kotlin-kapt' is important here.

otherwise it will report
app: Original kapt is deprecated. Please add "apply plugin: 'kotlin-kapt'" to your build.gradle. P
So below should work:

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'realm-android'

@beeender That was the case in the original version, when RealmList didn't work. Moving the realm plugin to the top fixed that, so moving it back to the bottom un-fixes it, right?

@Marcel50506 You also need apply plugin: 'kotlin-kapt' before apply plugin: 'realm-android' which was not in the build.gradle of the project you shared to me.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yuwu picture yuwu  Â·  3Comments

David-Kuper picture David-Kuper  Â·  3Comments

AAChartModel picture AAChartModel  Â·  3Comments

gpulido picture gpulido  Â·  3Comments

jjorian picture jjorian  Â·  3Comments