How to use scalamock for the awssdk - scala

I have a function that has the following type signature:
def post(target: String, partition: String, payload: String): IO[Boolean]
In this function, a call is placed to a third party to post this data to a service through the awssdk. For testing, I don't want these calls actually placed, which has brought me to scalamock, but am not sure how to do this in looking at the documentation.
Within the post function I have leverage my private instance of aws's client for this service after setting credentials. There is a particular method on this instance that is responsible for the call to aws.
How can scalamock be leveraged to mock the awssdk to test the code I have surrounding this and not make the actual call?

Do you have a trait that defines this method? Then you can use Scalamock to get an instance of it and make it respond to post calls with whatever value you want it to.
https://scastie.scala-lang.org/KgJ0kptnRaiteNTWPBzrow
trait MyService {
def post(target: String, partition: String, payload: String): Future[Boolean]
}
val mockedService = mock[MyService]
(mockedService.post _)
.expects("a", "b","c")
.returning(Future.successful(true))
.once()
mockedService.post("a", "b", "c")

Related

Calling Method in Scala from User Input

I have a user input:
val method = """doReplace(doReplace("ab","a","x"),"b","y")"""
How can I invoke this method at run-time using Scala:
object test2 {
def doReplace(str: String, oldChar: String, newChar: String) = {
str.replace(oldChar, newChar)
}
def main(args: Array[String]): Unit = {
val method = """doReplace(doReplace("ab","a","x"),"b","y")"""
}
}
If the user should only be able to call certain methods or have a simple grammar, you may write a simple parser that uses reflection. Scala fastparse is a really great utilty.
If the user should be able to enter arbitrary scala code, you could use a scala implementation of the JSR 223 scripting api or you can compile the code at runtime as describe in this question.
Be aware that this allows to execute arbitrary code on your machine. Do not expose this interface.

How to use Play Framework WSClient to share the same session to invoke multiple services in Scala?

I tried to get more information about WSClient, but did not get enough information on the web.
Here is the scenario:
I'm invoking 3 different rest services from an application in the following order. Login -> UploadFile -> Submit
I want to share the same session across these 3 rest service calls, to complete my process. I'm able to successfully call the login rest service and when I'm trying to call the remaining services, it is returning the response as "403 forbidden".
I was able to implement the same thing correctly in Java using HttpClient. But not sure how can I use the same session using WSClient here. How can I solve this issue? or am I getting this issue because of some other reason?
Below is the sample code which I'm using.
def login(loginUri: String, userName: String, password: String): Int ={
val loginResponse: Future[WSResponse] = ws.url(loginUri).withAuth(userName, password, WSAuthScheme.BASIC).get()
...
}
def uploadFile(uploadUri: String, file: File): Option[String] ={
val uploadResponse: Future[WSResponse] = ws.url(uploadUri).post(Source(FilePart("file", FilenameUtils.getName(file.getName), Option("application/vnd.ms-excel"), FileIO.fromPath(file.toPath)) :: List()))
...
}
def invoke(uri: String, payload: String): Option[String] {
val futResponse: Future[WSResponse] = ws.url(uri).addHttpHeaders("Content-Type" -> "application/json").post(payload)
...
}

What does using "implicit request" mean in Play?

