Scala: Proxy Design Pattern
Want to learn more about structural design patterns in Scala? Check out this post where we look at using the Proxy design pattern.
Join the DZone community and get the full member experience.
Join For FreeIn our previous blogs, we discussed the decorator design pattern and the adapter design pattern. Now, its time to discuss another structural design pattern, the Proxy design pattern. We will implement the same EUGDPR problem using the Proxy design pattern, which we implemented using the adapter design pattern from our previous blog.
Problem Statement
Earlier, in many applications, all the user-specific details, like username, IP addresses, phone number, etc., were logged directly without scrambling it. But, after new data protection law, i.e. EUGDPR, it is now mandatory to scramble any user-specific data.
Solution
We will add a proxy class between our logging framework(slf4j) and our client.
What Is the Proxy Design Pattern?
A proxy is a class functioning as an interface to something else.
The proxy design pattern focuses on providing a surrogate or placeholder for another object to control access to it.
We will create a LoggerProxy
class, which will be called before calling the Logging
framework, and it will scramble the logs and call the logging framework methods.
The build.sbt is a file that describes project settings. We are using the slf4j dependency
to add a logging framework to our application.
name := "ProxyDesignPattern"
version := "0.1"
scalaVersion := "2.12.6"
// https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12
libraryDependencies ++= Seq("org.slf4j" % "slf4j-api" % "1.7.5",
"org.slf4j" % "slf4j-simple" % "1.7.5")
The Client
class is the class that will actually call the logging
methods.
package com.knoldus
object Client extends App {
val logger = LoggerProxy.getLogger(this.getClass.getName)
logger.info("Log Contains IP address: 127.0.0.1")
logger.debug("UserName: jainnancy trying to sign in")
logger.error("Password: abxyz is wrong ")
}
The LoggerHelper
class will scramble the logs.
package com.knoldus
class LoggerHelper {
private val regex = "\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"
private val password = "Password: "
private val userName = "UserName: "
def scramble(message : String) = scrambleUsername(scrambleIp((scramblePassword(message))))
private def scrambleUsername(message : String) = {
if(message.contains(userName)) {
val index = message.indexOf(userName) + userName.length()
val textStartedPassword = message.substring(index)
message.substring(0, index) + "X" + textStartedPassword.substring(textStartedPassword.indexOf(" "))
}
else {
message
}
}
private def scrambleIp(message : String) = message.replaceAll(regex, "XXX.XXX.XXX.XXX")
private def scramblePassword(message : String) = {
if(message.contains(password)) {
val index = message.indexOf(password) + password.length()
val textStartedPassword = message.substring(index)
message.substring(0, index) + "X" + textStartedPassword.substring(textStartedPassword.indexOf(" "))
}
else {
message
}
}
}
The LoggerProxy
is the new class that will act as a proxy between the client
and logging
framework and will make sure that logs are scrambled before logging.
LoggerProxy
will implement the Logger
interface, which is defined in the slf4j framework.
package com.knoldus
import org.slf4j.{Logger, LoggerFactory, Marker}
object LoggerProxy extends Logger {
private var logger : Logger = _
private val loggerHelper = new LoggerHelper
def getLogger(name : String) : Logger = {
logger = LoggerFactory.getLogger(name)
LoggerProxy
}
def getName : String = logger.getName
def debug(msg : String) : Unit = logger.debug(loggerHelper.scramble(msg))
def debug(format : String, arg : scala.Any) : Unit = logger.debug(loggerHelper.scramble(format),arg)
def debug(format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit = logger.debug(loggerHelper.scramble(format), arg1, arg2)
def debug(format : String, arguments : AnyRef*) : Unit = logger.debug(loggerHelper.scramble(format), arguments)
def debug(msg : String, t : Throwable) : Unit = logger.debug(loggerHelper.scramble(msg), t)
def debug(marker : Marker, msg : String) : Unit = logger.debug(marker, loggerHelper.scramble(msg))
def debug(marker : Marker, format : String, arg : scala.Any) : Unit = logger.debug(marker, loggerHelper.scramble(format), arg)
def debug(marker : Marker, format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit =
logger.debug(marker, loggerHelper.scramble(format), arg1, arg2)
def debug(marker : Marker, format : String, arguments : AnyRef*) : Unit = logger.debug(marker, loggerHelper.scramble(format), arguments)
def debug(marker : Marker, msg : String, t : Throwable) : Unit = logger.debug(marker, loggerHelper.scramble(msg), t)
def isWarnEnabled : Boolean = logger.isWarnEnabled
def isWarnEnabled(marker : Marker) : Boolean = logger.isWarnEnabled(marker)
def error(msg : String) : Unit = logger.error(loggerHelper.scramble(msg))
def error(format : String, arg : scala.Any) : Unit = logger.error(loggerHelper.scramble(format), arg)
def error(format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit = logger.error(loggerHelper.scramble(format), arg1, arg2)
def error(format : String, arguments : AnyRef*) : Unit = logger.error(loggerHelper.scramble(format), arguments)
def error(msg : String, t : Throwable) : Unit = logger.error(loggerHelper.scramble(msg), t)
def error(marker : Marker, msg : String) : Unit = logger.error(marker, loggerHelper.scramble(msg))
def error(marker : Marker, format : String, arg : scala.Any) : Unit = logger.error(marker, loggerHelper.scramble(format), arg)
def error(marker : Marker, format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit =
logger.error(marker, loggerHelper.scramble(format), arg1, arg2)
def error(marker : Marker, format : String, arguments : AnyRef*) : Unit = logger.error(marker, loggerHelper.scramble(format), arguments)
def error(marker : Marker, msg : String, t : Throwable) : Unit = logger.error(marker, loggerHelper.scramble(msg), t)
def warn(msg : String) : Unit = logger.warn(loggerHelper.scramble(msg))
def warn(format : String, arg : scala.Any) : Unit = logger.warn(loggerHelper.scramble(format), arg)
def warn(format : String, arguments : AnyRef*) : Unit = logger.warn(loggerHelper.scramble(format), arguments)
def warn(format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit = logger.warn(loggerHelper.scramble(format), arg1, arg2)
def warn(msg : String, t : Throwable) : Unit = logger.warn(loggerHelper.scramble(msg), t)
def warn(marker : Marker, msg : String) : Unit = logger.warn(marker, loggerHelper.scramble(msg))
def warn(marker : Marker, format : String, arg : scala.Any) : Unit = logger.warn(marker, loggerHelper.scramble(format), arg)
def warn(marker : Marker, format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit =
logger.warn(marker, loggerHelper.scramble(format), arg1, arg2)
def warn(marker : Marker, format : String, arguments : AnyRef*) : Unit = logger.warn(marker, loggerHelper.scramble(format), arguments)
def warn(marker : Marker, msg : String, t : Throwable) : Unit = logger.warn(marker, loggerHelper.scramble(msg), t)
def trace(msg : String) : Unit = logger.trace(loggerHelper.scramble(msg))
def trace(format : String, arg : scala.Any) : Unit = logger.trace(loggerHelper.scramble(format), arg)
def trace(format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit = logger.trace(loggerHelper.scramble(format), arg1, arg2)
def trace(format : String, arguments : AnyRef*) : Unit = logger.trace(loggerHelper.scramble(format), arguments)
def trace(msg : String, t : Throwable) : Unit = logger.trace(loggerHelper.scramble(msg), t)
def trace(marker : Marker, msg : String) : Unit = logger.trace(marker, loggerHelper.scramble(msg))
def trace(marker : Marker, format : String, arg : scala.Any) : Unit = logger.trace(marker, loggerHelper.scramble(format), arg)
def trace(marker : Marker, format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit =
logger.trace(marker, loggerHelper.scramble(format), arg1, arg2)
def trace(marker : Marker, format : String, argArray : AnyRef*) : Unit = logger.trace(marker, loggerHelper.scramble(format), argArray)
def trace(marker : Marker, msg : String, t : Throwable) : Unit = logger.trace(marker, loggerHelper.scramble(msg), t)
def isInfoEnabled : Boolean = logger.isInfoEnabled
def isInfoEnabled(marker : Marker) : Boolean = logger.isInfoEnabled(marker)
def isErrorEnabled : Boolean = logger.isErrorEnabled
def isErrorEnabled(marker : Marker) : Boolean = logger.isErrorEnabled(marker)
def isTraceEnabled : Boolean = logger.isTraceEnabled
def isTraceEnabled(marker : Marker) : Boolean = logger.isTraceEnabled(marker)
def isDebugEnabled : Boolean = logger.isDebugEnabled
def isDebugEnabled(marker : Marker) : Boolean = logger.isDebugEnabled(marker)
def info(msg : String) : Unit = logger.info(loggerHelper.scramble(msg))
def info(format : String, arg : scala.Any) : Unit = logger.info(loggerHelper.scramble(format), arg)
def info(format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit = logger.info(loggerHelper.scramble(format), arg1, arg2)
def info(format : String, arguments : AnyRef*) : Unit = logger.info(loggerHelper.scramble(format), arguments)
def info(msg : String, t : Throwable) : Unit = logger.info(loggerHelper.scramble(msg), t)
def info(marker : Marker, msg : String) : Unit = logger.info(marker, loggerHelper.scramble(msg))
def info(marker : Marker, format : String, arg : scala.Any) : Unit = logger.info(marker, loggerHelper.scramble(format), arg)
def info(marker : Marker, format : String, arg1 : scala.Any, arg2 : scala.Any) : Unit =
logger.info(marker, loggerHelper.scramble(format), arg1, arg2)
def info(marker : Marker, format : String, arguments : AnyRef*) : Unit = logger.info(marker, loggerHelper.scramble(format), arguments)
def info(marker : Marker, msg : String, t : Throwable) : Unit = logger.info(marker, loggerHelper.scramble(msg), t)
}
Hope you liked the blog. Thanks for reading!
References
Published at DZone with permission of Nancy Jain, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Observability Architecture: Financial Payments Introduction
-
Boosting Application Performance With MicroStream and Redis Integration
-
13 Impressive Ways To Improve the Developer’s Experience by Using AI
-
Insider Threats and Software Development: What You Should Know
Comments