A Simple Link Shortener in Scala

10 June 2015

Recently I took it upon myself to dive into Scala. This post describes what my reaction was after writing a link shortener service using it. For those only interested in the code, check out my github.

After learning the basics of Clojure by writing a simple link shortener, I realized that it was a great way to get to know a language. So I decided to do the same in Scala. Scala is probably the most professional language I've used. It gives you a ton of options and you can really do things the way that you want to. This is a blessing and a curse, it's complicated but gives you a lot of tools.

In Scala's own words:

Object-Oriented Meets Functional

Have the best of both worlds. Construct elegant class hierarchies for maximum code reuse and extensibility, implement their behavior using higher-order functions. Or anything in-between.

I, again, forced a couple of requirements, I wanted to jar it and be able to deploy it, I wanted it to connect to Redis in order to store shortened links, and I wanted to make sure that I could deploy it withDocker. Lastly I wanted to make sure that I wrote tests as well.

What I love about the link shortener application is that you're going to run into plenty of little challenges writing the application.

You'll touch on:

  • The documentation for the language itself
  • The build tools
  • Web app frameworks in the language
  • Simple regular expressions in the language (url validation)
  • HTML templating
  • Testing

Now this isn't something that will take very long assuming you have basic programming skill and if you're looking for more of a challenge there are tons of ways to add onto this application. One of the requirements is that code and tutorials are not to be followed - I made myself write it from scratch.

After writing it I realized things are certainly a bit different in Scala. I decided to use Scalatra. It seems relatively straightforward but dealing with the actor paradigm is certainly a departure from what I'm used to. The first concept I really had to wrestle with was that of a Servlet and Servlet Context. A servlet is simply a way of running a webserver and responding to requests, which are in this case HTTP requests. It's a bit like middleware between the actual receiving of a request and what actually happens with it. The context is like the global context in which that servlet exists.

Once I got a hold of that I obviously needed to be sure that I understood a lot of the actual Scala nuances, like traits. Twitter's Scala School was pretty helpful for teaching the basics of the language. One thing about Scala is that there seems to be a lot of different ways of doing things. I could create a class that handle my url validation (basically creating a url class), or I could create a singleton object that would essentially be a function to do that for me.

Here's the classed based way, with pattern matching. I really like pattern matching.

class Url (inputUrl:String) {
  val validUrl ="^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]".r;
  val url = inputUrl match {
    case validUrl(_*) => inputUrl
    case _ => ""
  }
}

// use with new Url("http://www.google.com")

This was the singleton object based way with pattern matching as well.

object ValidateUrl {
  val validUrl ="^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]".r;
  def apply(inputUrl:String): Boolean = {
    inputUrl match {
      case validUrl(_*) => true
      case _ => false
    }
  }
}
// use with ValidateUrl("http://www.google.com")

Knowing these trade-offs still isn't quite clear to me, but I do love the more function approach of an object (the new keyword isn't something I really enjoy using). One of the things that I've really learned to love is companion objects, they make classes so much more functional.

The Scala-sbt was actually really nice to use, it made packaging and versioning easy and dependency management was pretty straightforward as well.

Now I wanted to really take the time to learn Scala because I'm using Spark pretty heavily at work and in my research. I had used pySpark previously but was ready to step up to something a bit more professional grade. I'm using it now on a regular basis and writing production, tested, code that runs on a several node cluster.

Now obviously there's a lot more to learn, but this was another great little project that helped me learn a new language.

Check out my other post on writing a link shortener in Clojure.