Search code examples
androidkotlinandroid-roomdagger-hilttypeconverter

Room TypeConverter with constructor error: java.lang.IllegalArgumentException


I have been struggling with this error for a long time. I have seen similar topics while no answer has brought the result. Following this tutorial https://www.section.io/engineering-education/storing-custom-data-types-with-custom-typeconverter-in-room-database/.

Error: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.cointracker/com.example.cointracker.MainActivity}: java.lang.IllegalArgumentException: A required type converter (class com.example.cointracker.data.util.converters.Converters) for com.example.cointracker.data.db.CoinDAO is missing in the database configuration.

My TypeConverter is:

@ProvidedTypeConverter
class Converters(
    private val jsonParser: JsonParser
) {
    @TypeConverter
    fun toQuoteJson(quote: Quote): String{
        return jsonParser.toJson(
            quote,
            object : TypeToken<Quote>(){}.type
        ) ?: "[]"
    }
    @TypeConverter
    fun fromQuoteJson(json: String): Quote{
        return jsonParser.fromJson<Quote>(
            json,
            object: TypeToken<Quote>(){}.type
        ) ?: Quote(null)
    }

    @TypeConverter
    fun toStringJson(meaning: List<String?>?) : String {
        return jsonParser.toJson(
            meaning,
            object : TypeToken<List<String>>(){}.type
        ) ?: "[]"
    }
    @TypeConverter
    fun fromStringsJson(json: String): List<String>{
        return jsonParser.fromJson<List<String>>(
            json,
            object: TypeToken<List<String>>(){}.type
        ) ?: emptyList()
    }
}

Class which is extending simple interface JsonParser:

class GsonParser(
    private val gson: Gson
): JsonParser {
    override fun <T> fromJson(json: String, type: Type): T? {
        return gson.fromJson(json, type)
    }

    override fun <T> toJson(obj: T, type: Type): String? {
        return gson.toJson(obj, type)
    }
}

Database:

@Database(
    entities = [Coin::class],
    version = 2,
    exportSchema = false
)
@TypeConverters(Converters::class)
abstract class CoinDatabase : RoomDatabase() {

    abstract fun getCoinDAO(): CoinDAO

}

Dependencies with Hilt:

@Module
@InstallIn(SingletonComponent::class)
class JsonModule {

    @Singleton
    @Provides
    fun provideGson(): Gson {
        return GsonBuilder().create()
    }

    @Singleton
    @Provides
    fun provideJsonParser(gson: Gson): JsonParser {
        return GsonParser(gson)
    }

}

and for database:

@Module
@InstallIn(SingletonComponent::class)
class DatabaseModule {

    @Singleton
    @Provides
    fun provideCoinsDatabase(app: Application): CoinDatabase {
        return Room.databaseBuilder(app,CoinDatabase::class.java,"coins_db")
            .addTypeConverter(Converters::class)
            .build()
    }

    @Singleton
    @Provides
    fun provideCoinsDao(coinDatabase: CoinDatabase): CoinDAO{
        return coinDatabase.getCoinDAO()
    }

}

Does anyone know how to solve this error?


Solution

  • You should initialise & add the Converters class in the addTypeConverter method when building the Room database. Don't simply pass the Converters::class.

    It should be:

    val converterFactory = Converters(jsonParserObject)
    
    Room.databaseBuilder(app, CoinDatabase::class.java,"coins_db")
        .addTypeConverter(converterFactory)
        .build()
    

    Source: this & this.