I have a lot of problems working with futures as an answer of using Scala Dispatch for asynchronous HTTP calls. I also used Case Class Matchers
lets suppose that I make a call here: http://ip.jsontest.com/ wich returns this json:
{
"ip": "x.xxx.xxx.xxx"
}
so I build my Specification as this
import dispatch._
import Defaults._
import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification
import org.specs2.matcher.MatcherMacros
import scala.language.experimental.macros
import scala.concurrent.duration._
class TestDispatchJSON extends Specification with MatcherMacros{
implicit val formats = DefaultFormats
case class Direction(ip: String)
val translateAPI = url("http://ip.jsontest.com/")
val response = Http( translateAPI OK as.String)
val direction = for(json <- response ) yield parse( json ).extract[Direction]
"The direction" should {
"direction must be of class Direction" in { implicit ee: ExecutionEnv =>
direction must matchA[Direction].ip("x.xxx.xxx.xxx").await(retries = 2, timeout = 10.seconds)
}
}
}
But it doesnt work, I get this error.
Testing started at 13:44 ...
13:44:41.170 [New I/O worker #1] DEBUG c.n.h.c.p.n.r.NettyConnectListener - Request using non cached Channel '[id: 0x702a0c8a, /172.16.10.142:5548 => ip.jsontest.com/64.233.184.121:80]':
DefaultHttpRequest(chunked: false)
GET / HTTP/1.1
Connection: keep-alive
Host: ip.jsontest.com
Accept: */*
User-Agent: Dispatch/0.11.3
13:44:41.335 [New I/O worker #1] DEBUG c.n.h.c.p.netty.handler.HttpProtocol -
Request DefaultHttpRequest(chunked: false)
GET / HTTP/1.1
Connection: keep-alive
Host: ip.jsontest.com
Accept: */*
User-Agent: Dispatch/0.11.3
Response DefaultHttpResponse(chunked: true)
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=ISO-8859-1
Vary: Accept-Encoding
Date: Thu, 18 Jun 2015 11:44:41 GMT
Server: Google Frontend
Cache-Control: private
Alternate-Protocol: 80:quic,p=0
Accept-Ranges: none
Transfer-Encoding: chunked
13:44:41.337 [New I/O worker #1] DEBUG c.n.h.c.p.n.channel.ChannelManager - Adding key: http://ip.jsontest.com:80 for channel [id: 0x702a0c8a, /172.16.10.142:5548 => ip.jsontest.com/64.233.184.121:80]
No usable value for $outer
Can't find ScalaSig for class java.lang.Object
org.json4s.package$MappingException: No usable value for $outer
Can't find ScalaSig for class java.lang.Object
at org.json4s.reflect.package$.fail(package.scala:96)
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:462)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$14.apply(Extraction.scala:482)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$14.apply(Extraction.scala:482)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
at scala.collection.AbstractTraversable.map(Traversable.scala:104)
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$instantiate(Extraction.scala:470)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$6.apply(Extraction.scala:515)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$6.apply(Extraction.scala:512)
at org.json4s.Extraction$.org$json4s$Extraction$$customOrElse(Extraction.scala:524)
at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:512)
at org.json4s.Extraction$.extract(Extraction.scala:351)
at org.json4s.Extraction$.extract(Extraction.scala:42)
at org.json4s.ExtractableJsonAstNode.extract(ExtractableJsonAstNode.scala:21)
at com.elevenpaths.TestDispatchJSON$$anonfun$1.apply(TestDispatchJSON.scala:35)
at com.elevenpaths.TestDispatchJSON$$anonfun$1.apply(TestDispatchJSON.scala:35)
at scala.util.Success$$anonfun$map$1.apply(Try.scala:236)
at scala.util.Try$.apply(Try.scala:191)
at scala.util.Success.map(Try.scala:236)
at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:121)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.pollAndExecAll(ForkJoinPool.java:1253)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1346)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: org.json4s.package$MappingException: Can't find ScalaSig for class java.lang.Object
at org.json4s.reflect.ScalaSigReader$.findClass(ScalaSigReader.scala:42)
at org.json4s.reflect.ScalaSigReader$.org$json4s$reflect$ScalaSigReader$$read$1(ScalaSigReader.scala:36)
at org.json4s.reflect.ScalaSigReader$.org$json4s$reflect$ScalaSigReader$$read$1(ScalaSigReader.scala:36)
at org.json4s.reflect.ScalaSigReader$.readField(ScalaSigReader.scala:38)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder$$anonfun$3.apply(Reflector.scala:66)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder$$anonfun$3.apply(Reflector.scala:65)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
at scala.collection.AbstractTraversable.map(Traversable.scala:104)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder.fields(Reflector.scala:65)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder.fields(Reflector.scala:78)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder.properties(Reflector.scala:82)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder.result(Reflector.scala:158)
at org.json4s.reflect.Reflector$.createDescriptor(Reflector.scala:50)
at org.json4s.reflect.Reflector$$anonfun$describe$1.apply(Reflector.scala:44)
at org.json4s.reflect.Reflector$$anonfun$describe$1.apply(Reflector.scala:44)
at org.json4s.reflect.package$Memo.apply(package.scala:39)
at org.json4s.reflect.Reflector$.describe(Reflector.scala:44)
at org.json4s.Extraction$.extract(Extraction.scala:349)
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:450)
... 30 more
The direction should
Process finished with exit code 0
I also want a good method to work with futures inside Specs2, beacause I do not like the ExecutionEnvironment, please add imports yo your answers
It looks like the json parsing itself doesn't work. The
No usable value for $outer
message indicates that reflection might not work withDirection
as an inner class of the Specification. So you should move it outside as a top-level class.