Воспроизвести исключение Morphia MappingException в WebSocket Iteratee после перезагрузки

Я использую Play 2.3 и Akka, чтобы настроить простой протокол подписки на публикацию через веб-сокет. В рамках этого протокола после подписки клиента сервер отправляет исходное состояние из базы данных.

Мой текущий код работает изначально, но во время разработки запрос Morphia внутри сокета Iteratee перестает работать после перезагрузки разработки. Регулярные запросы, даже запросы, которые делают один и тот же запрос, продолжают работать нормально.

Я использую подключаемый модуль распределенного суб-посредника паба Akka. Вот соответствующий код для актера, представляющего слушателя веб-сокета:

object Subscriber {
  def props(channel: Concurrent.Channel[JsValue]): Props = Props(new Subscriber(channel))
}

class Subscriber(channel: Concurrent.Channel[JsValue]) extends Actor {
  def receive = {
    case StatusUpdate(...) =>
      channel.push(...)
  }
}

И для контроллера главного представления:

object SocketController extends Controller {
  val mediator = DistributedPubSubExtension.get(Akka.system).mediator

  def index = WebSocket.using[JsValue] { implicit request =>
    val (out, channel) = Concurrent.broadcast[JsValue]

    val ws = Akka.system.actorOf(Subscriber.props(channel))

    val in = Iteratee.foreach[JsValue] { msg =>
      (msg \ "type").as[String] match {
        case "Subscribe" =>
          val target = (msg \ "value").as[String]

          // Query database with Morphia
          val current = MyObj.findByName(target)

          // Notify of current state
          ws ! StatusUpdate(target, current)

          // Subscribe for further updates
          mediator ! DistributedPubSubMediator.Subscribe(target, ws)
      }
    }

    (in, out)
  }
}

Проблема возникает в операторе запроса в итерации. После перезарядки Морфия бросает org.mongodb.morphia.mapping.MappingException: Could not map models.MyObj with ID: 5507a3653004b8a9e8f3d3b2. Вот полный след:

org.mongodb.morphia.mapping.MappingException: Could not map models.MyObj with ID: 5507a3653004b8a9e8f3d3b2
    at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:594)
    at org.mongodb.morphia.mapping.Mapper.fromDBObject(Mapper.java:299)
    at org.mongodb.morphia.query.MorphiaIterator.convertItem(MorphiaIterator.java:79)
    at org.mongodb.morphia.query.MorphiaIterator.processItem(MorphiaIterator.java:65)
    at org.mongodb.morphia.query.MorphiaIterator.next(MorphiaIterator.java:60)
    at org.mongodb.morphia.query.QueryImpl.get(QueryImpl.java:402)
    at models.MyObj$.findByName(MyObj.scala:99)
    at controllers.MyObj$$anonfun$MyObj$1$$anonfun$4.apply(MyObj.scala:99)
    at controllers.MyObj$$anonfun$MyObj$1$$anonfun$4.apply(MyObj.scala:93)
    at play.api.libs.iteratee.Iteratee$$anonfun$foreach$1.apply(Iteratee.scala:201)
    at play.api.libs.iteratee.Iteratee$$anonfun$foreach$1.apply(Iteratee.scala:201)
    at play.api.libs.iteratee.Iteratee$$anonfun$fold$1$$anonfun$apply$1.apply(Iteratee.scala:41)
    at play.api.libs.iteratee.internal$.eagerFuture(package.scala:30)
    at play.api.libs.iteratee.Iteratee$$anonfun$fold$1.apply(Iteratee.scala:41)
    at play.api.libs.iteratee.Iteratee$$anonfun$fold$1.apply(Iteratee.scala:41)
    at play.api.libs.iteratee.Iteratee$$anonfun$1.apply(Iteratee.scala:60)
    at play.api.libs.iteratee.Iteratee$$anonfun$1.apply(Iteratee.scala:60)
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
    at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
    at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: org.mongodb.morphia.mapping.MappingException: Error setting value from converter (ObjectIdConverter) for models.MyObj.id to 5507a3653004b8a9e8f3d3b2
    at org.mongodb.morphia.converters.DefaultConverters.fromDBObject(DefaultConverters.java:137)
    at org.mongodb.morphia.mapping.ValueMapper.fromDBObject(ValueMapper.java:27)
    at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:608)
    at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:589)
    ... 24 more
Caused by: java.lang.IllegalArgumentException: Can not set org.bson.types.ObjectId field models.MyObj.id to models.MyObj
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
    at java.lang.reflect.Field.set(Field.java:758)
    at org.mongodb.morphia.mapping.MappedField.setFieldValue(MappedField.java:508)
    at org.mongodb.morphia.converters.DefaultConverters.fromDBObject(DefaultConverters.java:135)
    ... 27 more

Это исключение происходит только в обработчике веб-сокетов, обычный запрос может выполнить запрос. Полный перезапуск сервера разработки устраняет проблему до следующей перезагрузки.

Вот журналы консоли после запуска и одного перезапуска: http://pastebin.com/xsstw4ki

Есть мысли о том, что здесь может происходить? Другие ссылки, которые я нашел для этой ошибки, кажутся несвязанными или старый.

Обновление - 4 июля 2015 г.

Также бывает в Play 2.4.2.


person Matt Bierner    schedule 21.03.2015    source источник
comment
Есть обновления по этому поводу?   -  person Sam Baumgarten    schedule 06.05.2015
comment
Я опубликовал проблему на GitHub (github.com/playframework/playframework/issues/4557 ), а затем запись в группах Google (groups.google.com/d / msg / play-framework / w0WhIckqvP0 / 6ZJ8_4KAKokJ) и до сих пор мертв.   -  person Sphygmomanometer    schedule 02.07.2015


Ответы (1)


Вы можете использовать следующий фрагмент кода, чтобы решить эту проблему. Измените создание морфии, добавив следующий код (код Scala)

if (Play.isDev)
    morphia.getMapper.getOptions.setObjectFactory(new PlayCreator)

Определение класса PlayCreator: (Код Java)

public class PlayCreator extends DefaultCreator {

@Override
protected ClassLoader getClassLoaderForClass() {
    return Play.application().classloader();
}
}

Пожалуйста, добавьте соответствующий импорт, и ваша горячая перезагрузка должна работать отлично :)

person Naveen    schedule 07.10.2015
comment
Эта кодовая база предназначена для Play 2.4.x. Используйте соответствующие методы для других версий Play 2.x - person Naveen; 07.10.2015