MongoDBにデータを登録しようとしたところ、 以下のエラーが発生しました。 エラー原因と対処方法を備忘としてメモします。

1.エラー内容


Exception in thread "main" java.lang.IllegalArgumentException: Invalid BSON field name java.runtime.name
    at org.bson.AbstractBsonWriter.writeName(AbstractBsonWriter.java:494)
    at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:188)
    at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:172)
    at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:189)
    at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:172)
    at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:189)
    at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:131)
    at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
    at com.mongodb.connection.InsertCommandMessage.writeTheWrites(InsertCommandMessage.java:99)
    at com.mongodb.connection.InsertCommandMessage.writeTheWrites(InsertCommandMessage.java:43)
    at com.mongodb.connection.BaseWriteCommandMessage.encodeMessageBody(BaseWriteCommandMessage.java:112)
    at com.mongodb.connection.BaseWriteCommandMessage.encodeMessageBody(BaseWriteCommandMessage.java:35)
    at com.mongodb.connection.RequestMessage.encode(RequestMessage.java:132)
    at com.mongodb.connection.BaseWriteCommandMessage.encode(BaseWriteCommandMessage.java:89)
    at com.mongodb.connection.WriteCommandProtocol.sendMessage(WriteCommandProtocol.java:170)
    at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:73)
    at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:66)
    at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:37)
    at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:155)
    at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:219)
    at com.mongodb.connection.DefaultServerConnection.insertCommand(DefaultServerConnection.java:108)
    at com.mongodb.operation.MixedBulkWriteOperation$Run$2.executeWriteCommandProtocol(MixedBulkWriteOperation.java:416)
    at com.mongodb.operation.MixedBulkWriteOperation$Run$RunExecutor.execute(MixedBulkWriteOperation.java:604)
    at com.mongodb.operation.MixedBulkWriteOperation$Run.execute(MixedBulkWriteOperation.java:363)
    at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:148)
    at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:141)
    at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:186)
    at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:177)
    at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:141)
    at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:72)
    at com.mongodb.Mongo.execute(Mongo.java:747)
    at com.mongodb.Mongo$2.execute(Mongo.java:730)
    at com.mongodb.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:482)
    at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:277)

2.原因

登録対象データは、javaのSystem.getProperties()の戻りです。
登録データのキー値:Valueとして、以下の形式となるため、エラーとなりました。
{“file.encoding” : “UTF-8”}
※キー値として、“.”を含む値は使えない。
MongoDBの仕様なのか、MongoDriver側の問題なのかはよくわかりません。

3.対処

javaオブジェクトをjacksonを使用してMap化していたので、
SimpleModuleにProperties用のSerializerを追加、
ObjectMapperに登録しました。
“.”がKey値に含まれる場合は、“_”に変換してキー値として使います。

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule("jobReportModule", Version.unknownVersion());
        module.addSerializer(Properties.class, new JsonSerializer<Properties>() {
            @Override
            public void serialize(Properties value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
                jgen.writeStartObject();
                for (String key : value.stringPropertyNames()) {
                    String convertedKey = key.replace(".", "_");
                    jgen.writeObjectField(convertedKey, value.get(key));
                }
                jgen.writeEndObject();
            }
        });
        mapper.registerModule(module);
        Map<String, Object> map = mapper.convertValue(report, Map.class);

  • 補足 キー値の変換は、PropertyNamingStrategyBaseを使用しても可能ですが、
    Nestされたキー値の変換までは行ってくれなかったため、
    Serializerを使って、変換処理を実装しました。

以上です。

コメント