Adapter design pattern with Scala

Reading Time: 2 minutes

AdapterFeaturedImage

Hi Readers!
In our last blog, we have discussed the Decorator design pattern with Scala.
In this blog, we will explore the Adapter design pattern. We will also implement this pattern in Scala.

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.

So, we need to change the logging logic for all such applications.
In order to do this, we will add some extra methods to our logging framework.
But wait!
We all know that most of our applications are generally flooded with logging statements and replacing all the statements with new method names, is not logically and practically possible.

So, what can we do now? 🤔

So here, the Adapter design pattern comes into the picture.

What is the Adapter design pattern?

Convert the interface of a class into another interface clients expect. Adapter
lets classes work together that could not otherwise because of incompatible
interfaces. Adapter is also known as wraper.

Solution to our problem:

We will change our existing logger framework to a framework, which supports methods like scrambledInfo(), scambledError(), scrambledDebug(), etc.

adapterDesignUml

We will create a LoggerAdapter class which will adapt or wrap ScrambledLogger and whenever client call info method, it will call the scrambledInfo method and will do same for the methods debugerror etc.

Flow chart- Adapter Design pattern

Client class is the class which will actually call the logging methods.

The LoggerHelper trait is an existing trait in which all the required logging methods are declared.

Now, ScrambledLogger is the new class which will scramble all the logs before logging. It is basically an Adaptee.

LoggerAdapter is the class which will act as an interface between our Client and our adaptee class ScrambledLogger.



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


package com.knoldus
import org.apache.log4j.BasicConfigurator
object Client extends App {
BasicConfigurator.configure()
val logger : LoggerHelper = LoggerAdapter.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 ")
}
view raw

Client.scala

hosted with ❤ by GitHub



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


package com.knoldus
object LoggerAdapter extends LoggerHelper {
var scrambledLogger : ScrambledLogger = _
override def info(msg : String) = scrambledLogger.scrambledInfo(msg)
override def debug(msg : String) = scrambledLogger.scrambledDebug(msg)
override def error(msg : String) = scrambledLogger.scrambledError(msg)
def getLogger(s : String) : LoggerHelper =
{
scrambledLogger = new ScrambledLogger(s)
LoggerAdapter
}
}



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


package com.knoldus
import org.apache.log4j.BasicConfigurator
trait LoggerHelper {
def info(msg : String)
def debug(msg : String)
def error(msg : String)
}



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


package com.knoldus
import org.apache.log4j.Logger
class ScrambledLogger(name : String)
{
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: "
private val logger = Logger.getLogger(name)
def scrambledInfo(message : String) = logger.info(scramble(message))
def scrambledDebug(message : String) = logger.debug(scramble(message))
def scrambledError(message : String) = logger.error(scramble(message))
private 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
}
}
}

Note:

  1. We are using following dependency for Logger:
    libraryDependencies += "log4j" % "log4j" % "1.2.17"
  2. ScrambledLogger is also somehow using the Proxy design pattern. Which we will discuss in the upcoming blog.

Hope you liked the blog 🙂

References:


knoldus-advt-sticker

 

Written by 

Nancy jain is a software consultant with experience of more than 6 months. She likes to explore new technologies and trends in the IT world. Her hobbies include watching web series, writing and travelling. Nancy is familiar with programming languages such as Java, Scala, C, C++, HTML, Javascript and she is currently working on reactive technologies like Scala, DynamoDb, AkkaHttp.

1 thought on “Adapter design pattern with Scala2 min read

Comments are closed.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading