Совместимость с драйвером mongodb 3.x для Android

Я разрабатываю приложение для Android, которое использует драйвер java mongodb 3.0.3 для подключения к каждому экземпляру mongodb.

Код соединителя для общего istance:

try{
    MongoCredential credential = MongoCredential.createCredential(user, dbname, pass.toCharArray());
    MongoClient mongoClient = new MongoClient( new ServerAddress(server , port ), Arrays.asList(credential));
    MongoDatabase db = mongoClient.getDatabase(dbname);
    System.out.println("Connect to database successfully ");
    Iterator i= mongoClient.listDatabaseNames().iterator();
    while (i.hasNext()){
        Log.d("DATABASE", (String) i.next());
    }
    Iterator ic= db.listCollectionNames().iterator();
    while (ic.hasNext()){
        Log.d("COLLECTION", (String) ic.next());
    }
}catch(Exception e){
    System.err.println( e.getClass().getName() + ": " + e.getMessage() );
}

Во время выполнения у меня есть некоторые ошибки:

09-11 19: 13: 50.898 7418-7418 / it.mysite.mongodbviewer W / org.bson.ObjectId ﹕ Не удалось получить идентификатор процесса из JMX с использованием случайного числа вместо java.lang.NoClassDefFoundError: Не удалось разрешить: Ljava/lang/ управление /ManagementFactory;

а также

com.mongodb.MongoException: java.lang.NoClassDefFoundError: com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient

которые генерируют цикл с этим:

I / art ject Отказ от повторной инициализации ранее неудачного класса java.lang.Class

У кого-нибудь есть решение? java/lang/management/ManagementFactory, кажется, не существует для Android, как вы можете решить? Если это центр проблемы.

Заранее спасибо, Маттео

PS: полный журнал:

09-11 19:13:50.898    7418-7418/it.mysite.mongodbviewer W/org.bson.ObjectId﹕ Failed to get process identifier from JMX, using random number instead
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;
at org.bson.types.ObjectId.createProcessIdentifier(ObjectId.java:502)
at org.bson.types.ObjectId.<clinit>(ObjectId.java:460)
at com.mongodb.connection.ClusterId.<init>(ClusterId.java:47)
at com.mongodb.connection.DefaultClusterFactory.create(DefaultClusterFactory.java:40)
at com.mongodb.Mongo.createCluster(Mongo.java:660)
at com.mongodb.Mongo.createCluster(Mongo.java:646)
at com.mongodb.Mongo.<init>(Mongo.java:275)
at com.mongodb.MongoClient.<init>(MongoClient.java:184)
at com.mongodb.MongoClient.<init>(MongoClient.java:160)
at it.mysite.mongodbmanager.data.MongoDBDriver.connect(MongoDBDriver.java:102)
at it.mysite.mongodbmanager.fragments.MongoDBAccountDetailFragment.onClick(MongoDBAccountDetailFragment.java:101)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19865)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
 Caused by: java.lang.ClassNotFoundException: Didn't find class "java.lang.management.ManagementFactory" on path: DexPathList[[zip file "/data/app/it.mysite.mongodbviewer-2/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
    at org.bson.types.ObjectId.createProcessIdentifier(ObjectId.java:502)
    at org.bson.types.ObjectId.<clinit>(ObjectId.java:460)
    at com.mongodb.connection.ClusterId.<init>(ClusterId.java:47)
    at com.mongodb.connection.DefaultClusterFactory.create(DefaultClusterFactory.java:40)
    at com.mongodb.Mongo.createCluster(Mongo.java:660)
    at com.mongodb.Mongo.createCluster(Mongo.java:646)
    at com.mongodb.Mongo.<init>(Mongo.java:275)
    at com.mongodb.MongoClient.<init>(MongoClient.java:184)
    at com.mongodb.MongoClient.<init>(MongoClient.java:160)
    at it.mysite.mongodbmanager.data.MongoDBDriver.connect(MongoDBDriver.java:102)
    at it.mysite.mongodbmanager.fragments.MongoDBAccountDetailFragment.onClick(MongoDBAccountDetailFragment.java:101)
    at android.view.View.performClick(View.java:4780)
    at android.view.View$PerformClick.run(View.java:19865)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5254)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Suppressed: java.lang.ClassNotFoundException: java.lang.management.ManagementFactory
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 22 more
 Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
