Error when trying to insert POJO document: Could not resolve codec

I’m trying to insert one POJO document into a collection in Android Studio and the returned error object says “failed to insert documents with: Could not resolve codec for Subscribed”.

Here is the class I’m trying to make a document of to insert into the matching collection:

package com.example.ourmprealmtest;
import org.bson.codecs.pojo.annotations.BsonProperty;
import org.bson.types.ObjectId;
import androidx.annotation.Nullable;

import java.util.ArrayList;

import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;

public class Subscribed {
    private ObjectId id;
    private String[] MPs;
    private String[] Bills;
    @BsonProperty("_partition")
    private String partition;

    public Subscribed() {}


    public ObjectId getId() {
        return id;
    }

    public void setId(String iD) {
        ObjectId userID = new ObjectId();
        id = userID;

    }

    public String[] getMPs() {
        return MPs;
    }

    public void setMPs(String[] MPs) {
        this.MPs = MPs;
    }

    public String[] getBills() {
        return Bills;
    }

    public void setBills(String[] bills) {
        Bills = bills;
    }

    public String getPartition() { return partition; }
    public void setPartition(String partition) { this.partition = partition; }
}

And here’s the logic for the insert from the main activity:

package com.example.ourmprealmtest;

import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmList;
import io.realm.mongodb.App;
import io.realm.mongodb.AppConfiguration;
import io.realm.mongodb.Credentials;
import io.realm.mongodb.User;
import io.realm.mongodb.mongo.MongoClient;
import io.realm.mongodb.mongo.MongoCollection;
import io.realm.mongodb.mongo.MongoDatabase;

import android.widget.Toast;

import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;

import java.util.ArrayList;
import java.util.Arrays;


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    String appID = "x";
    private App app;
    MongoDatabase mongoDatabase;
    MongoClient mongoClient;


    String[] MPs = {"Peter Julian", "Don Davies", "Leah Gazan"};
    String[] Bills = {"1708047", "4772238", "4771556"};
    String userID = "62018c22b24cd58e11f17c74";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Realm.init(this);

        app = new App(new AppConfiguration.Builder(appID).build());

        app.loginAsync(Credentials.anonymous(), new App.Callback<User>() {
            @Override
            public void onResult(App.Result<User> result) {
                if(result.isSuccess())
                {
                    Log.v("User","Logged In Successfully");

                    User user = app.currentUser();
                    MongoClient mongoClient =
                            user.getMongoClient("mongodb-atlas");
                    MongoDatabase mongoDatabase =
                            mongoClient.getDatabase("plant-data-database");

                    // registry to handle POJOs (Plain Old Java Objects)
                    CodecRegistry pojoCodecRegistry = fromRegistries(AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY,
                            fromProviders(PojoCodecProvider.builder().automatic(true).build()));
                    MongoCollection<Subscribed> mongoCollection =
                            mongoDatabase.getCollection(
                                    "subcribed",
                                    Subscribed.class).withCodecRegistry(pojoCodecRegistry);
                    Log.v("EXAMPLE", "Successfully instantiated the MongoDB collection handle");

                    Subscribed newSub = new Subscribed();
                    newSub.setId(userID);
                    newSub.setBills(Bills);
                    newSub.setMPs(MPs);
                    mongoCollection.insertOne(newSub).getAsync(task -> {
                        if (task.isSuccess()) {
                            Log.v("EXAMPLE", "successfully inserted a document with id: " + task.get().getInsertedId());
                        } else {
                            Log.e("EXAMPLE", "failed to insert documents with: " + task.getError().getErrorMessage());
                        }
                    });
                }
                else
                {
                    Log.v("User","Failed to Login");
                }
            }
        });

I don’t know if this is the optimal way to do this, there’s so much conflicting information in the documentation and gaps in coverage that make it really hard to tell how I should be setting this up. If anyone can help me get to the bottom of this issue or suggest another way to implement database connectivity that avoids dealing with POJOs altogether please let me know. I’ve been trying for weeks to just get basic CRUD methods to connect to an Atlas collection set up but nothing seems to work.

@Gus_McCallum: I wouldn’t recommend this way of implementation. Did you get a chance to look at this article which should be helpful for you for getting started?

Hi, thanks for the article.

Yes I’ve checked it out and many other examples in the documentation but first of all it seems like there’s almost no resources or at least complete examples of Android apps in Java which makes it very difficult to ascertain the specific syntax for setting up Realm for the most basic operations.

Secondly, there are many conflicting examples in the documentation that accomplish the same tasks in different ways, for example the syntax for using POJOs as above was copied directly from the documentation here which seems to be offering it as the “default” way to perform CRUD operations on an Atlas cluster through Realm.

I’m having a very hard time finding resources specific to my use case (Android app written in Java) and lots of conflicting information out there, if you have any other resources you think I should check out I would really appreciate it. All I’ve got working so far is anonymous sign ins through Realm but basic CRUD operations are still escaping me. Thanks.

Hi Gus,

Sorry to hear you’re having a tough time with this. I work on the documentation for the Java SDK (previously called the Android SDK), so hopefully I can help.

First: is there a reason why you’re preferring MongoDB Data Access here? There’s nothing wrong with using MongoDB Data Access (some use cases certainly make it the best option), but you might have an easier time using a local Realm Database instance and Sync to read and write data. There’s a lot more examples available for Realm Database, too, in that linked documentation.

If MongoDB Data Access is really the best way for you to go, I might be able to help – I did write that example and figure out this method of reading/writing POJOs with the SDK. I’ve tested the example on my end, so it does work in my case, but I can’t quite figure out what’s wrong with your implementation. Can you take a look at your backend Realm App logs and tell me if you see any errors when you query (and if so, what they are)?

If POJOs are giving you problems, you can also omit the codec information and the Subscribed class when you instantiate your MongoCollection, and use the default return type of BsonDocument instead. This won’t insert data into a nice typed POJO, but it will let you read and write data locally if that’s all you need.

Hopefully this helps a bit – happy to help you debug this, because as far as I can tell your example should work. Hopefully the logs can shed some light on what’s going on. Thanks for bringing this up, hopefully we can make this documentation a little clearer once we get to the bottom of this.

– Nate

1 Like