My Scala level is a beginner and I saw an action method clearly demonstrating a declaration implicit request=>. And my question is under what types of situation should we declare clearly? I also have seen methods which don't declare implicit request=> or request=>.
Could anyone explain the advantage?
I will not cover the meaning of implicit in scala itself as it has already been answered on stackoverflow here. The play documentation also explains the use of request => here but does not give examples of a useful implicit request.
TL; DR : when in doubt, use implicit request as it may be needed by some components.
Action without request
If the request does not change the result your block of code will return, it can be omitted and you can write.
def myAction = Action { Ok("Hello World") }
With Request
If on the other hand you need to use the content of the request (header or body), then you have to add a request parameter. A common example of this is parsing the body of the request :
Action(parse.json) { request => // it works without implicit
request.body.validate[MyClass].fold(/* do something */)
}
With implicit request
The play documentation encourages us to mark the request parameter as implicit because even if you do not use the request directly, one component you use may need it as an implicit. If you ever get a missing implicit error in one of your action, it probably boils down to the fact that you forgot to make your request implicit.
I think a good example you might encounter in play is the internationalization API. To sum up, it allows to automatically inject localized messages in your templates depending on the Accept-Language header in the request. All you have to do is add the I18nSupport trait to your controller and inject a messagesApi: MessagesApi parameter (and obviously define your internationalized messages). Then, in your twirl template, you can use the localized messages. For instance :
Template :
#()(implicit messages: Messages)
#*
message will be in english, spanish, klingon... depending on the supported
languages and request Accept-Language header
*#
#messages("say-hello")
Controller :
class MyController #Inject() (val messageApi: MessageApi) extends Controller with I18nSupport {
def myAction = Action {implicit request =>
// We do not have to bother about how messages are injected
// The I18nSupport trait does the work for us
Ok(html.myTemplate())
}
}
To be able to do this, the I18nSupport trait contains a def :
implicit def request2Messages(implicit request: RequestHeader): Messages = /* ... */
It allows to get an instance of Messages automatically (the compiler will implicitly call request2Messages(yourRequest) when needed but you need to have an implicit request (or request header) in scope.
Another example I have seen is automatically getting a user instance in the scope of the action when using some security frameworks in play.
Side note
A annoying gotcha with this kind of implicit chain is that if you forget to make your request implicit, the compiler will probably complain about a missing implicit Messages in scope while the real problem is a missing implicit request.
implicit in Scala has many use cases - one of them being passing parameters implicitly to functions that define implicit parameters.
For example:
def withImplicitParameter(greeting: String)(implicit name: String): Unit = {
println(greeting + " " + name)
}
// Using implicits
implicit val name = "Bob"
withImplicitParameter("Hello") // "Bob" is passed in implicitly for name parameter. Prints "Hello Bob"
withImplicitParameter("Bye")("Joe") // "Joe" is passed in explicitly for name parameter. Prints "Bye Joe"
Therefore unless one of the functions you're calling has an implicit parameter of the type Request you don't need { implicit request => ... }
More info can be found in Scala's official documentation on implicit parameters
Another example with similar API to play's implicit req => ...
case class ClassName(name: String)
def log(msg: String)(implicit className: ClassName) =
System.out.println(s"message=`$msg` className=`${className.name}`")
val cls = Option(ClassName("ImplicitClass"))
cls.foreach { implicit name =>
log("explicit message")
}
Produces
message=`explicit message` className=`ImplicitClass`

Can I prevent "def" to be overriden with "val"?

I have a trait the defines an abstract method without parameters. I want to prevent implementors from overriding this with val, so the method is called every time its value is needed. For eg.
sealed trait Downloader extends Loader {
def username: String
def password: String
def nonceProvider: NonceProvider
def request: Request
def download = {
val client = new Client
client execute request
}
}
This is a trait used for downloading certain resources. Now someone could write the following bad implementation:
case class DownloaderWithServiceDefinition(
override val username: String,
override val password: String,
override val nonceProvider: NonceProvider
serviceDefinition: ServiceDefinition) extends Downloader {
override val request = ServiceDefinitionRequest(serviceDefinition, username, password, nonceProvider.generateNonce())
}
In this implementation, request is assigned a value during construction instead of behaving like a method, so consecutive requests will have the same nonce value which is obviously not intended. Can i prevent this?
You would not want that as a general language feature. The assumption is that a trait requires SOME valid implementation of request of the right type, and codes that requirement. But a trait can make no assumptions/demands on the implementation details of this requirement.
As such, an implementer has the liberty to use a def, a val, a var or even a lazy val as it sees fit, with greater knowledge than the trait has. And if a correct implementation is what concerns you, then the burden of avoiding bugs is indeed in the implementation itself.
You can change your definition to def request(): Request or def request: () => Request to make intent clearer and document the contract you need (actual java/scala doc helps).
It might be even that the request itself, if only used as a way to obtain the nonce, should not be in the trait at all as it is an implementation detail. I would gather than a Downloader would probably not have a single Request at all, but make many as needed, so you might have a smell that you should structure your OO Design differently.

Play 2 - Can't return Json object in Response

I'm trying to do some RESTFull Web service POC using Play 2.1.3
I have the following class:
case class Student(id: Long,firstName: String,lastName: String)
Now I would like to create RESTfull URI which will get Json serialised Student POJO and return the same POJO in response.
implicit val studentReads = Json.reads[Student]
implicit val studentWrites = Json.writes[Student]
def updateStudent = Action(parse.json){
request=>request.body.validate[Student].map{
case xs=>Ok(xs)}.recoverTotal{
e => BadRequest("Detected error:"+ JsError.toFlatJson(e))
}
}
But I'm getting compilation Error -
Cannot write an instance of entities.Student to HTTP response. Try to define a
Writeable[entities.Student]
I just provided Writes[A] as an implicit variable.
What else am I missing?
I think the problem is that the Ok() method cannot figure out the Student needs to be transformed to json, as the arguments to Ok() may vary.
You may return an Ok(Json.toJson(xs))
You may explicitly point the desired type: Ok(xs: JsValue)
And be sure all implicits are in scope