scala - Play 2.4 WebSocket throws InstantiationException when using compile-time dependency injection -
websockets in play 2.4 doesn't seem work when using compile-time dependency injection. i'm using latest version 2.4.2. specifically, throws following exception upon connecting:
play.api.http.httperrorhandlerexceptions$$anon$1: execution exception[[instantiationexception: null]] @ play.api.http.httperrorhandlerexceptions$.throwabletousefulexception(httperrorhandler.scala:254) ~[play_2.11-2.4.0.jar:2.4.0] @ play.api.http.defaulthttperrorhandler.onservererror(httperrorhandler.scala:180) ~[play_2.11-2.4.0.jar:2.4.0] @ play.core.server.netty.playdefaultupstreamhandler$$anonfun$messagereceived$1.applyorelse(playdefaultupstreamhandler.scala:182) [play-netty-server_2.11-2.4.0.jar:2.4.0] @ play.core.server.netty.playdefaultupstreamhandler$$anonfun$messagereceived$1.applyorelse(playdefaultupstreamhandler.scala:180) [play-netty-server_2.11-2.4.0.jar:2.4.0] @ scala.runtime.abstractpartialfunction.apply(abstractpartialfunction.scala:36) [scala-library-2.11.6.jar:na] @ scala.util.failure$$anonfun$recover$1.apply(try.scala:215) [scala-library-2.11.6.jar:na] @ scala.util.try$.apply(try.scala:191) [scala-library-2.11.6.jar:na] @ scala.util.failure.recover(try.scala:215) [scala-library-2.11.6.jar:na] @ scala.concurrent.future$$anonfun$recover$1.apply(future.scala:324) [scala-library-2.11.6.jar:na] @ scala.concurrent.future$$anonfun$recover$1.apply(future.scala:324) [scala-library-2.11.6.jar:na] @ scala.concurrent.impl.callbackrunnable.run(promise.scala:32) [scala-library-2.11.6.jar:na] ... caused by: java.lang.instantiationexception: null @ sun.reflect.instantiationexceptionconstructoraccessorimpl.newinstance(instantiationexceptionconstructoraccessorimpl.java:48) ~[na:1.8.0_45] @ java.lang.reflect.constructor.newinstance(constructor.java:422) ~[na:1.8.0_45] @ java.lang.class.newinstance(class.java:442) ~[na:1.8.0_45] @ play.api.inject.newinstanceinjector$.instanceof(injector.scala:49) ~[play_2.11-2.4.0.jar:2.4.0] @ play.api.inject.simpleinjector$$anonfun$instanceof$1.apply(injector.scala:85) ~[play_2.11-2.4.0.jar:2.4.0] @ scala.collection.maplike$class.getorelse(maplike.scala:128) ~[scala-library-2.11.6.jar:na] @ scala.collection.abstractmap.getorelse(map.scala:59) ~[scala-library-2.11.6.jar:na] @ play.api.inject.simpleinjector.instanceof(injector.scala:85) ~[play_2.11-2.4.0.jar:2.4.0] @ play.api.inject.simpleinjector.instanceof(injector.scala:80) ~[play_2.11-2.4.0.jar:2.4.0] @ play.api.application$$anonfun$instancecache$1.apply(application.scala:234) ~[play_2.11-2.4.0.jar:2.4.0] @ play.api.application$$anonfun$instancecache$1.apply(application.scala:234) ~[play_2.11-2.4.0.jar:2.4.0] @ play.utils.inlinecache.fresh(inlinecache.scala:69) ~[play_2.11-2.4.0.jar:2.4.0] @ play.utils.inlinecache.apply(inlinecache.scala:62) ~[play_2.11-2.4.0.jar:2.4.0] @ play.api.libs.concurrent.akka$.system(akka.scala:37) ~[play_2.11-2.4.0.jar:2.4.0] ... here's how controller looks like:
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) } } and here's how applicationloader looks like:
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) }
turns out bug in play 2.4.2. there's pull request fix it.
until it's fixed, worked around overriding injector of appcomponents include actorsystem. appcomponents becomes:
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 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 }
Comments
Post a Comment