How to properly connect my Kotlin android App with Mongodb Atlas Cluster?

Specs:
Android Studio (Native)
Kotlin
Java Driver 4.5.1

I tried to connect to my MongoDB Atlas Cluster from a native Kotlin Android App and none of the ways I tried worked. It works just fine in my desktop app in C# 6.0. Here is what I did:

1- I’m using java driver 4.5.1, because I cant build the app with mongodb driver versions higher than 4.5.1, it doesn’t work for me. If I try to implement it in build.gradle, for example: implementation 'org.mongodb:mongodb-driver-sync:4.7.2' when I try to build the app I receive this:

Invalid build configuration. Attempt to create a global synthetic for ‘Record desugaring’ without a global-synthetics consumer.

Stacktrace:
https://pastebin.com/Wnszgb3G

but versions less or equal to 4.5.1 builds fine.

2- After rolling back to version 4.5.1 a new problem occurs, if my connection string contains +srv in it, it throws me an IllegalArgumentException when trying to connect from the connection string, so I have to remove the +srv to “connect” to my Atlas Cluster.

3- If I remove the +srv it goes fine through all connection functions, but it doesn’t connect to anything. If I try to run any database CRUD operation, I’ll receive a TimeoutException after around 30 seconds because I’m actually not logged in to the MongoDB Atlas Cluster.

Here is my connection code:

class Database(client: MongoClient){

    companion object {

        fun connect(username : String?, password: String?) : Database?
        {
            val databaseObject: Database
            lateinit var mongoClient: MongoClient

            if (username == null || password == null)
                return null;

            try {
                val connString = ConnectionString("mongodb://$username:$password@gmmdb.gioj2hh.mongodb.net/?retryWrites=true&w=majority")
                val settings = MongoClientSettings.builder()
                    .applyConnectionString(connString)
                    .serverApi(
                        ServerApi.builder().version(ServerApiVersion.V1).build()
                    )
                    .build()

                mongoClient = MongoClients.create(settings)

                val database = mongoClient.getDatabase("GMMDB")
                val collection = database.getCollection("gmm_estoque")
                
               // after around 30 seconds this function is called it throws me a TimeoutException
               // probably because I'm not really connected to the cluster app
               collection.insertOne(Document()
                    .append("_id", ObjectId())
                    .append("Date", Date.from(Instant.now()))
                    .append("Code", 192)
                    .append("Name", "Asa de galinha")
                    .append("Marca", "Sadia")
                    .append("Disponibilidade", 1)
                )
            }
            catch (e: Exception) {
                Log.d("AppDebug", e.toString() + " - \n\n Message: " + e.message + " -\n\n StackTrace: " + e.stackTrace)
            }

            return Database(mongoClient)
        }
    }
}

gradle:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    namespace 'com.freto.barcodereader'
    compileSdk 33

    defaultConfig {
        applicationId "com.freto.barcodereader"
        minSdk 21
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    viewBinding {
        enabled = true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    implementation 'org.mongodb:mongodb-driver-sync:4.5.1'
    implementation 'androidx.core:core-ktx:1.9.0'
    implementation 'androidx.appcompat:appcompat:1.5.1'
    implementation 'com.google.android.material:material:1.7.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

I’ve tried many things, but nothing seems to work, so I need help getting it to work, thank you very much, I enjoy MongoDB very much!

1 Like

Hello @Raique_Familia :wave:,

Welcome to MongoDB Community.

Thank you for your question. Could you give a brief on your use case on what are you trying to build? Is there a reason you are using Java Driver instead of Realm Database?

You can connect Android App to Cluster via Realm App Id. Please refer to Quick Start section of the documentation.

Another way is to connect the app remotely to Atlas Cluster, as explained in Realm Bytes, but it comes with limitations.

I hope the provided information is helpful. Please dont hesitate to ask if you need more assistance.

Cheers, :performing_arts:
Henna

3 Likes

No, Henna it’s not been helpful. Why would you try to introduce Realm instead of telling us why it gives us errors like that? and no Henna there’s absolutely no reason to try to use Drivers cause we’re totally out of our minds and definitely needed somebody to question that part of our decision making process.
Using Kotlin Driver above 4.5.1 throws desugaring exception and even using 4.5.1 in context of the android project it throws no such method exception. When you try to debug the app you can clearly see that ConnectionString()'s giving us that kind of trouble and i don’t know why. But if you’re doing it somewhere like in main() function of kotlin language it works like a charm.
so what is it? is it some configuration that’s to be done in android side or is it something that Kotlin Driver needs to go farther to be able to support? cause both errors are the same on KMongo, too.

1 Like

Hi @henna.s, thank you for your answer. I am having the same problem as described by the OP.

My usecase is that I want to push data from my Android app to a MongoDB instance (not Atlas). In the end it is some kind of logging. Realm seams not fitting since it seems targeted towards Atlas and also I do not need local storage, but just wan to create new records in my database. How can I solve the problem?

mongodb - Kotlin error: "Invalid build configuration. Attempt to create a global synthetic for 'Record desugaring' without a global-synthetics consumer." - Stack Overflow suggests that the SDK is outdated. Do we need to wait for a new release of the SDK?

:v:

Hello @Johann_Hemmann ,

Welcome to MongoDB Community :wave: and thank you for your question.

Could you please share what driver SDK are you using and what version? Are you getting the same error as mentioned on Stack Overflow?

Invalid build configuration. Attempt to create a global synthetic for 'Record desugaring' without a global-synthetics consumer
Could you share a detailed stack trace of the error?

The Realm Kotlin team suggests if you are using Kotlin, then you may switch to MongoDB Kotlin drivers: https://www.mongodb.com/docs/drivers/kotlin-drivers/

I look forward to your response.

Cheers,
henna

Regarding the “record desugaring” error, I suspect the cause is the introduction of support for Java records in the 4.6 release. You might try excluding the bson-record-codec artifact, e.g.

        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver-sync</artifactId>
            <version>${driverVersion}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.mongodb</groupId>
                    <artifactId>bson-record-codec</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

If someone could test that and report back, it might help others on this thread.

Regarding the support for “mongodb+srv” connection string, I suspect the cause is the driver’s reliance on JNDI to look up SRV records, which last I checked is not supported in Android. But it’s not enough to remove the “+srv” from the connection string. You need a different connection string that contains the actual host names of the cluster, rather than the SRV host name, which is different. If you’re using MongoDB Atlas, there should be a way to get both an SRV and non-SRV connection string in the Atlas web UI.

Regarding general support for Android: the Java driver is not tested on Android. It may work but we don’t make any effort to ensure that it does. The driver assumes it’s running on a standard JVM, and insofar as Android emulates one it should work, but it’s not considered a supported platform.

Regards,
Jeff Yemin