events.request_success += test_success_handle TypeError: unsupported operand type(s) for +=: 'EventHook' and 'function' - locust

I am new to locust tool and trying to write the individual success and failure to console. Here is the error received during execution.
Error:
events.request_success += test_success_handle
TypeError: unsupported operand type(s) for +=: 'EventHook' and 'function'
Code:
from locust import events
hostname = socket.gethostname()
def test_success_handle(request_type, name, response_time, response_length, **kwargs):
SUCCESS_TEMPLATE = '[{"measurement": "%s","tags": {"hostname":"%s","requestName": "%s","requestType": "%s","status":"%s"' \
'},"time":"%s","fields": {"responseTime": "%s","responseLength":"%s"}' \
'}]'
json_string = SUCCESS_TEMPLATE % (
"ResponseTable", hostname, name, request_type, "success", datetime.datetime.now(tz=pytz.UTC), response_time,
response_length)
print(json_string)
def test_fail_handle(request_type, name, response_time, response_length, exception, **kwargs):
FAIL_TEMPLATE = '[{"measurement": "%s","tags": {"hostname":"%s","requestName": "%s","requestType": "%s","exception":"%s","status":"%s"' \
'},"time":"%s","fields": {"responseTime": "%s","responseLength":"%s"}' \
'}]'
json_string = FAIL_TEMPLATE % (
"ResponseTable", hostname, name, request_type, exception, "fail", datetime.datetime.now(tz=pytz.UTC),
response_time, response_length)
print(json_string)
events.request_success += test_success_handle()
events.request_failure += test_fail_handle()
Could you please help me.. Is there a another way to resolve the issue with latest version of locust. Thank you
In the code we added POST request and and trying to fire the event and send it to handler to display in the console.

Try to use event annotations, the latest stable version of locust implements a method for what you need to do: add_listener, see https://docs.locust.io/en/stable/api.html
from locust import events, HttpLocust
hostname = socket.gethostname()
#events.request_success.add_listener
def test_success_handle(request_type, name, response_time, response_length, **kwargs):
SUCCESS_TEMPLATE = '[{"measurement": "%s","tags": {"hostname":"%s","requestName": "%s","requestType": "%s","status":"%s"' \
'},"time":"%s","fields": {"responseTime": "%s","responseLength":"%s"}' \
'}]'
json_string = SUCCESS_TEMPLATE % (
"ResponseTable", hostname, name, request_type, "success", datetime.datetime.now(tz=pytz.UTC), response_time,
response_length)
print(json_string)
#events.request_failure.add_listener
def test_fail_handle(request_type, name, response_time, response_length, exception, **kwargs):
FAIL_TEMPLATE = '[{"measurement": "%s","tags": {"hostname":"%s","requestName": "%s","requestType": "%s","exception":"%s","status":"%s"' \
'},"time":"%s","fields": {"responseTime": "%s","responseLength":"%s"}' \
'}]'
json_string = FAIL_TEMPLATE % (
"ResponseTable", hostname, name, request_type, exception, "fail", datetime.datetime.now(tz=pytz.UTC),
response_time, response_length)
print(json_string)
class MyLocust(HttpLocust):
events.request_success.add_listener(individual_success_handle)
events.request_failure.add_listener(individual_fail_handle)

I think you need to lose the parentheses, and keep the methods outside the Locust class like this
from locust import events, HttpLocust
hostname = socket.gethostname()
def test_success_handle(request_type, name, response_time, response_length, **kwargs):
SUCCESS_TEMPLATE = '[{"measurement": "%s","tags": {"hostname":"%s","requestName": "%s","requestType": "%s","status":"%s"' \
'},"time":"%s","fields": {"responseTime": "%s","responseLength":"%s"}' \
'}]'
json_string = SUCCESS_TEMPLATE % (
"ResponseTable", hostname, name, request_type, "success", datetime.datetime.now(tz=pytz.UTC), response_time,
response_length)
print(json_string)
def test_fail_handle(request_type, name, response_time, response_length, exception, **kwargs):
FAIL_TEMPLATE = '[{"measurement": "%s","tags": {"hostname":"%s","requestName": "%s","requestType": "%s","exception":"%s","status":"%s"' \
'},"time":"%s","fields": {"responseTime": "%s","responseLength":"%s"}' \
'}]'
json_string = FAIL_TEMPLATE % (
"ResponseTable", hostname, name, request_type, exception, "fail", datetime.datetime.now(tz=pytz.UTC),
response_time, response_length)
print(json_string)
class MyLocust(HttpLocust):
events.request_success += test_success_handle
events.request_failure += test_fail_handle

