Hi,
the following WS code throws an "IllegalStateException: Promise already
completed." from time to time (not always):
WS.url(s"http://localhost:$port/").get(headers =>
Done(headers)).flatMap(_.run)
(what I'm really doing is a bit more complex, but directly returning
Done allows me to reproduce the issue)
Is
s.th. wrong with this?
This is the full stacktrace:
> [info] WS
> [info] - should accept Done iteratee *** FAILED ***
> [info] java.lang.IllegalStateException: Promise already completed.
> [info] at scala.concurrent.Promise$class.complete(Promise.scala:55)
> [info] at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153)
> [info] at scala.concurrent.Promise$class.success(Promise.scala:89)
> [info] at scala.concurrent.impl.Promise$DefaultPromise.success(Promise.scala:153)
> [info] at
play.api.libs.ws.WS$WSRequest$$anon$2$$anonfun$onBodyPartReceived$1.apply(WS.scala:289)
> [info] at
play.api.libs.ws.WS$WSRequest$$anon$2$$anonfun$onBodyPartReceived$1.apply(WS.scala:285)
> [info] at play.api.libs.iteratee.ImmediateIteratee$$anonfun$pureFold$2.apply(Iteratee.scala:601)
> [info] at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
> [info] at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
> [info] at scala.concurrent.forkjoin.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1361)
The full test to reproduce this (using scalatestplus):
> import org.scalatestplus.play.{PlaySpec, OneServerPerSuite}
> import play.api.mvc.Action
> import play.api.mvc.Results._
> import play.api.libs.iteratee.Done
> import play.api.test.Helpers._
> import play.api.test.FakeApplication
> import
play.api.libs.ws.WS
> import scala.concurrent.ExecutionContext.Implicits.global
>
> class WSSpec extends PlaySpec with OneServerPerSuite {
>
> implicit override lazy val app: FakeApplication =
> FakeApplication(
> withRoutes = {
> case ("GET", "/") => Action { Ok }
> }
> )
>
> "WS" should {
> "accept Done iteratee" in {
> // run several times, because it fails only sometimes
> for(i <- 0 to 30) {
> val futureResponse = WS.url(s"http://localhost:$port/").get(headers => Done(headers)).flatMap(_.run)
> val response = await(futureResponse)
> response.status mustBe OK
> }
> }
> }
>
> }
Thanx && cheers,
Martin