playframework-2.6: not enough arguments for method apply: - scala

I am using Play-Framework-2.6 i am getting this error
/myproject/app/controllers/Application.scala:151: not enough
arguments for method apply: (data: akka.stream.scaladsl.Source[akka.util.ByteString, _], contentLength: Option[Long], contentType: Option[String])play.api.http.HttpEntity.Streamed in object Streamed.
[error] Unspecified value parameters contentLength, contentType.
[error] body = HttpEntity.Streamed(responseStream)
[error] ^
here is my code
def prometheusMetrics = Action {
val responseStream = Concurrent.unicast[Array[Byte]] { channel =>
val writer = new WriterAdapter(channel)
TextFormat.write004(writer, CollectorRegistry.defaultRegistry.metricFamilySamples())
writer.close()
}
Result(
header = ResponseHeader(200, Map.empty),
body = HttpEntity.Streamed(responseStream)
).as(TextFormat.CONTENT_TYPE_004)
}
i researched this but i did not find any suitable solution for it .please guide me
Update # 1
answer given by user #James Whiteley
after doing this
Result(
header = ResponseHeader(200, Map.empty),
body = HttpEntity.Streamed(responseStream, None, None)
).as(TextFormat.CONTENT_TYPE_004)
i am getting
type mismatch;
[error] found : play.api.libs.iteratee.Enumerator[Array[Byte]]{implicit val pec: scala.concurrent.ExecutionContext}
[error] required: akka.stream.scaladsl.Source[akka.util.ByteString, _]
[error] body = HttpEntity.Streamed(responseStream, None, None)

HttpEntity.Streamed seems to take three parameters, not one. Try
body = HttpEntity.Streamed(responseStream, None, None)
if you don't want to specify contentLength and contentType - these are optional parameters but still need to be defined.

Related

scala spark type mismatching

I need to group my rdd by two columns and aggregate the count. I have a function:
def constructDiagnosticFeatureTuple(diagnostic: RDD[Diagnostic])
: RDD[FeatureTuple] = {
val grouped_patients = diagnostic
.groupBy(x => (x.patientID, x.code))
.map(_._2)
.map{ events =>
val p_id = events.map(_.patientID).take(1).mkString
val f_code = events.map(_.code).take(1).mkString
val count = events.size.toDouble
((p_id, f_code), count)
}
//should be in form:
//diagnostic.sparkContext.parallelize(List((("patient", "diagnostics"), 1.0)))
}
At compile time, I am getting an error:
/FeatureConstruction.scala:38:3: type mismatch;
[error] found : Unit
[error] required: org.apache.spark.rdd.RDD[edu.gatech.cse6250.features.FeatureConstruction.FeatureTuple]
[error] (which expands to) org.apache.spark.rdd.RDD[((String, String), Double)]
[error] }
[error] ^
How can I fix it?
I red this post: Scala Spark type missmatch found Unit, required rdd.RDD , but I do not use collect(), so, it does not help me.

Found Option[CSVWriter] but required CSVWriter? `var` caused the issue?

The following code
var writers = new HashMap[String, CSVWriter]()
var writer = writers.get(pool)
if (writer == null) {
//writer = new CSVWriter(new FileWriter(s"..."))
writers.put(pool, writer) // Errr
}
Got the error of
[error] found : Option[au.com.bytecode.opencsv.CSVWriter]
[error] required: au.com.bytecode.opencsv.CSVWriter
[error] writers.put(pool, writer)
[error] ^
[error] one error found
Does var automatically add an Option wrapper? What I should do to put CSVWriter in the hashmap?
When a value is retrieved from a HashMap in scala using .get(key), the default returned value is of Option instance.
scala> val writers = collection.mutable.HashMap("abc" -> "def")
writers: scala.collection.mutable.HashMap[String,String] = Map(abc -> def)
scala> writers.get("abc")
res10: Option[String] = Some(def)
Option will return Some instance if the key exists in the HashMap and returns None if the key is not present.
scala> writers.get("a")
res13: Option[String] = None
This helps to avoid the nullpointer exceptions.
We need to get the real value using another get
scala> writers.get("abc").get
res11: String = def
But to be on the safe-side we can use getOrElse
scala> writers.getOrElse("abc", "no value")
res1: String = def
scala> writers.getOrElse("a", "no value")
res2: String = no value
I hope the explanation is clear