In case someone is still looking at solution for this type of error:
With Locust 1.0+ version (I'm currently at 1.4.1) there is a new way of adding eventHooks.
Instead of:
events.request_success += test_success_handle
events.request_failure += test_fail_handle
Do this:
events.request_success.add_listener(test_success_handle)
events.request_failure.add_listener(test_fail_handle)
And make sure it is defined inside def __init__

Can you try the below code to register your callback functions:
# registering the hooks for success & error events in Locust lifecycle
locust.events.request_success += test_success_handle
locust.events.request_failure += test_fail_handle

Related

Spark Scala NoClassDefFoundError: org/apache/spark/Logging

I've checked a bunch of other forums and posts, but I can't seem to narrow down the issue. All I keep seeing is people saying not to use logging and how it's deprecated, but I don't even know where I'm using it in my code.
When I run the following code:
import org.apache.spark._
import org.apache.spark.streaming._
import org.apache.spark.streaming.twitter._
import twitter4j.Status
object TrendingHashTags {
def main(args: Array[String]): Unit = {
if (args.length < 8) {
System.err.println("Usage: TrendingHashTags <consumer key> <consumer secret> " +
"<access token> <access token secret> " +
"<language> <batch interval> <min-threshold> <show-count> " +
"[<filters>]")
System.exit(1)
}
val Array(consumerKey, consumerSecret, accessToken, accessTokenSecret,
lang, batchInterval, minThreshold, showCount ) = args.take(8)
val filters = args.takeRight(args.length - 8)
System.setProperty("twitter4j.oauth.consumerKey", consumerKey)
System.setProperty("twitter4j.oauth.consumerSecret", consumerSecret)
System.setProperty("twitter4j.oauth.accessToken", accessToken)
System.setProperty("twitter4j.oauth.accessTokenSecret", accessTokenSecret)
val conf = new SparkConf().setMaster(("local[4]")).setAppName("TrendingHashTags")
val ssc = new StreamingContext(conf, Seconds(batchInterval.toInt))
ssc.checkpoint("checkpoint")
val tweets = TwitterUtils.createStream(ssc, None, filters)
val tweetsFilteredByLang = tweets.filter{tweet => tweet.getLang() == lang}
val statuses = tweetsFilteredByLang.map{tweet => tweet.getText()}
val words = statuses.flatMap{status => status.split("""\s+""")}
val hashTags = words.filter{word => word.startsWith("#")}
val hashTagPairs = hashTags.map{hashtag => (hashtag, 1)}
val tagsWithCounts = hashTagPairs.updateStateByKey(
(counts: Seq[Int], prevCount: Option[Int]) =>
prevCount.map{c => c + counts.sum}.orElse{Some(counts.sum)}
)
val topHashTags = tagsWithCounts.filter { case (t, c) =>
c > minThreshold.toInt
}
val sortedTopHashTags = topHashTags.transform{rdd =>
rdd.sortBy({case(w, c) => c}, false)
}
sortedTopHashTags.print(showCount.toInt)
ssc.start()
ssc.awaitTermination()
}
}
I get the following error stack trace:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/spark/Logging
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.apache.spark.streaming.twitter.TwitterUtils$.createStream(TwitterUtils.scala:44)
at TrendingHashTags$.main(TrendingHashTags.scala:28)
at TrendingHashTags.main(TrendingHashTags.scala)
Caused by: java.lang.ClassNotFoundException: org.apache.spark.Logging
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
Here are my build.sbt contents:
name := "sparkStreaming"
version := "0.1"
scalaVersion := "2.11.12"
libraryDependencies ++= Seq("org.apache.spark" %% "spark-core" % "2.4.5",
"org.apache.spark" %% "spark-sql" % "2.4.5",
"org.apache.spark" %% "spark-streaming" % "2.4.5" % "provided",
"org.apache.spark" %% "spark-streaming-twitter" % "1.6.3")
Clear indication is, some where internally you are using lower version of spark... (spark 1.5 may be)
sbt inspect tree clean
you can check with this.
for maven users mvn depdency:tree will give all the dependencies used list
One more thing is you are using
"org.apache.spark" %% "spark-streaming" % "2.4.5" % "provided",
change it to default maven scope compile and see.
similar quetion and answers here

Running http4s server with ZIO Env

Trying to learn using ZIO library, so I decided to create a basic web service app. Idea pretty basic, use http4s lib for server and route endpoints, print "hello world" on endpoint call.
With the help of docs and examples I found, produces code:
object Main extends ManagedApp {
type AppEnvironment = Clock with Console with HelloRepository
type AppTask[A] = RIO[AppEnvironment, A]
override def run(args: List[String]): ZManaged[ZEnv, Nothing, Int] = {
val httpApp: HttpApp[AppTask] = Router[AppTask]("/" -> helloWorldService).orNotFound
val server = ZIO.runtime[AppEnvironment].flatMap { implicit rts =>
BlazeServerBuilder[AppTask]
.bindHttp(8080, "0.0.0.0")
.withHttpApp(CORS(httpApp))
.serve
.compile[AppTask, AppTask, ExitCode]
.drain
}
(for {
_ <- ZManaged.environment[ZEnv] >>> server.toManaged_
} yield ())
.foldM(err => putStrLn(s"Execution failed with: $err").as(1).toManaged_, _ => ZManaged.succeed(0))
}
val dsl: Http4sDsl[AppTask] = Http4sDsl[AppTask]
import dsl._
val helloWorldService: HttpRoutes[AppTask] = HttpRoutes.of[AppTask] {
case GET -> Root / "hello" / name => Ok(Repo.getHello(name))
}
}
trait HelloRepository extends Serializable {
val helloRepository: HelloRepository.Service[Any]
}
object HelloRepository extends Serializable {
trait Service[R] extends Serializable {
def getHello(name: String): ZIO[R, Nothing, String]
}
}
object Repo extends HelloRepository.Service[HelloRepository] {
override def getHello(name: String): ZIO[HelloRepository, Nothing, String] = ZIO.succeed(s"Hello $name")
}
I create router: Router[AppTask]("/" ...
I create server: ZIO.runtime[AppEnvironment].flatMap ...
Then trying to start server with ZIO enviroment,
but something I am missing as this line:
_ <- ZManaged.environment[ZEnv] >>> server.toManaged_
is incorected, and throws error on build:
Error:(34, 39) inferred type arguments [touch.Main.AppEnvironment,Throwable,Unit] do not conform to method >>>'s type parameter bounds [R1 >: zio.ZEnv,E1,B]
_ <- ZManaged.environment[ZEnv] >>> server.toManaged_
Error:(34, 39) inferred type arguments [touch.Main.AppEnvironment,Throwable,Unit] do not conform to method >>>'s type parameter bounds [R1 >: zio.ZEnv,E1,B]
Error:(34, 50) type mismatch;
found : zio.ZManaged[touch.Main.AppEnvironment,Throwable,Unit]
(which expands to) zio.ZManaged[zio.clock.Clock with zio.console.Console with touch.HelloRepository,Throwable,Unit]
required: zio.ZManaged[R1,E1,B]
maybe someone can help me with the correct syntax?
also would appriacete some explanation, or link to docs, where this is explained.
I would like to explain more but I don't know where you got your code sample or what your build.sbt looks like but I happen to have some http4s code lying around so I took the liberty of adding some import statements and simplifying it a bit. You can always add back the complexity I took out.
Here's what worked for me.
/tmp/http4s/test.scala
import org.http4s.implicits._
import org.http4s.server.blaze._
import org.http4s.server.Router
import org.http4s.server.middleware.CORS
import org.http4s._
import org.http4s.dsl.Http4sDsl
import zio._
import zio.clock._
import zio.console._
import zio.interop.catz._
trait HelloRepository
{
def getHello(name: String): ZIO[AppEnvironment, Nothing, String]
}
trait AppEnvironment extends Console with Clock
{
val helloRepository: HelloRepository
}
object Main extends App {
type AppTask[A] = RIO[AppEnvironment, A]
val dsl: Http4sDsl[AppTask] = Http4sDsl[AppTask]
import dsl._
val httpApp: HttpApp[AppTask] = Router[AppTask](
"/" -> HttpRoutes.of[AppTask] {
case GET -> Root / "hello" / name => Ok( ZIO.accessM[AppEnvironment](_.helloRepository.getHello(name)) )
}
).orNotFound
val program = for {
server <- ZIO.runtime[AppEnvironment]
.flatMap {
implicit rts =>
BlazeServerBuilder[AppTask]
.bindHttp(8080, "0.0.0.0")
.withHttpApp(CORS(httpApp))
.serve
.compile
.drain
}
} yield server
val runEnv = new AppEnvironment with Console.Live with Clock.Live
{
val helloRepository = new HelloRepository
{
def getHello(name: String): ZIO[AppEnvironment, Nothing, String] = ZIO.succeed(s"Hello $name")
}
}
def run(args: List[String]) =
program
.provide(runEnv)
.foldM(err => putStrLn(s"Execution failed with: $err") *> ZIO.succeed(1), _ => ZIO.succeed(0))
}
/tmp/http4s/build.sbt
val Http4sVersion = "0.20.0"
val CatsVersion = "2.0.0"
val ZioCatsVersion = "2.0.0.0-RC3"
val ZioVersion = "1.0.0-RC13"
val LogbackVersion = "1.2.3"
lazy val root = (project in file("."))
.settings(
organization := "example",
name := "example",
version := "0.0.1-SNAPSHOT",
scalaVersion := "2.12.8",
scalacOptions ++= Seq("-Ypartial-unification"),
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-effect" % CatsVersion,
"dev.zio" %% "zio" % ZioVersion,
"dev.zio" %% "zio-interop-cats" % ZioCatsVersion,
"org.http4s" %% "http4s-blaze-server" % Http4sVersion,
"org.http4s" %% "http4s-dsl" % Http4sVersion,
"ch.qos.logback" % "logback-classic" % LogbackVersion,
),
addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.6"),
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.2.4")
)
scalacOptions ++= Seq(
"-deprecation", // Emit warning and location for usages of deprecated APIs.
"-encoding", "UTF-8", // Specify character encoding used by source files.
"-language:higherKinds", // Allow higher-kinded types
"-language:postfixOps", // Allows operator syntax in postfix position (deprecated since Scala 2.10)
"-feature", // Emit warning and location for usages of features that should be imported explicitly.
"-Ypartial-unification", // Enable partial unification in type constructor inference
"-Xfatal-warnings", // Fail the compilation if there are any warnings
)
sample execution
bash-3.2$ cd /tmp/http4s
bash-3.2$ sbt
...
sbt:example> compile
...
[info] Done compiling.
[success] Total time: 5 s, completed Oct 24, 2019 11:20:53 PM
sbt:example> run
...
[info] Running Main
23:21:03.720 [zio-default-async-1-163838348] INFO org.http4s.blaze.channel.nio1.NIO1SocketServerGroup - Service bound to address /0:0:0:0:0:0:0:0:8080
23:21:03.725 [blaze-selector-0] DEBUG org.http4s.blaze.channel.nio1.SelectorLoop - Channel initialized.
23:21:03.732 [zio-default-async-1-163838348] INFO org.http4s.server.blaze.BlazeServerBuilder -
_ _ _ _ _
| |_| |_| |_ _ __| | | ___
| ' \ _| _| '_ \_ _(_-<
|_||_\__|\__| .__/ |_|/__/
|_|
23:21:03.796 [zio-default-async-1-163838348] INFO org.http4s.server.blaze.BlazeServerBuilder - http4s v0.20.0 on blaze v0.14.0 started at http://[0:0:0:0:0:0:0:0]:8080/
23:21:11.070 [blaze-selector-1] DEBUG org.http4s.blaze.channel.nio1.SelectorLoop - Channel initialized.
23:21:11.070 [blaze-selector-1] DEBUG org.http4s.blaze.channel.nio1.NIO1HeadStage - Starting up.
23:21:11.070 [blaze-selector-1] DEBUG org.http4s.blaze.channel.nio1.NIO1HeadStage - Stage NIO1HeadStage sending inbound command: Connected
23:21:11.070 [blaze-selector-1] DEBUG org.http4s.server.blaze.Http1ServerStage$$anon$1 - Starting HTTP pipeline
23:21:11.072 [blaze-selector-1] DEBUG org.http4s.blazecore.IdleTimeoutStage - Starting idle timeout stage with timeout of 30000 ms
At this point after opening http://localhost:8080/hello/there I observed the expected output in the browser.
Hope this helps.

Slick with PostgreSQL Scala SBT Intellij IDEA

I am trying to create a project with Slick in Intellij IDEA with PostgreSQL driver. But I have managed to find only this tutorial
I followed it, but I have got an error:
Exception in thread "main" java.lang.ExceptionInInitializerError
at Main.main(Main.scala)
Caused by: com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'url'
Here is my code for the main class:
import scala.slick.driver.PostgresDriver.simple._
object Main {
case class Song(
id: Int,
name: String,
singer: String)
class SongsTable(tag: Tag) extends Table[Song](tag, "songs") {
def id = column[Int]("id")
def name = column[String]("name")
def singer = column[String]("singer")
def * = (id, name, singer) <> (Song.tupled, Song.unapply)
}
lazy val songsTable = TableQuery[SongsTable]
val db = Database.forConfig("scalaxdb")
def main(args: Array[String]): Unit = {
val connectionUrl = "jdbc:postgresql://localhost/songs?user=postgres&password=postgresp"
Database.forURL(connectionUrl, driver = "org.postgresql.Driver") withSession {
implicit session =>
val songs = TableQuery[SongsTable]
songs.list foreach { row =>
println("song with id " + row.id + " has name " + row.name + " and a singer is " + row.singer)
}
}
}
}
These is application.conf file:
scalaxdb = {
dataSourceClass = "slick.jdbc.DatabaseUrlDataSource"
properties = {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://localhost/dbname?user=user&password=password"
}
}
And this is build.sbt:
libraryDependencies ++= Seq(
"org.postgresql" % "postgresql" % "9.3-1100-jdbc4",
"com.typesafe.slick" %% "slick" % "2.1.0",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
I can not figure out what I am doing wrong. I would be very grateful for any advice on fixing this.
Don't you mind to use a little more up-to-date version of Slick?
import slick.jdbc.PostgresProfile.api._
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
object Main {
case class Song(
id: Int,
name: String,
singer: String)
class SongsTable(tag: Tag) extends Table[Song](tag, "songs") {
def id = column[Int]("id")
def name = column[String]("name")
def singer = column[String]("singer")
def * = (id, name, singer) <> (Song.tupled, Song.unapply)
}
val db = Database.forConfig("scalaxdb")
val songs = TableQuery[SongsTable]
def main(args: Array[String]): Unit = {
Await.result({
db.run(songs.result).map(_.foreach(row =>
println("song with id " + row.id + " has name " + row.name + " and a singer is " + row.singer)))
}, 1 minute)
}
}
build.sbt
scalaVersion := "2.12.4"
libraryDependencies += "com.typesafe.slick" %% "slick" % "3.2.1"
libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.25"
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % "3.2.1"
libraryDependencies += "org.postgresql" % "postgresql" % "42.1.4"

Error in sending data as multi form data in play /scala

This is my code the same code is working in play 2.1.5 but I am unable to create war file in play 2.1.5 so I switched to play 2.4.3 and now in response it is coming that 400 bad request client is sending wrong syntactically even post rest api is not hitting. Can some tell me what I am missing?
import play.api._
import play.api.libs.ws._
import play.api.mvc._
//import javax.inject.Inject
import play.api.Play.current
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.libs.ws.WSAuthScheme
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
import org.apache.commons.codec.binary.Base64.encodeBase64
class Application extends Controller {
def index = Action {
Ok(views.html.index("Your new application is ready."))
}
def postUpload=Action(parse.multipartFormData){request=>
val groupingType= request.body.dataParts("Grouping type").mkString
val email=request.body.dataParts("NotificationRecepients").mkString
val custId=request.body.dataParts("CustomerId").mkString
val custIdFinal:Int=custId.toInt
request.body.file("file").map { file =>
val file1=file.ref.file.getAbsolutePath;
val fileName = file.filename
val contentType = file.contentType
//file.ref.moveTo(new File("/home/kanchan/Desktop/"+fileName),true)
val user = "myUser";
val password = "myPassword";
val encodedCredentials =
new String(encodeBase64("%s:%s".format(user, password).getBytes))
val asyncHttpClient:AsyncHttpClient =WS.client.underlying
val postBuilder = asyncHttpClient.preparePost(url)
val builder = postBuilder
.addHeader("Authorization", "Basic " + encodedCredentials)
.addBodyPart(new StringPart("selectedGroupType", "Functional Grouping", "UTF-8"))
.addBodyPart(new StringPart("mailRecipients", "kancgupt#cisco.com", "UTF-8"))
.addBodyPart(new StringPart("selectedFile", "Sample_group_upload_file.xlsx", "UTF-8"))
.addBodyPart(new FilePart("file",new File("/home/kanchan/Downloads/Sample_group_upload_file.xlsx")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}.getOrElse {
Ok( "Missing file")
}
}
}
Play version 2.4.3
sbt:0.13.8
getting following error:
Apache Tomcat/6.0.39 - Error report HTTP Status 400 - Bad Requesttype Status reportmessage Bad Requestdescription The request sent by the client was syntactically incorrect.Apache Tomcat/6.0.39
You describing something really strange. I took your code, curl, REST server echo (http://httpbin.org, exactly http://httpbin.org/post url), create new play-scala application with the 2.4.3 play. It works like a charm.
Code:
package controllers
import play.api._
import play.api.libs.ws._
import play.api.mvc._
import play.api.Play.current
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.libs.ws.WSAuthScheme
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
import org.apache.commons.codec.binary.Base64.encodeBase64
class Original extends Controller {
def postUpload = Action(parse.multipartFormData) { request =>
val groupingType = request.body.dataParts("Groupingtype").mkString
val email = request.body.dataParts("NotificationRecepients").mkString
val custId = request.body.dataParts("CustomerId").mkString
val custIdFinal: Int = custId.toInt
request.body.file("file").map { file =>
val file1 = file.ref.file.getAbsolutePath;
val fileName = file.filename
val contentType = file.contentType
val url = "http://httpbin.org/post"
val user = "myUser";
val password = "myPassword";
val encodedCredentials =
new String(encodeBase64("%s:%s".format(user, password).getBytes))
val asyncHttpClient: AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost(url)
val builder = postBuilder
.addHeader("Authorization", "Basic " + encodedCredentials)
.addBodyPart(new StringPart("selectedGroupType", groupingType, "UTF-8"))
.addBodyPart(new StringPart("mailRecipients", email, "UTF-8"))
.addBodyPart(new StringPart("selectedFile", fileName, "UTF-8"))
.addBodyPart(new FilePart("file", new File(file1)))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}.getOrElse {
Ok("Missing file")
}
}
}
curl command (from the project root folder):
curl -i -X POST \
-H "Content-Type:multipart/form-data" \
-F "Groupingtype=Groupingtype" \
-F "NotificationRecepients=NotificationRecepients" \
-F "CustomerId=123" \
-F "file=#app/controllers/Application.scala" \
'http://localhost:9000/post'
curl response:
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Tue, 06 Oct 2015 18:38:11 GMT
Content-Length: 3122
{
"args": {},
"data": "",
"files": {
"file": "package controllers..."
},
"form": {
"mailRecipients": "NotificationRecepients",
"selectedFile": "Application.scala",
"selectedGroupType": "Groupingtype"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic bXlVc2VyOm15UGFzc3dvcmQ=",
"Content-Length": "3215",
"Content-Type": "multipart/form-data; boundary=2EmAF3UE9xSuA6KQpUS3q-Ohzkp0f_7-8",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.111",
"url": "http://httpbin.org/post"
}
Try to create new simple project and use my code - then migrate yours in to this new project - maybe you will find something. It could be some wrong migration steps from 2.1.5 or so.
my build.sbt
name := """scala-send-multipart-clean"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.6"
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test
)
resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
// Play provides two styles of routers, one expects its actions to be injected, the
// other, legacy style, accesses its actions statically.
routesGenerator := InjectedRoutesGenerator
my project/plugins.sbt
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.3")
// web plugins
addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.0.6")
addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.3")
addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.7")
addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0")
my project/build.properties
#Activator-generated Properties
#Wed Oct 07 00:44:35 EEST 2015
template.uuid=7da33b5a-3aef-4d2e-b318-dae93632b999
sbt.version=0.13.8
java version "1.8.0_40", updated to the "build 1.8.0_60-b27" - no difference.
I am getting this [StringPart name=selectedGroupType contentType=UTF-8
charset=US-ASCII tranferEncoding=8bit contentId=null
dispositionType=null, StringPart name=mailRecipients contentType=UTF-8
charset=US-ASCII tranferEncoding=8bit contentId=null
dispositionType=null, StringPart name=selectedFile contentType=UTF-8
charset=US-ASCII tranferEncoding=8bit contentId=null
dispositionType=null, FilePart name=file
contentType=application/octet-stream charset=null
tranferEncoding=binary contentId=null dispositionType=null
filename=Sample_group_upload_file.xlsx]
It is the way toString is realised in the Parts. That's all, it does not tell something about "correct" or "not correct".
My results for
println(builder.build().getParts())
is
[StringPart name=selectedGroupType contentType=UTF-8 charset=US-ASCII tranferEncoding=8bit contentId=null dispositionType=null, StringPart name=mailRecipients contentType=UTF-8 charset=US-ASCII tranferEncoding=8bit contentId=null dispositionType=null, StringPart name=selectedFile contentType=UTF-8 charset=US-ASCII tranferEncoding=8bit contentId=null dispositionType=null, FilePart name=file contentType=application/octet-stream charset=null tranferEncoding=binary contentId=null dispositionType=null filename=multipartBody1697314279257602964asTemporaryFile]
As you see it very similar to yours, but if you will output names and values for the string part, I am pretty sure you will receive both:
import scala.collection.JavaConversions._
...
builder.build().getParts().map{ part =>
if(part.isInstanceOf[StringPart]){
val stringPart: StringPart = part.asInstanceOf[StringPart]
println(stringPart.getName() + ":" + stringPart.getValue())
}
}
results:
selectedGroupType:Groupingtype
mailRecipients:NotificationRecepients
selectedFile:Application.scala

Why does spray-can server not respond to a http request?

I'm trying to set a very basic HTTP server using spray-can. If I call the endpoint I've set a mapping for, I'm getting a timeout (although using a debugger I can see that the actor receives the message).
My source looks like this:
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.io.IO
import spray.can.Http
import spray.http.{HttpMethods, HttpRequest, HttpResponse, Uri}
class App extends Actor {
implicit val system = context.system
override def receive = {
case "start" =>
val listener: ActorRef = system.actorOf(Props[HttpListener])
IO(Http) ! Http.Bind(listener, interface = "localhost", port = 8080)
}
}
class HttpListener extends Actor {
def receive = {
case _: Http.Connected =>
sender() ! Http.Register(self)
case HttpRequest(HttpMethods.GET, Uri.Path("/ping"), _, _, _) =>
HttpResponse(entity = "PONG")
}
}
object Main {
def main(args: Array[String]) {
val system = ActorSystem("my-actor-system")
val app: ActorRef = system.actorOf(Props[App], "app")
app ! "start"
}
}
Executing run shows:
> run
[info] Running Main
[INFO] [09/10/2014 21:33:38.839] [my-actor-system-akka.actor.default-dispatcher-3] [akka://my-actor-system/user/IO-HTTP/listener-0] Bound to localhost/127.0.0.1:8080
The following HTTP/1.1 500 Internal Server Error shows up when I hit http://localhost:8080/ping:
➜ ~ curl --include http://localhost:8080/ping
HTTP/1.1 500 Internal Server Error
Server: spray-can/1.3.1
Date: Wed, 10 Sep 2014 19:34:08 GMT
Content-Type: text/plain; charset=UTF-8
Connection: close
Content-Length: 111
Ooops! The server was not able to produce a timely response to your request.
Please try again in a short while!
My build.sbt looks like:
scalaVersion := "2.11.2"
resolvers += "spray repo" at "http://repo.spray.io"
libraryDependencies ++= Seq(
"io.spray" %% "spray-can" % "1.3.1",
"io.spray" %% "spray-routing" % "1.3.1",
"com.typesafe.akka" %% "akka-actor" % "2.3.5"
)
Any ideas on what I'm doing wrong?
case HttpRequest(HttpMethods.GET, Uri.Path("/ping"), _, _, _) =>
HttpResponse(entity = "PONG")
should be
case HttpRequest(HttpMethods.GET, Uri.Path("/ping"), _, _, _) =>
sender ! HttpResponse(entity = "PONG")
You are returning HttpResponse instead of sending a message to the sender.