09-11 19:13:50.901    7418-7418/it.mysite.mongodbviewer I/cluster﹕ Cluster created with settings {hosts=[192.168.1.74:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
09-11 19:13:50.918    7418-7418/it.mysite.mongodbviewer I/System.out﹕ Connect to database successfully
09-11 19:13:50.924    7418-7418/it.mysite.mongodbviewer I/cluster﹕ No server chosen by ReadPreferenceServerSelector{readPreference=primary} from cluster description ClusterDescription{type=UNKNOWN, connectionMode=SINGLE, all=[ServerDescription{address=192.168.1.74:27017, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out
09-11 19:13:50.954    7418-7487/it.mysite.mongodbviewer I/art﹕ Rejecting re-init on previously-failed class java.lang.Class<com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient>
09-11 19:13:50.954    7418-7487/it.mysite.mongodbviewer I/art﹕ Rejecting re-init on previously-failed class java.lang.Class<com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient>
09-11 19:13:50.955    7418-7487/it.mysite.mongodbviewer I/art﹕ Rejecting re-init on previously-failed class java.lang.Class<com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient>
09-11 19:13:50.956    7418-7487/it.mysite.mongodbviewer I/cluster﹕ Exception in monitor thread while connecting to server 192.168.1.74:27017
com.mongodb.MongoException: java.lang.NoClassDefFoundError: com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient
at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:125)
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:127)
at java.lang.Thread.run(Thread.java:818)
 Caused by: java.lang.NoClassDefFoundError: com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient
at com.mongodb.connection.ScramSha1Authenticator.createSaslClient(ScramSha1Authenticator.java:61)
at com.mongodb.connection.SaslAuthenticator.authenticate(SaslAuthenticator.java:42)
at com.mongodb.connection.DefaultAuthenticator.authenticate(DefaultAuthenticator.java:32)
at com.mongodb.connection.InternalStreamConnectionInitializer.authenticateAll(InternalStreamConnectionInitializer.java:99)
at com.mongodb.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:44)
at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115)
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:127)
at java.lang.Thread.run(Thread.java:818)
09-11 19:13:51.479    7418-7487/it.mysite.mongodbviewer I/art﹕ Rejecting re-init on previously-failed class java.lang.Class<com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient>
09-11 19:13:52.106    7418-7487/it.mysite.mongodbviewer I/art﹕ Rejecting re-init on previously-failed class java.lang.Class<com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient>
09-11 19:13:52.637    7418-7487/it.mysite.mongodbviewer I/art﹕ Rejecting re-init on previously-failed class java.lang.Class<com.mongodb.connection.ScramSha1Authenticator$ScramSha1SaslClient>

3 ответа

Решение

Для тех, кто хочет использовать github.com/mongodb/mongo-java-driver на Android у меня есть решение!

Я разветвился от служебного github.com/mongodb/mongo-java-driver и интегрированные классы из github.com/koterpillar/android-sasl чинить javax.security.sasl на андроид.

Важное замечание: Драйвер-асинхронизация не портирована, потому что java.nio.channels.AsynchronousSocketChannel не существует на Android и не существует никакого портирования.

В результате получается работающий синхронный драйвер MongoDB для Android (Java), который можно загрузить по https://github.com/matfur92/mongo-java-driver

ПОСЛЕДНИЕ ОБНОВЛЕНИЯ (5 ноября 2015 г.): 3.2.0-SNAPSHOT -> https://github.com/matfur92/mongo-java-driver/blob/gh-pages/JARs/mongo-java-driver-3.2.0-SNAPSHOT.jar?raw=true

Мне кажется, что ManagementFactory - красная сельдь, поскольку драйвер ловит это исключение и вместо этого использует случайное число.

По-видимому, реальная проблема заключается в том, что драйверу необходимо пройти аутентификацию с помощью SCRAM-SHA-1, реализация которого импортирует следующие классы:

import javax.crypto.Mac;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;

Я подозреваю, что они недоступны на платформе Android, которая не является полной реализацией среды выполнения Java.

Одна вещь, которую вы могли бы попробовать, это запустить MongoDB 2.6, для которой реализация аутентификации драйвера основана только на java.security.MessageDigest.

Еще одна вещь, о которой стоит подумать, - это поместить службу REST между мобильным приложением и MongoDB, которое отвечает за передачу всех взаимодействий с базой данных. Приложение REST может быть запущено в среде, где драйвер MongoDB будет полностью функциональным.

Обходной путь службы REST не подходит, я должен подключиться напрямую к экземплярам mongodb.

РЕДАКТИРОВАТЬ:

Синхронизация mongo-java-driver правильно портирована на Android с этим портированием: https://github.com/matfur92/mongo-java-driver

Ни один драйвер-асинхронный не портирован, потому что java.nio.channels.AsynchronousSocketChannel не существует на Android и не существует никакого портирования.

Если у кого-то есть решение, чтобы заставить работать драйвер-асинхронный, скажите, пожалуйста. Проблема в java.nio.channels.AsynchronousSocketChannel которые не существуют для Android

Другие вопросы по тегам