how to test action with multipart form data in play scala framework

I need an action method to receive file upload and I want to test this also. But my test is throwing error
My action:
def upload = Action.async(parse.multipartFormData) { request =>
val multipart = request.body
val optFile = multipart.files.toList.headOption.map(_.ref.file)
optFile match {
case None => Future.successful(Ok("got none"))
case Some(file) => Future.successful(Ok("got some"))
}
}
I want to test this method but getting error:
My test
"create notes" in {
val temp = SingletonTemporaryFileCreator.create("test", "png")
val tempFile = TemporaryFile(temp)
val filePart = FilePart[TemporaryFile](key = "image", filename = "debug.png", contentType = Some("image/png"), ref = tempFile)
val form = MultipartFormData(dataParts = Map(), files = Seq(filePart), badParts = Seq(), missingFileParts = Seq())
val notesController = new NotesController()
val result = notesController.upload().apply(FakeRequest(POST, "/notes/upload").withMultipartFormDataBody(form))
status(result) mustEqual OK
}
Error:
[error] found : play.api.libs.iteratee.Iteratee[Array[Byte],play.api.mvc.Result]
[error] required: scala.concurrent.Future[play.api.mvc.Result]
[error] status(result) mustEqual OK
[error] ^
[error] one error found
[error] (root/test:compileIncremental) Compilation failed

Scala specs2 mocking a trait method returns always Nullpointer exception

I have a trait that I want to mock and use that mocked Trait in another Service during testing. The problem is, that I receive a Nullpointerexception when I try to mock the return value of the indexDocuments function.
Testmethod:
"createDemand must return None if writing to es fails" in new WithApplication {
val demandDraft = DemandDraft(UserId("1"), "socken bekleidung wolle", Location(Longitude(52.468562), Latitude(13.534212)), Distance(30), Price(25.0), Price(77.0))
val es = mock[ElasticsearchClient]
val sphere = mock[SphereClient]
val productTypes = mock[ProductTypes]
sphere.execute(any[ProductCreateCommand]) returns Future.successful(product)
productTypes.demand returns ProductTypeBuilder.of("demand", ProductTypeDrafts.demand).build()
// this line throws the nullpointer exception
es.indexDocument(any[IndexName], any[TypeName], any[JsValue]) returns Future.failed(new RuntimeException("test exception"))
val demandService = new DemandService(es, sphere, productTypes)
demandService.createDemand(demandDraft) must be (Option.empty[Demand]).await
}
Trait:
sealed trait ElasticsearchClient {
implicit def convertListenableActionFutureToScalaFuture[T](x: ListenableActionFuture[T]): Future[T] = {
val p = Promise[T]()
x.addListener(new ActionListener[T] {
def onFailure(e: Throwable) = p.failure(e)
def onResponse(response: T) = p.success(response)
})
p.future
}
lazy val client = createElasticsearchClient()
def close(): Unit
def createElasticsearchClient(): Client
def indexDocument(esIndex: IndexName, esType: TypeName, doc: JsValue): Future[IndexResponse] =
client.prepareIndex(esIndex.value, esType.value).setSource(doc.toString()).execute()
def search(esIndex: IndexName, esType: TypeName, query: QueryBuilder): Future[SearchResponse] =
client.prepareSearch(esIndex.value).setTypes(esType.value).setQuery(query).execute()
}
Exception
[error] NullPointerException: (DemandServiceSpec.scala:89)
[error] services.DemandServiceSpec$$anonfun$1$$anonfun$apply$8$$anon$2$$anonfun$8.apply(DemandServiceSpec.scala:89)
[error] services.DemandServiceSpec$$anonfun$1$$anonfun$apply$8$$anon$2$$anonfun$8.apply(DemandServiceSpec.scala:89)
[error] services.DemandServiceSpec$$anonfun$1$$anonfun$apply$8$$anon$2.delayedEndpoint$services$DemandServiceSpec$$anonfun$1$$anonfun$apply$8$$anon$2$1(DemandServiceSpec.scala:89)
[error] services.DemandServiceSpec$$anonfun$1$$anonfun$apply$8$$anon$2$delayedInit$body.apply(DemandServiceSpec.scala:81)
[error] play.api.test.WithApplication$$anonfun$around$1.apply(Specs.scala:23)
[error] play.api.test.WithApplication$$anonfun$around$1.apply(Specs.scala:23)
[error] play.api.test.PlayRunners$class.running(Helpers.scala:49)
[error] play.api.test.Helpers$.running(Helpers.scala:403)
[error] play.api.test.WithApplication.around(Specs.scala:23)
[error] play.api.test.WithApplication.delayedInit(Specs.scala:20)
[error] services.DemandServiceSpec$$anonfun$1$$anonfun$apply$8$$anon$2.<init>(DemandServiceSpec.scala:81)
[error] services.DemandServiceSpec$$anonfun$1$$anonfun$apply$8.apply(DemandServiceSpec.scala:81)
[error] services.DemandServiceSpec$$anonfun$1$$anonfun$apply$8.apply(DemandServiceSpec.scala:81)
Please let me know if you need additional information.
I found out that the any[] Matchers in the indexDocuments call are the problem. When I replace them with the actual values it works:
"createDemand must return None if writing to es fails and deleteDemand should be called once with correct parameters" in new WithApplication {
val demandDraft = DemandDraft(UserId("1"), "socken bekleidung wolle", Location(Longitude(52.468562), Latitude(13.534212)), Distance(30), Price(25.0), Price(77.0))
val es = mock[ElasticsearchClient]
val sphere = mock[SphereClient]
val productTypes = mock[ProductTypes]
sphere.execute(any[ProductCreateCommand]) returns Future.successful(product)
sphere.execute(any[ProductDeleteByIdCommand]) returns Future.successful(product)
productTypes.demand returns ProductTypeBuilder.of("demand", ProductTypeDrafts.demand).build()
es.indexDocument(IndexName("demands"), TypeName("demands"), Json.toJson(demand)) returns Future.failed(new RuntimeException("test exception"))
val demandService = new DemandService(es, sphere, productTypes)
demandService.createDemand(demandDraft) must be (Option.empty[Demand]).await
}
I've had this happen a whole bunch and work around it by creating a class (rather than a trait) to feed to mock:
trait SomeTraitYouWantToMock {
…
}
class MockableSomeTraitYouWantToMock extends SomeTraitYouWantToMock
val whatever = mock[MockableSomeTraitYouWantToMock]

