2

这是我第一次使用 Mongo Scala 驱动程序(2.1 版),我注意到在处理我的一些案例类时出现了奇怪的行为——其中一些在classToCaseClassMap解码数据时没有被识别为其中一个走错了路,并以java.util.NoSuchElementException: head of empty list第 204 行的错误结束,org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec因为fieldClazzTypeArgs列表为空。

这是堆栈跟踪的前三分之一左右:

error: class java.util.NoSuchElementException: head of empty list
scala.collection.immutable.Nil$.head(List.scala:420)
scala.collection.immutable.Nil$.head(List.scala:417)
org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec$class.readDocument(MacroCodec.scala:204)
palladium.calendar.dal.mongodb.Implicits$$anon$2$GoogleCalendarEventMacroCodec$3.readDocument(GoogleCalendarDAO.scala:55)
org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec$class.readValue(MacroCodec.scala:173)
palladium.calendar.dal.mongodb.Implicits$$anon$2$GoogleCalendarEventMacroCodec$3.readValue(GoogleCalendarDAO.scala:55)
org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec$class.decode(MacroCodec.scala:104)
palladium.calendar.dal.mongodb.Implicits$$anon$2$GoogleCalendarEventMacroCodec$3.decode(GoogleCalendarDAO.scala:55)
org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec$class.readDocument(MacroCodec.scala:197)
palladium.calendar.dal.mongodb.Implicits$$anon$8$GoogleCalendarMacroCodec$3.readDocument(GoogleCalendarDAO.scala:61)
org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec$class.readValue(MacroCodec.scala:173)
palladium.calendar.dal.mongodb.Implicits$$anon$8$GoogleCalendarMacroCodec$3.readValue(GoogleCalendarDAO.scala:61)
org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec$class.readArray(MacroCodec.scala:187)
palladium.calendar.dal.mongodb.Implicits$$anon$8$GoogleCalendarMacroCodec$3.readArray(GoogleCalendarDAO.scala:61)
org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec$class.readValue(MacroCodec.scala:174)
palladium.calendar.dal.mongodb.Implicits$$anon$8$GoogleCalendarMacroCodec$3.readValue(GoogleCalendarDAO.scala:61)
org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec$class.decode(MacroCodec.scala:104)
palladium.calendar.dal.mongodb.Implicits$$anon$8$GoogleCalendarMacroCodec$3.decode(GoogleCalendarDAO.scala:61)
com.mongodb.operation.CommandResultArrayCodec.decode(CommandResultArrayCodec.java:52)
com.mongodb.operation.CommandResultDocumentCodec.readValue(CommandResultDocumentCodec.java:53)
org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:84)
org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:41)
org.bson.codecs.configuration.LazyCodec.decode(LazyCodec.java:47)
org.bson.codecs.BsonDocumentCodec.readValue(BsonDocumentCodec.java:101)
com.mongodb.operation.CommandResultDocumentCodec.readValue(CommandResultDocumentCodec.java:56)
org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:84)
org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:41)
com.mongodb.connection.ReplyMessage.<init>(ReplyMessage.java:57)
com.mongodb.connection.CommandProtocol.getResponseDocument(CommandProtocol.java:139)
com.mongodb.connection.CommandProtocol.access$000(CommandProtocol.java:51)
com.mongodb.connection.CommandProtocol$CommandResultCallback.callCallback(CommandProtocol.java:271)
com.mongodb.connection.ResponseCallback.onResult(ResponseCallback.java:48)
com.mongodb.connection.ResponseCallback.onResult(ResponseCallback.java:23)
com.mongodb.connection.DefaultConnectionPool$PooledConnection$2.onResult(DefaultConnectionPool.java:470)
com.mongodb.connection.DefaultConnectionPool$PooledConnection$2.onResult(DefaultConnectionPool.java:464)
com.mongodb.connection.UsageTrackingInternalConnection$3.onResult(UsageTrackingInternalConnection.java:119)
com.mongodb.connection.UsageTrackingInternalConnection$3.onResult(UsageTrackingInternalConnection.java:115)
com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49)
com.mongodb.connection.InternalStreamConnection.executeCallbackAndReceiveResponse(InternalStreamConnection.java:378)
com.mongodb.connection.InternalStreamConnection.access$1700(InternalStreamConnection.java:66)
com.mongodb.connection.InternalStreamConnection$ResponseBuffersCallback.onResult(InternalStreamConnection.java:420)
com.mongodb.connection.InternalStreamConnection$ResponseBuffersCallback.onResult(InternalStreamConnection.java:389)
com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback.onSuccess(InternalStreamConnection.java:562)
com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback.access$2200(InternalStreamConnection.java:517)
com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback$ResponseBodyCallback.onResult(InternalStreamConnection.java:584)
com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback$ResponseBodyCallback.onResult(InternalStreamConnection.java:568)
com.mongodb.connection.InternalStreamConnection$3.completed(InternalStreamConnection.java:447)
com.mongodb.connection.InternalStreamConnection$3.completed(InternalStreamConnection.java:444)
com.mongodb.connection.AsynchronousSocketChannelStream$BasicCompletionHandler.completed(AsynchronousSocketChannelStream.java:218)
com.mongodb.connection.AsynchronousSocketChannelStream$BasicCompletionHandler.completed(AsynchronousSocketChannelStream.java:201)
sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126)
sun.nio.ch.Invoker.invokeDirect(Invoker.java:157)
sun.nio.ch.UnixAsynchronousSocketChannelImpl.implRead(UnixAsynchronousSocketChannelImpl.java:553)
sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:276)
sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:297)

