Skip to main content


Showing posts from April, 2013

SiftingAppender: logging different threads to different log files

One novel feature of Logback is SiftingAppender ( JavaDoc ). In short it's a proxy appender that creates one child appender per each unique value of a given runtime property. Typically this property is taken from MDC . Here is an example based on the official documentation linked above: <?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender"> <discriminator> <key>userid</key> <defaultValue>unknown</defaultValue> </discriminator> <sift> <appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender"> <file>user-${userid}.log</file> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{HH:mm:ss:SSS} | %-5level | %thr

WatchService combined with Akka actors

WatchService is a handy class that can notify you about any file system changes (create/update/delete of file) in a given set of directories. It is described nicely in the official documentation so I won't write another introduction tutorial. Instead we will try to combine it with Akka to provide fully asynchronous, non-blocking file system changes notification mechanism. And we will scale it both to multiple directories and multiple... servers! Just for starters here is a simple, self-descriptive example: val watchService = FileSystems.getDefault.newWatchService() Paths.get("/foo/bar").register(watchService, ENTRY_CREATE, ENTRY_DELETE) while(true) { val key = watchService.take() key.pollEvents() foreach { event => event.kind() match { case ENTRY_CREATE => //... case ENTRY_DELETE => //... case x => logger.warn(s"Unknown event $x") } } key.reset() } I kno

Scala traits implementation and interoperability. Part II: Traits linearization

This is a continuation of Scala traits implementation and interoperability. Part I: Basics . Dreadful diamond problem can be mitigated using Scala traits and a process called linearization . Take the following example: trait Base { def msg = "Base" } trait Foo extends Base { abstract override def msg = "Foo -> " + super.msg } trait Bar extends Base { abstract override def msg = "Bar -> " + super.msg } trait Buzz extends Base { abstract override def msg = "Buzz -> " + super.msg } class Riddle extends Base with Foo with Bar with Buzz { override def msg = "Riddle -> " + super.msg } Now let me ask you a little question: what is the output of (new Riddle).msg ? Riddle -> Base Riddle -> Buzz -> Base Riddle -> Foo -> Base Riddle -> Buzz -> Bar -> Foo -> Base It's not (1) because Base.msg is overriden by all traits we extend, so that shouldn't be a surprise. But i

Scala traits implementation and interoperability. Part I: Basics

Traits in Scala are similar to interfaces, but much more powerful. They allow implementations of some of the methods, fields, stacking, etc. But have you ever wondered how are they implemented on top of JVM? How is it possible to extend multiple traits and where the implementations go to? In this article, based on my StackOverflow answer , I will give several trait examples and explain how scalac implements them, what are the drawbacks and what you get for free. Often we will look at compiled classes and decompile them to Java. It's not essential knowledge, but I hope you'll enjoy it. All examples are compiled against Scala 2.10.1. Simple trait with no method implementations The following trait: trait Solver { def answer(question: String): Int } compiles down to the most boring Java interface: