import scala.collection.mutable
class Session
trait SessionProvider:
def session: Session
trait DefaultSessionProvider extends SessionProvider:
val dummySession = new Session
override def session = dummySession
abstract class Identity
trait IdentityCache:
def getOrAuthenticate():Session
trait InMemoryIdentityCache extends SessionProvider:
val cache = mutable.Map.empty[Session, SessionProvider]
override def getOrAuthenticate():InMemoryIdentityCache =
cache.getOrElseUpdate(session, authenticate())
trait Authenticator:
def authenticate():Session
trait UsesSAMLIdentity:
class SAMLIdentity(val saml: String) extends Identity
trait SAMLAuthenticator extends Authenticator with UsesSAMLIdentity:
val dummySAMLIdentity = new SAMLIdentity("XXX")
override def authenticate() = dummySAMLIdentity
trait RoleManager:
def hasRole(role: String): Boolean
trait SAMLRoleManager extends RoleManager with UsesSAMLIdentity:
override def hasRole(role: String): Boolean =
val identity = getOrAuthenticate()
identity.saml == "XXX"
object WebApp extends SAMLRoleManager :
def main(args: Array[String]): Unit =
println(hasRole("YYY")) // Prints "true"
I am new in Scala and I am trying to implement the above code to print true in main. My problem is that my IDE says "Not found: authenticate" and "Not found session" in trait InMemoryIdentityCache. I am a little confused about how to implement this cake pattern.
I will appreciate any help.
InMemoryIdentityCache
extends SessionProvider
but doesn't implement session
. So whatever extends it would have to provide it. From what I see only DefaultSessionProvider
has it defined, but nothing mixes it in. Actually nobody mixes-in any SessionProvider
as far as I can see).
InMemoryIdentityCache
doesn't extend Authenticator
so it cannot access authenticate()
. If you want to tell compiler that it should extends Authenticator
and a method will be there, you need:
trait InMemoryIdentityCache extends ...:
self: Authenticator =>
The fact that "final" cake might have all the methods doesn't allow you to miss them in the intermediate cake layers.
Also cake pattern is widely recognized as antipattern. Rewrite your code to use constructors to inject dependencies and you'll immediately see where there are issues and why.
import scala.collection.mutable
class Session
abstract class Identity
class SAMLIdentity(val saml: String) extends Identity
trait SessionProvider:
def session: Session
class DefaultSessionProvider extends SessionProvider:
val dummySession = new Session
override def session = dummySession
trait Authenticator:
def authenticate(): Identity // you had Session, it didn't work
class SAMLAuthenticator extends Authenticator:
val dummySAMLIdentity = new SAMLIdentity("XXX")
override def authenticate() = dummySAMLIdentity // because your return SAMLIdentity
trait IdentityCache:
// you had Session her as well, even though there is Identity in class name
def getOrAuthenticate(): Identity
class InMemoryIdentityCache(
sessionProvider: SessionProvider,
authenticator: Authenticator
) extends IdentityCache:
val cache = mutable.Map.empty[Session, Identity] // you had [Session, SessionProvider] ?!?
override def getOrAuthenticate(): Identity =
cache.getOrElseUpdate(sessionProvider.session, authenticator.authenticate())
trait RoleManager:
def hasRole(role: String): Boolean
class SAMLRoleManager(identityCache: IdentityCache) extends RoleManager:
override def hasRole(role: String): Boolean =
identityCache.getOrAuthenticate() match {
case identity: SAMLIdentity => identity.saml == "XXX"
case _ => false
}
object WebApp:
def main(args: Array[String]): Unit =
val sessionProvider: SessionProvider = new DefaultSessionProvider
val authenticator: Authenticator = new SAMLAuthenticator
val identityCache: IdentityCache = new InMemoryIdentityCache(sessionProvider, authenticator)
val roleManager: RoleManager = new SAMLRoleManager(identityCache)
println(roleManager.hasRole("YYY")) // Prints "true"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.