Scalariver in a (spray) can

Last time, I mentioned using a tool to format my code in scala whenever I am using sublimetext editor. It has been a lot of fun and I loved using it. What better way to show your support to a tool is to contribute to it.Though I'm not going to add a new feature (just yet) but I believe this is a good start.

Getting to know the server

Scalariver is using an embedded server called tiscaf. The way the server is designed follows the object oriented paradigm. Look at the original code of scalariver, the way the services are defined and registered to the server are so OO.

To learn more about tiscaf, http://gaydenko.com/scala/tiscaf/httpd/

Motivation

When learning scala, you cannot avoid functional programming. I believe that it is the best language to learn fp for oo programmers. Scala provides a safety net for those seeking to do more fp but aren't ready yet to do pure fp.

In this blog entry, the intention is to write this tool more functional and the way this is achieved is through the tools used. For the server, I'm going to use spray's embedded server called spray-can. I will also be using spray-routing for defining the services in a more easy to read and understand kind of way.

Bits and pieces explained

My version of scalariver only has one source file, ScalariverCan.scala, where the server, actor handler, and rest api are defined.

The entry point,

object Boot extends App {
implicit val river = ActorSystem("Scalariver")
val handler = river.actorOf(ScalariverHandler.props, name = "scalariver")
import com.typesafe.config._
import util.Properties
val serverPort = Properties.envOrElse("PORT", "8080").toInt
val conf = ConfigFactory.load()
val server = conf.getString("interface")
IO(Http) ! Http.Bind(handler, interface = server, port = serverPort)
}

In our Boot source, we will create the actor system, instantiate the actor handler that we will bind to spray-can.

The service handler,

object ScalariverHandler {
def props: Props = Props[ScalariverHandler]
}
class ScalariverHandler extends Actor
with FormattingService
with StaticContentService
with ActorLogging {
implicit val timeout: Timeout = 1.second
def actorRefFactory = context
def receive = runRoute(formatRoute ~ staticRoute)
}

This is our only actor that handles request to our spray-can server. As seen in its definition, it is mixin with two services we defined for this project ie FormattingService and StaticContentService.

The api services which includes the formatting service and static content service. These are http services that can be mixin to an actor and is required in order to bind to our spray-can server.

Formatting service is our main service that accepts the request only via POST with form data defined in scalariver original guide.

trait FormattingService extends HttpService {
implicit def executionContext = actorRefFactory.dispatcher
import FormattingService._
def formatRoute =
path("") {
post {
entity(as[FormData]) { formData
implicit val allParams = formData.fields.toMap
val source = allParams get SOURCE_FIELD
val version = allParams getOrElse (SCALA_VERSION, "2.10")
val Some(indentLevel: Int) = Some((allParams getOrElse (INDENT_LEVEL, "0")) toInt)
lazy val preferences = new FormattingPreferences(formatPreferences.toMap)
complete {
Try(ScalaFormatter.format(
source = source.get,
scalaVersion = version,
formattingPreferences = preferences,
initialIndentLevel = indentLevel))
}
}
}
}
}

Static content service is for allowing us to use the other web artefacts used by scalariver. This is basically the web frontend for those who wants to try it out which by the way I also made available at http://scalariver.herokuapp.com/

trait StaticContentService extends HttpService {
def staticRoute = path("") {
getFromResource("index.html")
} ~ getFromResourceDirectory("")
}

Conclusion

The implementation now follows a functional style approach through routes which are basically functions that is described best in spray-io website. Overall, it just made the code alot easier to understand as well as written as concise as it is intended.

You can also go view the complete project at https://github.com/ferrlin/scalariver.