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.
Related
I was looking at some open source scala project. and I saw that some are doing something like :
abstract class Foo{
def create(implicit ex: ExecutionContextExecutor): Seq[ResultSet] = {
Await.result(createAsync(), timeout)
}
def createAsync()(implicit ex: ExecutionContextExecutor): Future[Seq[ResultSet]] = //implementation
... more like those
}
is there any advantage/disadvantage for calling each method with
(implicit ex: ExecutionContextExecutor) parameter rather than passing the ExecutionContextExecutor in the class constructor:
abstract class Foo(implicit ex: ExecutionContextExecutor){
def create(timeout: FiniteDuration): Seq[ResultSet] = {
Await.result(createAsync(), timeout)
}
def createAsync(): Future[Seq[ResultSet]] = //implementation
... more like those
}
is there preferred option ?
The former approach gives you more flexibility as to where the execution of createAsync will be scheduled, since each time you can make a decision as to which ExecutionContext you want to pass in. Question is, do you need that flexibility? I find that most of the times a single ExecutionContext is sufficient, but it is really a matter of case by case analysis.
In general, the first snippet is horrible IMO. Exposing a synchronous wrapper which blocks around an asynchronous operation is usually a sign of a code smell, and code like that doesn't scale well.
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`
I have the situation where I want to preserve information about some generic type passed within a message to be able to create another generic class with that same type within receive method responsible for processing the message.
At first glance I thought TypeTag is my best friend here, but, after trying that out it seems this is not the best possible solution, or not solution at all. Let me first explain what I have at the moment and what is the outcome.
Message case class
trait MessageTypeTag[T] {
def typeTag: TypeTag[T]
}
case class Message[T](id: Int, payload: T, helper: MyClass[T],
cond: Condition[MyClass[T]])(implicit val typeTag: TypeTag[T])
extends MessageTypeTag[T]
MyClass2
class MyClass2[+T <: Any](_eval: Option[T] = None) {
def getEval = _eval getOrElse None
}
Receive method
def receive() = {
case m#Message(id, payload, helper, cond) => {
// this prints a proper type tag, i.e. String, because type is known in the runtime
println(m.typeTag.tpe)
// compiler complains here because it sees m.typeTag as TypeTag[Any], i.e. exact
// type is not known in the compile time
val temp = new MyClass2[m.typeTag.tpe](...)
}
}
Dirty solution
After reading several articles, discussions, documentation on both Scala and akka I come up with some dirty solution by putting the (call to) factory method case class.
case class Message[T](id: Int, payload: T, helper: MyClass[T],
cond: Condition[MyClass[T]])(implicit val typeTag: TypeTag[T])
extends MessageTypeTag[T] {
def getMyClass2: MyClass2[T] = {
// instantiate an object of type T
val bla = typeTag.mirror.runtimeClass(typeTag.tpe).newInstance.asInstanceOf[T]
// we can call apply here to populate created object or do whathever is needed
...
// instantiate MyClass2 parametrized with type T and return it
new MyClass2[T](Some(bla))
}
}
As you can see this is far from good solution/design because this case class is all but lightweight and actually defeats the purpose of case class itself. It can be improved in a way that reflection call is not coded here but in some external factory which is just called within case class, but I have a feeling there must be a better approach to accomplish this.
Any suggestion would be very appreciated. If there are some more information needed, I can provide it.
And, I believe, similar problem/solution has been described here, but I'm wondering is there a better way. Thanks.
If you want to be able to instantiate a class with reflection then you have to pass it around, there's no way around that. I think a ClassTag based solution is slightly simpler:
val bla = classTag.runtimeClass.newInstance.asInstanceOf[T]
but it's still pretty ugly.
It might be better to pass around a factory as a function rather than using a reflective approach; this lets you work with classes with no no-arg constructor or that require some setup:
case class Message[T](..., factory: () => T) {
def getMyClass2 = new MyClass2[T](Some(factory()))
}
Message(..., {_ => new SomeTThatTakesArguments(3, 4)})
I suspect the best solution will be to change your MyClass2 so that it doesn't depend on the type in the same way - perhaps you can express the constraint MyClass2 needs as a typeclass you can include in the Message, or leave it out entirely. But you'll need to post MyClass2 if you want us to suggest a solution on those lines.
I'm having trouble finding an elegant way of designing a some simple classes to represent HTTP messages in Scala.
Say I have something like this:
abstract class HttpMessage(headers: List[String]) {
def addHeader(header: String) = ???
}
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers)
new HttpRequest("/", List("foo")).addHeader("bar")
How can I make the addHeader method return a copy of itself with the new header added? (and keep the current value of path as well)
Thanks,
Rob.
It is annoying but the solution to implement your required pattern is not trivial.
The first point to notice is that if you want to preserve your subclass type, you need to add a type parameter. Without this, you are not able to specify an unknown return type in HttpMessage
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String):X
}
Then you can implement the method in your concrete subclasses where you will have to specify the value of X:
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers){
type X = HttpRequest
def addHeader(header: String):HttpRequest = new HttpRequest(path, headers :+header)
}
A better, more scalable solution is to use implicit for the purpose.
trait HeaderAdder[T<:HttpMessage]{
def addHeader(httpMessage:T, header:String):T
}
and now you can define your method on the HttpMessage class like the following:
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String)(implicit headerAdder:HeaderAdder[X]):X = headerAdder.add(this,header) }
}
This latest approach is based on the typeclass concept and scales much better than inheritance. The idea is that you are not forced to have a valid HeaderAdder[T] for every T in your hierarchy, and if you try to call the method on a class for which no implicit is available in scope, you will get a compile time error.
This is great, because it prevents you to have to implement addHeader = sys.error("This is not supported")
for certain classes in the hierarchy when it becomes "dirty" or to refactor it to avoid it becomes "dirty".
The best way to manage implicit is to put them in a trait like the following:
trait HeaderAdders {
implicit val httpRequestHeaderAdder:HeaderAdder[HttpRequest] = new HeaderAdder[HttpRequest] { ... }
implicit val httpRequestHeaderAdder:HeaderAdder[HttpWhat] = new HeaderAdder[HttpWhat] { ... }
}
and then you provide also an object, in case user can't mix it (for example if you have frameworks that investigate through reflection properties of the object, you don't want extra properties to be added to your current instance) (http://www.artima.com/scalazine/articles/selfless_trait_pattern.html)
object HeaderAdders extends HeaderAdders
So for example you can write things such as
// mixing example
class MyTest extends HeaderAdders // who cares about having two extra value in the object
// import example
import HeaderAdders._
class MyDomainClass // implicits are in scope, but not mixed inside MyDomainClass, so reflection from Hiberante will still work correctly
By the way, this design problem is the same of Scala collections, with the only difference that your HttpMessage is TraversableLike. Have a look to this question Calling map on a parallel collection via a reference to an ancestor type
I have a Social object, responsable of connecting to Twitter, facebook, etc, and retrieve provider info for the specified user
For each provider I implemented a singleton TwitterAdapter, all inheriting from an abstract class SocialAdapter
here's the code: https://github.com/RestOpenGov/ideas-ba/blob/master/webservice/app/services/security/SocialConnector.scala#L98
For testing, I would obviously like to mock the TwitterAdapter, so that instead of connecting with twitter it returns some fixed response.
One solution I've found was to inject the list of adapters using an implicit parameter. The problem with this solution is that the Social.retrieveSocialProviderInfo is called from other functions, so I have to pass around the implicit List[SocialAdapter] parameter though all the call chain, like this:
def createApplicationToken(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters)
: Either[List[Error], ApplicationToken] = {
// go to social info provider and fetch information
retrieveProviderInfo(accessToken).fold(
[...]
def retrieveProviderInfo(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters)
: Either[List[Error], IdentityProviderInfo] = {
[...]
and finally
object Social {
val defaultAdapters = List(TwitterAdapter, FacebookAdapter)
def retrieveSocialProviderInfo
(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters) // adapters can be injected
: Option[IdentityProviderInfo] = {
[...]
You get the idea
It works fine, normally I just ignore the second group of parameters and pick the default from Social.defaultAdapters, I only set it to List(MockTwitterAdapter, MockFacebookAdapter) when testing, but I'm cluttering the code just to be able to test it.
The other solution would be to make Social.defaultAdapters a var (instead of a val) and just change it for testing, normally in production mode it would always have the same value.
I think this must be a pretty common scenario. Is there a better strategy to handle these situations? Or maybe some way to extend the scope of the implicit assignment? Or shall I just go with a full-featured dependency injection framework?
A simple approach can be to just use traits all along:
// you can test this trait and override the adapters as you wish
// by overriding the defaultAdapters member
trait Social {
implicit val defaultAdapters = List(TwitterAdapter, FacebookAdapter)
def retrieveSocialProviderInfo(accessToken: AccessToken):
Option[IdentityProviderInfo] = ...
}
// you can use this object directly in your production code
// if you don't want to mix it in
object Social extends Social
// or use the trait by mixing it with another
trait Application extends Social {
def createApplicationToken(accessToken: AccessToken):
Either[List[Error], ApplicationToken] = {
// the defaultAdapters are accessible to the
// retrieveProviderInfo method
retrieveProviderInfo(accessToken).fold(...)
}