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`
Related
No instance of play.api.libs.json.Format is available for akka.actor.typed.ActorRef[org.knoldus.eventSourcing.UserState.Confirmation] in the implicit scope (Hint: if declared in the same file, make sure it's declared before)
[error] implicit val userCommand: Format[AddUserCommand] = Json.format
I am getting this error even though I have made Implicit instance of Json Format for AddUserCommand.
Here is my code:
trait UserCommand extends CommandSerializable
object AddUserCommand{
implicit val format: Format[AddUserCommand] = Json.format[AddUserCommand]
}
final case class AddUserCommand(user:User, reply: ActorRef[Confirmation]) extends UserCommand
Can anyone please help me with this error and how to solve it?
As Gael noted, you need to provide a Format for ActorRef[Confirmation]. The complication around this is that the natural serialization, using the ActorRefResolver requires that an ExtendedActorSystem be present, which means that the usual approaches to defining a Format in a companion object won't quite work.
Note that because of the way Lagom does dependency injection, this approach doesn't really work in Lagom: commands in Lagom basically can't use Play JSON.
import akka.actor.typed.scaladsl.adapter.ClassicActorSystemOps
import play.api.libs.json._
class PlayJsonActorRefFormat(system: ExtendedActorSystem) {
def reads[A] = new Reads[ActorRef[A]] {
def reads(jsv: JsValue): JsResult[ActorRef[A]] =
jsv match {
case JsString(s) => JsSuccess(ActorRefResolver(system.toTyped).resolveActorRef(s))
case _ => JsError(Seq(JsPath() -> Seq(JsonValidationError(Seq("ActorRefs are strings"))))) // hopefully parenthesized that right...
}
}
def writes[A] = new Writes[ActorRef[A]] {
def writes(a: ActorRef[A]): JsValue = JsString(ActorRefResolver(system.toTyped).toSerializationFormat(a))
}
def format[A] = Format[ActorRef[A]](reads, writes)
}
You can then define a format for AddUserCommand as
object AddUserCommand {
def format(arf: PlayJsonActorRefFormat): Format[AddUserCommand] = {
implicit def arfmt[A]: Format[ActorRef[A]] = arf.format
Json.format[AddUserCommand]
}
}
Since you're presumably using JSON to serialize the messages sent around a cluster (otherwise, the ActorRef shouldn't be leaking out like this), you would then construct an instance of the format in your Akka Serializer implementation.
(NB: I've only done this with Circe, not Play JSON, but the basic approach is common)
The error says that it cannot construct a Format for AddUserCommand because there's no Format for ActorRef[Confirmation].
When using Json.format[X], all the members of the case class X must have a Format defined.
In your case, you probably don't want to define a formatter for this case class (serializing an ActorRef doesn't make much sense) but rather build another case class with data only.
Edit: See Levi's answer on how to provide a formatter for ActorRef if you really want to send out there the actor reference.
In my play app, I have some action filter that does some auth stuff. It has a WrappedRequest type which includes some information after the auth has been done e.g.
case class User(f : Foo) extends extends WrappedRequest[A](request)
I have a lot of twirl templates where I want to pass this Foo in. The way I am doing it now is to create an implicit value inside each controller method which loads a template, so e.g.
def doStuff : Action{
implicit request =>
implicit val value = request.f
Ok(some_template())
}
In the template I have
// some imports
#()(implicit f : Foo)
Because I have a shed load of templates, I will have to declare the implicit in my controller method and then update each template to have that implicit picked up. Is there a better way to do this?
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.
My application code uses AService
trait AService {
def registerNewUser (username: String)(implicit tenant: Tenant): Future[Response]
}
to register a new user. Class Tenant is a simple case class:
case class Tenant(val vstNumber:String, val divisionNumber:String)
Trait AServiceMock mimics the registration logic by using a mocked version of AService
trait AServiceMock {
def registrationService = {
val service = mock[AService]
service.registerNewUser(anyString) returns Future(fixedResponse)
service
}
}
Iow whenever registerNewUser is called on AService the response will be "fixedResponse" (defined elsewhere).
My question is, how do I define the implicit tenant-parameter as a mockito matcher like anyString?
btw. I'm using Mockito with Specs2 (and Play2)
Sometimes you have to post on SO first to come up with the completely obvious answer (duhh):
service.registerNewUser(anyString)(any[Tenant]) returns Future(fixedResponse)
This a complement to #simou answer. For now I think this is how it should be done, but I think it is intresting to know why the alternative solution proposed by #Enrik should be avoided as it may fail at run time with a cryptic error in some circumstances.
What you can safely do is if you want an exact match on your implicit argument for your stub, you can just add it in the scope :
trait AServiceMock {
implicit val expectedTenant: Tenant = Tenant("some expected parameter")
def registrationService = {
val service = mock[AService]
service.registerNewUser(anyString) returns Future(fixedResponse)
service
}
}
This will work fine but only if service.registerNewUser is expected to be called with the exact same tenant that the one provided by the implicit value expectedTenant .
What will not reliably work on the other hand is anything in the style :
implicit val expectedTenant1: Tenant = any[Tenant]
implicit def expectedTenant2: Tenant = any[Tenant]
implicit def expectedTenant3: Tenant = eqTo(someTenant)
To reason is related to how mockito create its argument matcher.
When you write myFunction(*,12) returns "abc" mockito actually use a macro that :
add code to intialize a list were argument matcher can register
If needed, wrap all argument that are not matcher in matchers.
add code to retrive the list of matchers that were declared for this function.
In the case of expectedTenant2 or expectedTenant3 what may append is that a first argument matcher will be registerd when the function is evaludated. But the macro will not see this function is registering a macther. It will only consider the declared return type of this function and so may decide to wrap this returned value inside a second matcher.
So in practice if you have code like this
trait AServiceMock {
implicit def expectedTenant(): Tenant = any[Tenant]
def registrationService = {
val service = mock[AService]
service.registerNewUser(anyString) returns Future(fixedResponse)
service
}
}
You expect it to be like that after applying the implicit :
trait AServiceMock {
def registrationService = {
val service = mock[AService]
service.registerNewUser(anyString)(any[Tenant]) returns Future(fixedResponse)
service
}
}
But actually mockito macro will make it as something more or less like that :
trait AServiceMock {
def registrationService = {
val service = mock[AService]
// In practice the macro use DefaultMatcher and not eqTo but that do not change much for the matter we discuss.
service.registerNewUser(anyString)(eqTo(any[Tenant])) returns Future(fixedResponse)
service
}
}
So now you declare two matcher inside the implicit argument of your stub. When mockito will retrive the list of matchers that were declared for registerNewUser, it will see three of them and will think that you are trying to register a stub with three argument for a function that need only two and will log :
Invalid use of argument matchers!
2 matchers expected, 3 recorded:
I'm not yet sure why it may still work in some cases, my hypotheses are :
Maybe the macro sometime decide in some case that a matcher is not needed, and do not wrap the value returned by implicit function in an additional matcher.
Maybe with some leniency option enabled, mockito ignore additional matcher. Even if that was the case, the additonal matcher may mess up the order of the argument for your stub.
It may be also possible that under some circonstance, the scala compiler inline the implicit def, this would allow the macro to see that a matcher was used.
Background
I am trying to understand best practices for bringing implicit objects into scope within a Scala application.
I have a Playframework 2.2.0 (Scala 2.10) web app that mixes in a trait for Authorization. It checks. The Authenticated object checks that there is a user_id in scope, attempts to retrieve the user info, access token, and a data package object called a MagicNotebook from cache, database, and web service call. If the request is valid, then various objects are added to the wrapped request.
object Authenticated extends ActionBuilder[AuthenticatedRequest] {
def invokeBlock[A](request: Request[A],
block: (AuthenticatedRequest[A] => Future[SimpleResult])) = {
request.session.get(userName).map { implicit userId =>
Cache.getAs[DbUser](userKey).map { user =>
Cache.getAs[String](accessTokenKey).map { accessToken =>
Cache.getAs[MagicNotebook](magicNotebookKey(userId)).map { notebook =>
block(AuthenticatedRequest(user, accessToken, notebook, request) )
}.getOrElse(startOver)
}.getOrElse {
requestNewAccessToken(user.token).flatMap { response =>
persistAccessToken(response).map { accessToken =>
Cache.getAs[MagicNotebook](magicNotebookKey(userId)).map { notebook =>
block(AuthenticatedRequest(user, accessToken, notebook, request))
}.getOrElse(startOver)
}.getOrElse(startOver)
}
}
}.getOrElse(startOver) // user not found in Cache
}.getOrElse(startOver) // userName not found in session
}
}
}
case class AuthenticatedRequest[A](user: DbUser,
accessToken: String,
magic: MagicNotebook,
request: Request[A])
extends WrappedRequest[A](request)
Question
What is the best way to bring these implicit variables into scope?
Through an implicit class?
I tried to use an implicit companion class, with the following code:
object Helper {
implicit class Magical(request: AuthenticatedRequest[AnyContent]) {
def folderMap = request.magic.fMap
def documentMap = request.magic.dMap
}
}
However, I don't really get the benefit of an implicit this way:
def testing = Authenticated { implicit request =>
import services.Helper._
request.magic.home.folders // doesn't compile
request.magic.home.folders(Magical(request).ffMap) // compiles, but not implicitly
Ok("testing 123")
}
Through an import statement?
One possibility I considered was through an import statement within the controller. Here, the request has a MagicNotebook object in scope that I would like to use as an implicit variable.
def testing = Authenticated { implicit request =>
import request.magic._
request.magic.home.folders // implicit map is a parameter to the `folder` method
Ok("testing 123")
}
Through a companion trait?
Here, I create a companion trait that is mixed into the Authenticate trait that includes the two maps of the MagicNotebook object into scope of the controller.
trait Magic {
implicit def folderMap[A](implicit request: AuthenticatedRequest[A]) =
request.magic.fMap
implicit def docMap[A](implicit request: AuthenticatedRequest[A]) =
request.magic.dMap
}
My preference is the companion trait solution, but I was wondering if there might be a better way that I overlooked. I ended up re-writing methods that use the implicit variable, to use the MagicNotebook's two maps instead of whole object as implicit parameters.
But again, I was wondering if there might be a better way.
I am quite partial to package objects for this sort of thing. See What's New in Scala 2.8: Package Objects for a description. Package objects effectively allow you to put implicit classes into a package, which you can't otherwise do.
However, the main snag with this approach is that you can't split the definition of an object across multiple source files, so because the implicit classes need to be defined within the package object, they also need to be all in the same source file. If you have many implicit classes you wish to have imported, this can result in a large and unwieldy source file. However, that in itself is a sign that you have a “package god object” which should be split.
One of the ways I know of defining implicits is by using Package Objects.
package implicitIdiomatic {
implicit def nullableLongToOption(l:java.lang.Long) = Option(l)
}
}
package implicitIdiomatic
class ImplicitIdiomaticTest{
val l:Long = 1
longOpt(l)
def longOpt(l:Option[Long]) = l match {case Some(l1) => println(l1); case None => println("No long")}
}
Kind of useless example but hope you get the idea. Now when longOpt gets l, it is converted to Option[Long] using the implicit.
As long as you are working in the same package as defined by the package object you don't need the import statement.