Closed sharawanan closed 6 months ago
From the exception, it seems you are trying to insert an instance that is not a RealmModel
but a LinkedTreeMap
.
Could you check that you are deserializing to the correct object type?
The same code works on Retrofit 2.9.0 and AGP 7.4.1
@sharawanan Can you elaborate a bit on how your model looks like?
open class UserRoleMenus : RealmObject() {
@PrimaryKey
@Index
var id = 0
var name: String? = null
var parent: String? = null
var actions: UserRoleMenuActions? = null
var components: RealmList<UserRoleComponents>? = null
}
open class UserRoleMenuActions : RealmObject() {
var show: Boolean = false
var view: Boolean = false
var add: Boolean = false
var edit: Boolean = false
var delete: Boolean = false
}
open class UserRoleComponents : RealmObject() {
var name: String? = null
var show: Boolean = false
}
private var userRoleMenusList: List<UserRoleMenus>? = emptyList()
val asyncTracker: SafeAsyncTask<Boolean> = object : SafeAsyncTask<Boolean>() {
@Throws(java.lang.Exception::class)
override fun call(): Boolean {
val response: Response<UserRoleWrapper?> =
serviceProvider.getService(getActivity).getUserRole(userId)!!.execute()
return if (response.isSuccessful && response.body() != null) {
if (response.body()!!.success != null && response.body()?.userRoleMenus?.size!! > 0) {
userRoleMenusList = response.body()!!.userRoleMenus
saveuserRoleMenu()
true
} else {
if (response.body() != null && response.body()!!.error != null) {
Toaster.showShort(getActivity, "" + response.body()!!.error)
}
false
}
} else false
}
@Throws(RuntimeException::class)
override fun onException(e: java.lang.Exception) {
e.printStackTrace()
if (e !is IOException) {
val cause = if (e.cause != null) e.cause else e
Toaster.showLong(getActivity, cause!!.message)
}
apiView.onException()
}
@Throws(Exception::class)
override fun onSuccess(resSuccess: Boolean?) {
if (resSuccess!!) {
apiView.onSuccess()
} else {
apiView.onException()
}
}
override fun onFinally() {
}
}
asyncTracker.execute()
fun saveuserRoleMenu()
{
Realm.getDefaultInstance().use { realmT ->
val results = realmT.where<UserRoleMenus>().findAll()
val results1 = realmT.where<UserRoleMenuActions>().findAll()
val results2 = realmT.where<UserRoleComponents>().findAll()
realmT.executeTransaction { results.deleteAllFromRealm() }
realmT.executeTransaction { results1.deleteAllFromRealm() }
realmT.executeTransaction { results2.deleteAllFromRealm() }
realmT.executeTransaction { realm: Realm ->
realm.insertOrUpdate(
userRoleMenusList
)
}
}
}
@sharawanan There is nothing in the model definition that catches the eye. From the stacktrace it seems like you are invoking the insertOrUpdate(Collection<? extends RealmModel>)
-variant of insertOrUpdate
so I assume your userRoleMenusList
is just a list of UserRoleMenus
. In that case it looks like our plugin might not have been applied.
Is this code in your main
source set or is it test/integration test code or are there some specials about your configuration?
Also just to be completely explicit and help troubleshooting, what is the exact type of userRoleMenusList
?
@rorbech I've updated full code
It is a bit difficult to hunt without the ability to debug, but there are a couple of concerns:
userRoleMenusList
is a global variable updated in an async task. Could you try to pass the value saveuserRoleMenu
as an argument, so that you are absolutely certain that it is the response of an immediate request that is passed. UserRoleWrapper
, so it is still not possible to reason about what is actually going onCould you debug and inspect that the userRoleMenusList
is in fact a non-null UserRoleMenus
-collection when you see the error?
It is not a Realm issue.
It is related to gson due to Type Erasure.
I have the same issue with my simple custom class, I am keeping my androidGradlePlugin 7.4.2
for now.
@sharawanan Have you been able to trace down what the root of this was? If not please share more details or a minimal project that shows the issue for us to try to debug it.
This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.
Same issue here with AGP 8.0.2. The issue gets resolved when downgrading to 7.4.2 with no code change.
In my case, I'm using a Room database with the item in List having it's own table. It's also a variable in a parent object, which deserializes correctly outside of this variable, which throws an error only on using it (not when converting it - therefore runtime only).
Here's my logic for parsing:
@TypeConverter fun toQuestionAnswerIOList(value: String): List<QuestionAnswerIO> { return gson.fromJson( value, TypeToken.getParameterized(List::class.java, QuestionAnswerIO::class.java).type ) }
(gson
is injected by Hilt)
and here's a definition for CollectionIO object:
@Entity(tableName = AppRoomDatabase.ROOM_COLLECTION_TABLE) data class CollectionIO(
val questions: MutableList<QuestionIO> = mutableListOf(),
@SerializedName("default_preference")
val defaultPreference: UserPromptPreferences = UserPromptPreferences(),
var name: String = "",
var description: String = "",
val icon: LargePathAsset? = null,
@SerializedName("date_created")
@ColumnInfo(name = "date_created")
var dateCreated: Date? = null,
@SerializedName("date_modified")
@ColumnInfo(name = "date_modified")
var dateModified: Date? = DateUtils.now.time,
@PrimaryKey
val uid: String = UUID.randomUUID().toString()
): Serializable {
/** Checks whether object contains any non-default data */
val isNotEmpty: Boolean
get() = dateCreated != null
|| name.isNotEmpty()
|| description.isNotEmpty()
|| questions.isNotEmpty()
override fun toString(): String {
return "{" +
"questions: $questions" +
"defaultPreference: $defaultPreference" +
"name: $name" +
"description: $description" +
"icon: $icon" +
"dateCreated: $dateCreated" +
"dateModified: $dateModified," +
"uid: $uid," +
"task: $tasks" +
"}"
}
}`
Add this line in proguard file
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keepattributes Signature
-keep class com.google.gson.reflect.TypeToken
-keep class * extends com.google.gson.reflect.TypeToken
-keep public class * implements java.lang.reflect.Type
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
gradle.properties
android.enableJetifier=true
android.useAndroidX=true
android.debug.obsoleteApi=true
org.gradle.configureondemand=true
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx6656M
org.gradle.warning.mode=all
kotlin.mpp.stability.nowarn=true
kotlin.mpp.androidSourceSetLayoutVersion=2
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
android.enableR8.fullMode=false
This seems to solve the issue. Thank you.
This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.
How frequently does the bug occur?
Always
Description
Using Retrofit 2.9.0 and AGP 8.0.1
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to io.realm.RealmModel at io.realm.DefaultRealmModuleMediator.insertOrUpdate(SourceFile:7121) at io.realm.Realm.insertOrUpdate(SourceFile:1367)
Stacktrace & log output
No response
Can you reproduce the bug?
Always
Reproduction Steps
No response
Version
10.15.1
What Atlas App Services are you using?
Local Database only
Are you using encryption?
No
Platform OS and version(s)
Android
Build environment
Android Studio version: ... Android Build Tools version: ... Gradle version: ...