我的应用程序模拟某人的 Google 日历。这是我的案例课程:

case class GoogleDateTime(date: Option[DateTime] = None, dateTime: Option[DateTime])

case class LongId(id: Long)

case class GoogleCalendarEvent(id: String,
                           status: Option[String] = None,
                           htmlLink: Option[String] = None,
                           created: Option[DateTime] = None,
                           updated: Option[DateTime] = None,
                           creator: Option[GoogleWho] = None,
                           organizer: Option[GoogleWho] = None,
                           summary: Option[String],
                           description: Option[String] = None,
                           location: Option[String] = None,
                           start: GoogleDateTime,
                           end: GoogleDateTime,
                           extendedProperties: Option[GoogleEventExtendedProperties] = None)

case class GoogleCalendarEventList(nextPageToken: Option[String],
                               items: Option[List[GoogleCalendarEvent]])

case class GoogleWho(email: Option[String],
                 displayName: Option[String])

case class GoogleEventSharedProperties(createdBy: Option[String] = None,
                                   sessionType: Option[String] = None,
                                   sessionId: Option[LongId] = None,
                                   locationId: Option[LongId] = None,
                                   roomId: Option[LongId] = None)

case class GoogleEventExtendedProperties(shared: Option[GoogleEventSharedProperties])

这是一个屏幕截图的链接,显示了classToCaseClassMap错误发生时的内容。

屏幕截图显示了一个包含六个项目的地图,包括我的四个案例类:GoogleCalendarEventGoogleWhoGoogleDateTimeGoogleEventExtendedProperties。只有第一个 ( GoogleCalendarEvent) 被正确识别为案例类。

我尝试制作有问题的课程sealed,但这没有帮助。

以下是我创建 CodecRegistry 的方法:

val dtMap = Map(BsonType.DATE_TIME -> classOf[DateTime])

val typeClassReplacedMap = new BsonTypeClassMap(JavaConversions.mapAsJavaMap(dtMap))

val gcCodecProvider = new DocumentCodecProvider(typeClassReplacedMap)

implicit val gcRegistry: CodecRegistry = fromRegistries(fromCodecs(dtCodec),
fromProviders( gcCodecProvider,
classOf[GoogleCalendarEvent],
classOf[GoogleDateTime],
classOf[LongId],
classOf[GoogleEventExtendedProperties],
classOf[GoogleEventSharedProperties],
classOf[GoogleWho],
classOf[GoogleCalendar]),
DEFAULT_CODEC_REGISTRY )

是显示数据访问代码以及我如何使用它的要点(在 sbt 控制台或 Intellij IDEA Scala 控制台中)。

我正在重构的应用程序在 Reactive Mongo 版本 0.11.7 上运行良好,但我们需要将其迁移到官方支持的 Mongo Scala 驱动程序才能使用新的 Atlas 数据库。

4

2 回答 2

2

我修复了从Providers 项目重新排序的类似问题。那些家伙类 A(b: B) 和类 B(i: Int) 应该是相反的顺序: fromProviders(classOf[B], classOf[A])

所以,看起来你应该在 classOf[GoogleEventExtendedProperties] 之后放置 classOf[GoogleCalendarEvent]

于 2017-09-01T21:43:03.063 回答
1

在那之后的FWIW,看看https://jira.mongodb.org/browse/SCALA-338

我有同样的问题,感谢您的帖子,我发现这是编解码器提供商的订购。

最初我虽然可以通过确保在这些其他案例类之前列出包含其他案例类类型的值的案例类来解决它。但是到现在为止,即使那样也不能解决我的问题,但也许它可以帮助解决您的具体情况。

只需从 2.1.0 降级到 2.0.0 即可解决我的问题。

于 2017-08-30T08:16:28.580 回答