How to test file upload in Play 2.2.2?

I'm using Play 2.2.2 and have been unsuccessfully trying to add tests to my file upload functionality. I know there are plenty of questions about this, I have checked many but either they don't work or the API is deprecated and doesn't work or it fails with some spurious error.
This is how a valid request looks like from the browser (using Firefox's WebDeveloper plugin):
-----------------------------479326525221683770414613115
Content-Disposition: form-data; name="files[]"; filename="upload_aum_sample.csv"
Content-Type: text/csv
AccountName,AuM,Name
IX_CH1,10,A
IX_CH2,20,B
IX_CH3,30,C
IX_CH4,40,D
IX_CH5,50,E
IX_CH6,60,F
IX_CH7,70,G
IX_CH8,80,H
-----------------------------479326525221683770414613115--
This is what I have tried so far without success:
Compiles with a warning i.e. that routeAndCall is deprecated:
"upload file correctly" in new WithApplication {
val fileName = "upload_aum_sample.csv"
val file = getClass().getResource(fileName).getFile()
val data = MultipartFormData(Map(), List(FilePart("files[]", fileName, Some("text/csv"), file)), List(), List())
val result = routeAndCall(FakeRequest(POST, "/aum/upload/do", FakeHeaders(), data).withSession("username" -> "Test")).get
status(result) must equalTo(OK)
contentType(result) must beSome.which(_ == "application/json")
}
and results in the Exception:
[info] ! upload file correctly
[error] MatchError: <function1> (of class play.core.Router$Routes$$anon$4) (Helpers.scala:187)
[error] play.api.test.RouteInvokers$$anonfun$routeAndCall$1.apply(Helpers.scala:187)
[error] play.api.test.RouteInvokers$$anonfun$routeAndCall$1.apply(Helpers.scala:187)
[error] play.api.test.RouteInvokers$class.routeAndCall(Helpers.scala:187)
[error] AumUploadPageSpec.routeAndCall(AumUploadPageSpec.scala:30)
[error] play.api.test.RouteInvokers$class.routeAndCall(Helpers.scala:178)
[error] AumUploadPageSpec.routeAndCall(AumUploadPageSpec.scala:30)
[error] AumUploadPageSpec$$anonfun$12$$anon$3$delayedInit$body.apply(AumUploadPageSpec.scala:73)
[error] play.api.test.WithApplication$$anonfun$around$1.apply(Specs.scala:20)
[error] play.api.test.WithApplication$$anonfun$around$1.apply(Specs.scala:20)
[error] play.api.test.PlayRunners$class.running(Helpers.scala:45)
[error] play.api.test.Helpers$.running(Helpers.scala:364)
[error] play.api.test.WithApplication.around(Specs.scala:20)
[error] play.api.test.WithApplication.delayedInit(Specs.scala:17)
[error] AumUploadPageSpec$$anonfun$12$$anon$3.<init>(AumUploadPageSpec.scala:48)
[error] AumUploadPageSpec$$anonfun$12.apply(AumUploadPageSpec.scala:48)
[error] AumUploadPageSpec$$anonfun$12.apply(AumUploadPageSpec.scala:48)
Compiles fine no warnings
"upload file correctly" in new WithApplication {
val fileName = "upload_aum_sample.csv"
val file = getClass().getResource(fileName).getFile()
val data = MultipartFormData(Map(), List(FilePart("files[]", fileName, Some("text/csv"), file)), List(), List())
val result = controllers.Application.uploadDo("aum")(FakeRequest(POST, "/aum/upload/do", FakeHeaders(), data).withSession("username" -> "Test")).run
status(result) must equalTo(OK) // <<<<<<< test fails here
contentType(result) must beSome.which(_ == "application/json")
}
But the test fails due to the server responding 400 instead of 200 i.e. not OK
[info] x upload file correctly
[error] '400' is not equal to '200' (AumUploadPageSpec.scala:53)
UPDATE 1: If embed the file content rather than the file I still get the same errors i.e.
Change
val file = getClass().getResource(fileName).getFile()
to
val file = scala.io.Source.fromFile(getClass().getResource(fileName).getFile()).map(_.toByte).toArray
UPDATE 2: These are the routing and server side code respectively:
# Generic controllers
POST /:context/upload/do controllers.Application.uploadDo(context: String)
//------------------------------------------------------------------------
/**
* Action that uploads a file for a given context
* #param context the input context
*/
def uploadDo(context: String) = Action(parse.multipartFormData) { implicit request ⇒
request.body.file("files[]").map { file ⇒
val filename = file.filename
val contentType = file.contentType
}
Ok(Json.parse(
"""{"files": [
{
"name": "picture1.jpg",
"size": 902604,
"error": "Filetype not allowed"
},
{
"name": "picture2.jpg",
"size": 841946,
"error": "Filetype not allowed"
}
]}"""))
}
The top answer (irritatingly unaccepted) to this question solves my problem. I'm including it here for completeness.
trait FakeMultipartUpload {
case class WrappedFakeRequest[A](fr: FakeRequest[A]) {
def withMultipart(parts: (String, ContentBody)*) = {
// create a multipart form
val entity = new MultipartEntity()
parts.foreach { part =>
entity.addPart(part._1, part._2)
}
// serialize the form
val outputStream = new ByteArrayOutputStream
entity.writeTo(outputStream)
val bytes = outputStream.toByteArray
// inject the form into our request
val headerContentType = entity.getContentType.getValue
fr.withBody(bytes).withHeaders(CONTENT_TYPE -> headerContentType)
}
def withFileUpload(fileParam: String, file: File, contentType: String) = {
withMultipart(fileParam -> new FileBody(file, contentType))
}
}
implicit def toWrappedFakeRequest[A](fr: FakeRequest[A]) = WrappedFakeRequest(fr)
// override Play's equivalent Writeable so that the content-type header from the FakeRequest is used instead of application/octet-stream
implicit val wBytes: Writeable[Array[Byte]] = Writeable(identity, None)
}
#RunWith(classOf[JUnitRunner])
class AumUploadPageSpec extends PlaySpecification with FakeMultipartUpload {
//------------------------------------------------------------------------
"upload file correctly" in new WithApplication {
val fileName = "idxsrs_aum_2014-06-04.csv"
val uploadFile = new File(getClass().getResource(fileName).getPath())
val request = FakeRequest(POST, "/aum/upload/do").withFileUpload("files[]", uploadFile, "text/csv")
val response = route(request).get
status(response) must equalTo(OK)
contentType(response) must beSome.which(_ == "application/json")
}
}