• Java操作MongoDB报错 java.lang.IllegalStateException: state should be: open


    问题描述

    • 我在使用Spark整合MongoDB,涉及到了MongoDB Colletion中的文档删除与新建(也就是更新文档)时,出现了报错java.lang.IllegalStateException: state should be: open
    • 错误代码如下
     /**
         * 将数据保存到 MongoDB userId -> 1, recs -> 22:4.5|45:3.8
         *
         * @param userId      用户ID
         * @param streamRecs  流式的推荐结果
         * @param mongoConfig MongoDB 的配置
         */
        public static void saveRecListToMongoDB(int userId, Tuple2<Integer, Double>[] streamRecs, Properties mongoConfig) {
            log.info("准备将实时推荐列表保存到 MongoDB,入参为:userId={} streamRecs={}", userId, streamRecs);
            // 1.连接到 StreamRecList实时推荐列表
            MongoCollection<Document> streamRecListCollection = null;
            try (MongoClient mongoClient = MongoClients.create(mongoConfig.getProperty("mongo.uri"))) {
                streamRecListCollection = mongoClient
                        .getDatabase(mongoConfig.getProperty("mongo.db"))
                        .getCollection(mongoConfig.getProperty("mongo.collection"));
            }
            // 2.删除 Mongo collection 中已存在的记录
            log.info("删除 Mongo collection 中已存在的用户 userId={} 的实时推荐表", userId);
            // fixme java.lang.IllegalStateException: state should be: open
            streamRecListCollection.findOneAndDelete(Filters.eq("userId", userId));
    
            
            // 3.插入文档(即将用户实时推荐列表写入到MongoDB)
            List<Document> recList = Arrays.stream(streamRecs).map(rec ->
                    new Document().append("movieId", rec._1).append("rating", rec._2)
            ).collect(Collectors.toList());
    
            Document doc = new Document("userId", userId).append("recs", recList);
    
            streamRecListCollection.insertOne(doc);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    分析原因与解决

    • 1)我在想,既然Java编译器在编译器没有报错,那就应该不存在受检异常
    • 2)查找网络资料后,分析问题应该是出现在MongoDB连接的问题上,因此我检查了我的配置文件,如下:
    # Mongo相关配置
    mongo.uri=mongodb://192.168.188.128:27017,192.168.188.129:27017,192.168.188.130:27017/recommend
    mongo.db=recommend
    
    • 1
    • 2
    • 3
    • 3)配置文件也正确,那我们没有思绪了
    • 4)又想到是因为MongoDB连接上的问题,我又看到了在代码中使用了 try-with-resource语法,我觉得是因为这个语法的原因,因此我将对MongoDB 的操作都包裹在了try-with-resource中,代码如下:
        public static void saveRecListToMongoDB(int userId, Tuple2<Integer, Double>[] streamRecs, Properties mongoConfig) {
            log.info("准备将实时推荐列表保存到 MongoDB,入参为:userId={} streamRecs={}", userId, streamRecs);
            // 1.连接到 StreamRecList实时推荐列表
            MongoCollection<Document> streamRecListCollection = null;
            try (MongoClient mongoClient = MongoClients.create(mongoConfig.getProperty("mongo.uri"))) {
                streamRecListCollection = mongoClient
                        .getDatabase(mongoConfig.getProperty("mongo.db"))
                        .getCollection(mongoConfig.getProperty("mongo.collection"));
    
                // 2.删除 Mongo collection 中已存在的记录
                log.info("删除 Mongo collection 中已存在的用户 userId={} 的实时推荐表", userId);
                // fixme java.lang.IllegalStateException: state should be: open
                streamRecListCollection.findOneAndDelete(Filters.eq("userId", userId));
    
    
                // 3.插入文档(即将用户实时推荐列表写入到MongoDB)
                List<Document> recList = Arrays.stream(streamRecs).map(rec ->
                        new Document().append("movieId", rec._1).append("rating", rec._2)
                ).collect(Collectors.toList());
    
                Document doc = new Document("userId", userId).append("recs", recList);
    
                streamRecListCollection.insertOne(doc);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    至此,Bug成功解决了

    Bug复现

    • 1)Bug代码如下:
    import com.mongodb.client.MongoClient;
    import com.mongodb.client.MongoClients;
    import com.mongodb.client.MongoCollection;
    import com.mongodb.client.model.Filters;
    import org.bson.Document;
    
    /**
     * 演示 fixme java.lang.IllegalStateException: state should be: open
     */
    public class BugTest {
        public static void main(String[] args) {
            // 1.连接到 StreamRecList实时推荐列表
            MongoCollection<Document> collection = null;
            try (MongoClient mongoClient = MongoClients.create("mongodb://192.168.188.150:27017/testdb")) {
                collection = mongoClient
                        .getDatabase("testdb")
                        .getCollection("user");
            }
            // 2.删除 Mongo collection 中已存在的记录
            // fixme java.lang.IllegalStateException: state should be: open
            collection.findOneAndDelete(Filters.eq("userId", 1));
            
            // 3.插入文档(即将用户实时推荐列表写入到MongoDB)
            Document doc = new Document("userId", 2);
    
            collection.insertOne(doc);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 2)报错堆栈信息如下:
    Exception in thread "main" java.lang.IllegalStateException: state should be: open
    	at com.mongodb.assertions.Assertions.isTrue(Assertions.java:72)
    	at com.mongodb.internal.connection.BaseCluster.getDescription(BaseCluster.java:167)
    	at com.mongodb.internal.connection.SingleServerCluster.getDescription(SingleServerCluster.java:41)
    	at com.mongodb.client.internal.MongoClientDelegate.getConnectedClusterDescription(MongoClientDelegate.java:155)
    	at com.mongodb.client.internal.MongoClientDelegate.createClientSession(MongoClientDelegate.java:105)
    	at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.getClientSession(MongoClientDelegate.java:287)
    	at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:211)
    	at com.mongodb.client.internal.MongoCollectionImpl.executeFindOneAndDelete(MongoCollectionImpl.java:733)
    	at com.mongodb.client.internal.MongoCollectionImpl.findOneAndDelete(MongoCollectionImpl.java:714)
    	at com.mongodb.client.internal.MongoCollectionImpl.findOneAndDelete(MongoCollectionImpl.java:708)
    	at com.clear.bug.BugTest.main(BugTest.java:23)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 3)将MongoDB相关操作放入try-with-resource即可成功运行
    public class BugTest {
        public static void main(String[] args) {
            // 1.连接到 StreamRecList实时推荐列表
            MongoCollection<Document> collection = null;
            try (MongoClient mongoClient = MongoClients.create("mongodb://192.168.188.150:27017/testdb")) {
                collection = mongoClient
                        .getDatabase("testdb")
                        .getCollection("user");
    
    
                // 2.删除 Mongo collection 中已存在的记录
                collection.findOneAndDelete(Filters.eq("userId", 1));
    
                // 3.插入文档(即将用户实时推荐列表写入到MongoDB)
                Document doc = new Document("userId", 2);
    
                collection.insertOne(doc);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    React学习之路 - HTML5 新特性
    YOLOX理论
    在网络安全、爬虫和HTTP协议中的重要性和应用
    JavaScript-es6-新版语法-export-import
    远程访问及控制
    生信基因序列比对相关软件安装fastqc、hisat2、samtools;GATK docker安装
    前端三大Css处理器之Less
    js文字逐个显示
    解读 | 快速精确的体素GICP三维点云配准算法
    C++核心编程--多态篇
  • 原文地址:https://blog.csdn.net/weixin_56058578/article/details/134526205