How to use a standalone WSClient in a Scala application - scala

I would like to use ws in a standalone application. Trying this code, copied from https://gist.github.com/cdimascio/46b2b7d2986636c1189c :
import com.ning.http.client.AsyncHttpClientConfig
import play.api.libs.ws.ning._
import play.api.libs.ws._
// provide an execution context
import scala.concurrent.ExecutionContext.Implicits.global
object WSStandaloneTest {
def main(args: Array[String]) {
// set up the client
val config = new NingAsyncHttpClientConfigBuilder(DefaultWSClientConfig()).build
val builder = new AsyncHttpClientConfig.Builder(config)
val client = new NingWSClient(builder.build)
// execute a GET request
val response = client.url("http://www.example.com").get
// print the response body
response.foreach(r => {
println(r.body)
// not the best place to close the client,
// but it ensures we dont close the threads before the response arrives
// Good enough for the gist :-D
client.close()
})
}
}
Results in the following error:
[error] object ning is not a member of package play.api.libs.ws
[error] import play.api.libs.ws.ning._
In my build.sbt I have this:
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.1"
libraryDependencies += "com.typesafe.play" %% "play-ws" % "2.6.1"
What am I doing wrong?

NingWSClient is deprecated in Play! 2.5.x.
In 2.6.x
The ning package has been replaced by the ahc package, and the Ning* classes replaced by AHC*.
There is a migration guide available in the official doc.
So you can choose to downgrade to 2.5.x and use ning or update the code.

Related

Hazelcast server with scala client issue

I am trying to setup hazelcast server and client on my local machine. I am also trying to connect to local Hazelcast server by scala-client.
For server I used below code,
import com.hazelcast.config._
import com.hazelcast.Scala._
object HazelcastServer {
def main(args: Array[String]): Unit = {
val conf = new Config
serialization.Defaults.register(conf.getSerializationConfig)
serialization.DynamicExecution.register(conf.getSerializationConfig)
val hz = conf.newInstance()
val cmap = hz.getMap[String, String]("test")
cmap.put("a","A")
cmap.put("b","B")
}
}
and hazelcast client as,
import com.hazelcast.Scala._
import client._
import com.hazelcast.client._
import com.hazelcast.config._
object Hazelcast_Client {
def main(args:Array[String]): Unit = {
val conf = new Config
serialization.Defaults.register(conf.getSerializationConfig)
serialization.DynamicExecution.register(conf.getSerializationConfig)
val hz = conf.newClient()
val cmap = hz.getMap("test")
println(cmap.size())
}
}
In my build.sbt,
libraryDependencies += "com.hazelcast" % "hazelcast" % "3.7.2"
libraryDependencies += "com.hazelcast" %% "hazelcast-scala" % "3.7.2"
I am getting below error and stuck in dependency issues.
Symbol 'type <none>.config.ClientConfig' is missing from the classpath.
[error] This symbol is required by 'value com.hazelcast.Scala.client.package.conf'.
[error] Make sure that type ClientConfig is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'package.class' was compiled against an incompatible version of <none>.config.
[error] val conf = new Config
I referred hazelcast documentation. I am not able to find any good hazelcast scala examples to understand the setup and to start playing with. If anybody can help in solving this issue, or share really good scala examples that would be helpful.
I've done a Scala+Akka Hazelcast before. My build.sbt included
libraryDependencies += "com.hazelcast" % "hazelcast-all" % "3.7.2"
I seem to remember that hazelcast-all was required.

unable to use WS.url() in Play app tutorial

I am doing a tutorial for Play framework with Scala. I am quite early into the tutorial and i am having a problem with ws. In my class WS is not recognized although that says to use WS.url("url-here") and to import play.api.libs._ which i have done both. I have also tried using ws.url("url-here") as well... and here wsis recognized but after that i get a "can't resolve symbol 'url'". Here is my build.sbt:
name := """play_hello"""
organization := "x.x"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.12.3"
libraryDependencies ++= Seq(
"org.scalatestplus.play" %% "scalatestplus-play" % "3.1.2" % Test,
"com.ning" % "async-http-client" % "1.9.29",
guice,
ws
)
And here is the code for my class:
package controllers
import javax.inject.Inject
import com.ning.http.client.oauth.{ConsumerKey, RequestToken}
import play.api.Play.current
import play.api.libs._
import play.api.mvc._
import scala.concurrent.Future
class Application #Inject()(cc: ControllerComponents) extends
AbstractController(cc){
def tweets = Action.async{
credentials.map { case (consumerKey, requestToken) =>
WS.url("http://stream.twitter.com")
Future.successful{
Ok
}
}getOrElse{
Future.successful{
InternalServerError("Twitter credentials are missing!")
}
}
}
def credentials: Option[(ConsumerKey, RequestToken)] = for{
apiKey <- current.configuration.getString("twitter.apiKey")
apiSecret <- current.configuration.getString("twitter.apiSecret")
token <- current.configuration.getString("twitter.token")
tokenSecret <- current.configuration.getString("twitter.tokenSecret")
}yield (
new ConsumerKey(apiKey, apiSecret),
new RequestToken(token, tokenSecret)
)
}
I Figure that most likely this is some type of problem with a dependency conflict. Here is a screenshot of ws related libraries in project structure. I would appreciate any help in finding a solution to this. Thank you.
The solution was to add ws: WSClient to the parameters of Application class constructor. Apperently standalone WS object has been removed in more recent versions of ws library.
class Application #Inject()(cc: ControllerComponents, ws: WSClient) extends AbstractController(cc)
Now i can use:
ws.url("https://stream.twitter.com/1.1/statuses/filter.json")
Also according to the documentation on play website if you for some reason can not use an injected WSClient, then you can create an instance of one and use that.

Get content from Akka ResponseEntity in Scala

I do a GET HTTP call to a rest service which returns a json. I would like to parse the json to a scala object but here I got stuck. I am using the Akka api and I can't manage to retrieve the content from the Akka's ResponseEntity
Here is my sbt file:
name := "ScalaHttp"
version := "1.0"
scalaVersion := "2.11.8"
libraryDependencies ++={
val akkaV = "2.4.5"
Seq(
"com.typesafe.akka" %% "akka-http-core" % akkaV,
"com.typesafe.play" %% "play-json" % "2.4.0-M3"
)
}
And here is the app
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpRequest
import akka.stream.ActorMaterializer
import scala.concurrent.ExecutionContext.Implicits.global
object Sender {
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
Http().singleRequest(HttpRequest(uri = "http://declinators.com/declinator?noun=komunikacja")) foreach {
y => println(y.entity)
println(y.entity.getContentType())
println(y.entity.contentType)
}
}
}
This prints:
HttpEntity.Strict(application/json,{"nominative":"komunikacja","genitive":"komunikacji","dative":"komunikacji","accusative":"komunikacjÄ™","instrumental":"komunikacjÄ…","locative":"komunikacji","vocative":"komunikacjo"})
application/json
application/json
Here come the questions:
1. Why ResponseEntity supplies getContentType() and contentType()? They return the same thing.
2. Getting the contentyType is easy, you have two ways for doing it, but how can I get the content itself, so I can play (i.e. parse it using play) with the json!
You can use entity.data.toString for Binary content type, or the following code piece
data.decodeString(nb.charset.value)
Please follow the HttpEntity.Strict.toString implementation here for detail:
https://github.com/akka/akka/blob/master/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpEntity.scala#L316

Play: How to Create a Fake Request in Production Code

FakeRequest comes from artifact play-test and is added to the project only in the test scope... but I need to create a kind of fake request just to invoke a method that takes an implicit RequestHeader:
import play.api.test._
...
implicit val request = FakeRequest(
Helpers.POST,
controllers.routes.auth.Users.triggerPasswordReset(superuser.email.get).url,
FakeHeaders(),
""
)
// createToken takes an implict RequestHeader
createToken(TokenType.Reset, account).map { token =>
EmailHelper.sendPasswordResetEmail(user.email.get, token.asJwt)
...
}
How do I import FakeRequest in the compile scope? Is there a better option? Or shall I invoke the controller's method directly?
Add the following to your Build.sbt
libraryDependencies ++= Seq(
"com.typesafe.play" %% "play-test" % "2.2.1" % "compile"
)
Make sure to change "2.2.1" to be whatever version of Play your are using.
This should expose the play test classes to the compile scope.
Cheers!

How to make Squeryl work with the Play! Framework?

I'm trying to learn how to make a simple database app with Play and Squeryl. I've made the Tasks app from the Play tutorial, but I want to change the model / schema so that it uses Squeryl instead of Anorm. I've been looking at different tutorials, examples and answers, but I haven't really figured out how to do this.
So, given the source code from the Play Tutorial (ScalaTodoList); how do I proceed to make it work with Squeryl?
More specifically:
How do I implement the all(), create(), and delete() methods in my model? (I'd like to use auto-incrementing ID's for the Tasks)
Which database adapter to use is currently hard coded in Build.scala and Global.scala (see below). How can I make it such that it automatically uses H2 for dev/testing and Postgres on Heroku, like it does for Anorm in the Play tutorial?
How do I make sure that it automatically creates my tables?
This is what I've done thus far
I've completed the Play ScalaTodoList Tutorial.
In project/Build.scala, object ApplicationBuild, I've added the dependencies:
// From the "Squeryl Getting Started tutorial"
val posgresDriver = "postgresql" % "postgresql" % "8.4-702.jdbc4"
val h2 = "com.h2database" % "h2" % "1.2.127"
// From the "Squeryl Getting Started tutorial"
libraryDependencies ++= Seq(
"org.squeryl" %% "squeryl" % "0.9.5",
h2
)
// From the Play tutorial
val appDependencies = Seq(
// Add your project dependencies here,
"org.squeryl" %% "squeryl" % "0.9.5", // Copied from above so that it compiles (?)
"postgresql" % "postgresql" % "8.4-702.jdbc4"
)
added app/Global.scala (taken from the SO answer mentioned above, just changed the adapter to H2):
import play.db.DB
import play.api.Application
import play.api.GlobalSettings
import org.squeryl._
import org.squeryl.adapters._
object Global extends GlobalSettings {
override def onStart(app: Application): Unit =
{
SessionFactory.concreteFactory = Some(
() => Session.create(DB.getDataSource().getConnection(),
dbAdapter));
}
override def onStop(app: Application): Unit =
{
}
val dbAdapter = new H2Adapter(); // Hard coded. Not good.
}
in app/models/Task.scala I've added imports and removed the Anorm implemetations in all(), create(), and delete().
The controller from the Play tutorial expects the all() method to return List[Task].
import org.squeryl.PrimitiveTypeMode._
import org.squeryl.Schema
import org.squeryl.annotations.Column
case class Task(id: Long, label: String)
object Task extends Schema {
val tasks = table[Task] // Inspired by Squeryl tutorial
def all(): List[Task] = {
List[Task]() // ??
}
def create(label: String) {
// ??
}
def delete(id: Long) {
// ??
}
}
The rest of the files are left as they were at the end of the Play tutorial.
Here is an example Play 2 project with Squeryl:
https://github.com/jamesward/play2bars/tree/scala-squeryl
The "Play for Scala" (MEAP) book has a chapter on Squeryl integration
http://www.manning.com/hilton/