Reputation: 274
UPDATED: Method is returning type ANY rather than type Future[string]. Require return of type String.
I'm making a http request using the play.ws library 2.6. This was previously done with a curl request but this only uses basic authentication.
Below is my code and I'm trying to return a json string from this function to be deserialised in another method.
import java.io.{File, InputStream}
import java.nio.file.Paths
import javax.inject._
import org.apache.commons.io.FileUtils
import play.api._
import play.api.http.HttpEntity
import play.api.libs.ws._
import play.api.mvc._
import play.api.Play.current
import scala.collection.mutable.ListBuffer
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import sys.process._
@Singleton
class BuildService @Inject() (
ws: WSClient,
ec: ExecutionContext,
config: Configuration) {
def bbApiRequest(requestUrl: String, timeout: FiniteDuration):
Future[String] = {
val request = ws
.url(requestUrl)
.withAuth(
"user",
"pw1234",
WSAuthScheme.BASIC)
.get()
Await.result(request, timeout)
val returner = request.map(_.json)
} // <-- line 72 in below error points here.
}
When run it produces the error:
[error] C:\my_path\app\services\BuildService.scala:72: type mismatch;
[error] found : Unit
[error] required: scala.concurrent.Future[String]
[error] }
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[info] Compiling 1 Scala source to C:\my_path\restapi\target\scala-
2.12\classes...
[error] C:\my_path\restapi\app\services\BuildService.scala:72: type
mismatch;
[error] found : Unit
[error] required: scala.concurrent.Future[String]
[error] }
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
I'm trying to get ideally:
Appreciate any help!
Upvotes: 0
Views: 1547
Reputation: 274
The authorization can also be inputs into the function or retrieved from environment variables within the method (much easier to manage).
Simply needed to use .body on the Await call, which converts the output to generic type string.
package utils
import javax.inject._
import play.api._
import play.api.http.HttpEntity
import play.api.libs.ws._
import play.api.mvc._
import play.api.Play.current
import scala.collection.mutable.ListBuffer
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import sys.process._
@Singleton
class HTTPRequest @Inject() (
ws: WSClient,
ec: ExecutionContext,
config: Configuration) {
def bbApiRequest(requestUrl: String, timeout: FiniteDuration) = {
val request = ws
.url(requestUrl)
.withAuth(
"user",
"PW123",
WSAuthScheme.BASIC)
.get()
Await.result(request, timeout).body
}
}
Upvotes: 0
Reputation: 14803
Here is the function I use:
// first work with Futures the Play Controller will support that!
def bbApiRequest(requestUrl: String): Future[String] = {
// call the webservice with basic authentication
wsClient.url(requestUrl)
.withAuth("tester", "pwd123", WSAuthScheme.BASIC)
.get()
.map(checkStatus) // function that evaluates the HTTP Status
.map(_.json) // get the json
.map(Json.prettyPrint) // get it as string
}
I would create a case class
directly like:
.map(jsValue => handleJson(jsValue.validate[YourModel])) // or create a model of it (instead)
instead of .map(Json.prettyPrint)
Edit
Here an example of checkStatus
:
protected def checkStatus(resp: WSResponse): WSResponse = {
resp.status match {
case Status.OK => resp
case Status.NOT_FOUND => throw WebNotFoundException()
case Status.FORBIDDEN | Status.UNAUTHORIZED => throw WebAccessForbiddenException()
case Status.NOT_ACCEPTABLE => throw WebNotAcceptableException()
case _ => throw WebBadStatusException(resp.status + " - " + resp.statusText.toString)
}
}
The Exception are created by myself.
Upvotes: 1