Совместимость с драйвером 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