2015-07-10 3 views
4

WebSockets in Play 2.4, похоже, не работает при использовании инъекции зависимостей во время компиляции. Я использую последнюю версию 2.4.2. В частности, он выдает следующее исключение при подключении:Play 2.4 WebSocket throws InstantiationException при использовании инъекции зависимостей во время компиляции

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[InstantiationException: null]] 
    at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:254) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:180) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$messageReceived$1.applyOrElse(PlayDefaultUpstreamHandler.scala:182) [play-netty-server_2.11-2.4.0.jar:2.4.0] 
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$messageReceived$1.applyOrElse(PlayDefaultUpstreamHandler.scala:180) [play-netty-server_2.11-2.4.0.jar:2.4.0] 
    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) [scala-library-2.11.6.jar:na] 
    at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:215) [scala-library-2.11.6.jar:na] 
    at scala.util.Try$.apply(Try.scala:191) [scala-library-2.11.6.jar:na] 
    at scala.util.Failure.recover(Try.scala:215) [scala-library-2.11.6.jar:na] 
    at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:324) [scala-library-2.11.6.jar:na] 
    at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:324) [scala-library-2.11.6.jar:na] 
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) [scala-library-2.11.6.jar:na] 
    ... 
Caused by: java.lang.InstantiationException: null 
    at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48) ~[na:1.8.0_45] 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[na:1.8.0_45] 
    at java.lang.Class.newInstance(Class.java:442) ~[na:1.8.0_45] 
    at play.api.inject.NewInstanceInjector$.instanceOf(Injector.scala:49) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.api.inject.SimpleInjector$$anonfun$instanceOf$1.apply(Injector.scala:85) ~[play_2.11-2.4.0.jar:2.4.0] 
    at scala.collection.MapLike$class.getOrElse(MapLike.scala:128) ~[scala-library-2.11.6.jar:na] 
    at scala.collection.AbstractMap.getOrElse(Map.scala:59) ~[scala-library-2.11.6.jar:na] 
    at play.api.inject.SimpleInjector.instanceOf(Injector.scala:85) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.api.inject.SimpleInjector.instanceOf(Injector.scala:80) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:234) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:234) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.utils.InlineCache.fresh(InlineCache.scala:69) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.utils.InlineCache.apply(InlineCache.scala:62) ~[play_2.11-2.4.0.jar:2.4.0] 
    at play.api.libs.concurrent.Akka$.system(Akka.scala:37) ~[play_2.11-2.4.0.jar:2.4.0] 
    ... 

Вот как контроллер выглядит следующим образом:

class Application extends Controller { 
    import play.api.Play.current 
    def socket = WebSocket.acceptWithActor[String, String] { request => out => 
    WebSocketActor.props(out) 
    } 
} 

object WebSocketActor { 
    def props(out: ActorRef) = Props(new WebSocketActor(out)) 
} 

class WebSocketActor(out: ActorRef) extends Actor { 
    def receive = { 
    case msg: String => 
     out ! ("Received message: " + msg) 
    } 
} 

А вот как ApplicationLoader выглядит следующим образом:

class AppLoader extends ApplicationLoader { 
    override def load(context: Context): Application = new AppComponents(context).application 
} 

class AppComponents(context: Context) extends BuiltInComponentsFromContext(context) { 
    lazy val appController = new controllers.Application 
    lazy val router = new Routes(httpErrorHandler, appController, assets) 
    lazy val assets = new controllers.Assets(httpErrorHandler) 
} 

ответ

4

Оказывается, это ошибка в игре 2.4.2. В настоящий момент есть исправление pull request.

До тех пор, пока оно не будет исправлено, я работал вокруг него, переопределяя injectorAppComponents, а также actorSystem. Таким образом, AppComponents будет:

class AppComponents(context: Context) extends BuiltInComponentsFromContext(context) { 
    lazy val appController = new controllers.Application 
    lazy val router = new Routes(httpErrorHandler, appController, assets) 
    lazy val assets = new controllers.Assets(httpErrorHandler) 

    // temporary workaround until issue #4614 in playframework is fixed. See https://github.com/playframework/playframework/issues/4614 
    override lazy val injector = new SimpleInjector(NewInstanceInjector) + router.asInstanceOf[play.api.routing.Router] + crypto + httpConfiguration + actorSystem 
}