Archive for the 'Heiko Seeberger' Category

SLF4S – Logging the Scala way

Do we need another logging framework in the Java/Scala world? Certainly not! As Scala is fully "downward" compatible to Java, we can use whatever Java logging solution we want. And there are many, aren't there?.

So why SLF4S? Well, SLF4S isn't another logging framework, but a very thin Scala wrapper around SLF4J which has emerged as the leading Java logging solution. Why do we need a Scala wrapper for SLF4S? Well, there are some nice Scala features that can make logging even easier and/or more performant.

First, SLF4J Loggers use by-name parameters which are only evaluated if needed/accessed. When logging "traditionally", we often create messages by concatenating Strings or using the String.format method, even if we don't need these messages in the end because the logging level is not enabled. Of course we could "manually" check whether the logging level is enabled, e.g. by calling logger.isDebugEnabled, but we often don't, because it's cumbersome. With by-name parameters we can simply call our log methods and let SLF4S check whether the log level is enabled. Just take a look at one example:
def debug(msg: => String) {
if (slf4jLogger.isDebugEnabled) slf4jLogger debug msg
}

Second, SLF4S offers a Logging trait which can be mixed into any class to make a Logger instance available. That particular Logger will be initialized with the name of the class it is mixed into which is a common use case.
class MyClazz extends SomeClazz with Logging
...
logger debug "SLF4S just rocks!"
...

Of course you can create Loggers with arbitrary names by calling Logger("SomeSpecialName").

Last but not least, SLF4S offers implicit conversions from "usual" SLF4J Loggers into "pimped" SLF4S Loggers.

Ah, and of course, SLF4S is OSGi compliant. But that's not a big surprise, taking into account that the authors are OSGi fanboys and SLF4J is OSGi compliant, too.

How to setup a Scala project with SBT and IDEA

Today I helped my mate Bernd Kolb setting up a simple Scala project. He had been struggling far too long with various options like Maven, SBT, Eclipse and Intellij IDEA. If I remember correctly it only took a 30 minutes conf call to setup a simple Scala and Lift project with SBT and IDEA. But there are quite a few things to know in order to be successful which I am going to describe here in a step-by-step tutorial. I hope you find it useful. Please let me know any issues.

Why SBT and IDEA?

Why not Maven and Eclipse? Or Ant and Netbeans? Or ...? First, we have to make a choice. Second, SBT and IDEA are currently the best build tool and the best IDE for Scala. SBT is written specifically for Scala and offers very fast compilation, interactive mode for continuous compilation, testing, etc., integration for Scala test tools like specs and ScalaTest, cross compiling against different Scala versions and many more. While the Scala IDE for Eclipse recently has made nice progress and the Netbeans plugin looks good, IDEA still offers the best Scala plugin with many features known from a Java IDE, e.g. refactroings, code completion, code navigation, etc.

Preparations

Java 5 or 6 is assumed. Get the SBT launcher and follow the instructions to set it up. Install IDEA 9.0.3 and use its plugin manager to install the Scala plugin. Here we go!

1. Create a SBT project

Create a folder for your project, cd there and run SBT. You will be asked the following questions. Answer like I did or chose different values (except for the Scala version).

Project does not exist, create new project? (y/N/s) y

Name: simple

Organization: localhost

Version [1.0]:

Scala version [2.7.7]: 2.8.0

sbt version [0.7.4]:


Now SBT will download Scala 2.7.7 as well as some other libraries for internal use. And it will download Scala 2.8.0 which is used to build your project.

As soon as the downloads are finished, you are in SBT's interactive mode. At the prompt enter compile, then ~test (press enter to leave the triggered mode) and then help to make yourself familiar with the features.

Looking at your project in the file system, you will notice a layout similar to Maven: Scala sources go into src/main/scala, Scala tests go into src/test/scala and artifacts go into target. If your project looks different from the one at the right, you probably did not run compile or test. But as it is important to run your project against the same version as it was compiled against, there is a Scala_2.8.0 folder between the target and the classes, test-classes etc.

Update

Thanks to Comments from Bart and Mikko I looked into the sbt-idea-plugin which makes it possible to create the project files for IDEA from SBT. While it is still under active development and there are some minor issues, the current snapshot release 0.1 already produces usable IDEA project files. So you could just go for that plugin and skip the next two steps.

2. Create an IDEA project

Now you have to create an IDEA project on top of your SBT project.

Choose File > New Project ..., select Create project from scratch and continue.

Then pick your project folder for Project files location and continue.

Then enter src/main/scala as path for the source directory and continue.


Now it is getting a little tricky!

Select Scala from the list of technologies.

Ignore the erroneous combo for the Version.

Choose Pick files from disk and select scala-compiler.jar and scala-library.jar form project/boot/scala-2.8.0/lib.

Then change the Name to scala-2.8.0 and click Finish.

3. Adjust IDEA project settings

Now you have make some adjustments to align SBT's and IDEA's project layout.


Choose Modules on the left and navigate to the Sources tab. Add src/main/resources to the Sources (blue) and src/test/scala and src/test/resources to the Test Sources (green). Exclude (red) .idea, lib, project/boot and target.

 


Next go to the Paths tab and select target/scala_2.8.0/classes for the Output path and target/scala_2.8.0/test-classes for the Test output path.

 


Then choose the Scala facet from the mid column (below the one and only module simple) and unchek Use Scala compilers ....

That's it! Now you are ready to go.

4. Give it a try

In IDEA go to the src/main/scala folder and choose New > Scala Class from the context menu. Call it Hello and make it an Object.

In the editor delete the package statement and enter the following code:

object Hello {

  def main(args: Array[String]) {

    println("Hello!")

  }

}

From the context menu choose Run Hello.main(). IDEA will build your project and then run this object.

After that go to SBT and enter ~run. Watch the output and look for the Hello! message. Then change the message in the code, e.g. to Hello, world!. As you have told SBT to use triggered run by prefixing whith the tilda, your project will be incrementally built and the Hello object run again: Watch the output.

Have fun with Scala, SBT and IDEA!

ScalaModules slides from W-JAX 09 online

There were a lot of interesting talks at the OSGi Day at W-JAX. If you are interested in the slides of my ScalaModules talk you can take it from here: http://www.slideshare.net/heiko.seeberger/wjax-09-scalamodules

Lift slides from W-JAX 09 online

The Scala Day at W-JAX was a great success: Many cool talks and lots of interested folks. If you are interested in the slides of my Lift talk you can take it from here: http://www.slideshare.net/heiko.seeberger/wjax-09-lift

Scala 2.8: Be more concise with named and default arguments

Scala 2.8 will bring quite a lot of interesting new features, e.g. redesigned collection libraries, named and default arguments, support for continuations, a pimped REPL, etc. In the following I will show how named and default arguments enable us to write our Scala code even more concisely than before.

Let's flesh out an example in the 2.7 style: An order with an ID, order items and a shipping mode.

case class Order27(id: Long,
items: List[Item],
mode: ShippingMode)

case class Item()

sealed trait ShippingMode
case object StandardShipping extends ShippingMode
case object ExpressShipping extends ShippingMode
case object OvernightShipping extends ShippingMode

The order's ID shall be "mandatory" while we want to allow for defaults for the item list and the shipping mode. Hence we have to provide some auxiliary constructors.

case class Order27(id: Long,
items: List[Item],
mode: ShippingMode) {

def this(id: Long, items: List[Item]) =
this(id, items, StandardShipping)

def this(id: Long, mode: ShippingMode) =
this(id, Nil, StandardShipping)

def this(id: Long) =
this(id, Nil, StandardShipping)
}

As you can see, now it is possible to create an order by only giving the ID, e.g.

val order = Order27(1)

will create an order with the items set to the empty list (OK, this does not make too much sense in practice) and the shipping mode set to standard shipping.

On the one hand that's nice. But on the other hand the code is blown up significantly and it will take the reader some time to reason about the different possibilities to create an order, what is mandatory and what is optional with defaults.

Scala 2.8 let's us define default values with the class (or method) parameters by simply putting the default values behind the type.

case class Order28(id: Long,
items: List[Item] = Nil,
mode: ShippingMode = StandardShipping)

Now we can leave out the arguments for which defaults are defined, e.g.

val order = Order28(1)

will again create an order with no items and standard shipping. But this time there is no auxiliary constructor necessary to achieve that. Wow!

But how can we give the shipping mode and leave out the items? Looking at the order of the parameters in the primary constructor it is obvious that we have to give the item list before the shipping mode.

val order = Order28(1, HERE GOES THE ITEM LIST, OvernightShipping)

This is where named arguments enter the game. We simply prepend an argument value with its name, e.g.

val order = Order28(1, mode = OvernightShipping)

This way Scala knows how to get things right. Wow!!

Invitation to improve ScalaModules’s DSL

Over the last months the ScalaModules team has worked on the upcoming 2.0 release. There will be a lot of improvements, e.g. auto-registration of service interfaces, operator notation, filters as objects and the user guide transferred to the Wiki. We are not ready for a final release yet, but most things should already be fairly stable.

There is still one thing we are racking our brains over a lot and maybe one of you could come up with a better solution that we have got right now. The new API for registering services offers auto-registration of service interfaces, such that there is no need to explicitly define the service interface(s). The following snippet will register the service greeting under the service interface Greeting, because greeting implements Greeting.

trait Greeting ...
val greeting = ...
ctx register greeting

Of course there are times when you want to explicitly register a service under a certain service interface. Now it would be very nice to write something like

ctx register greeting as classOf[AnotherInterface]

But this will not work in the current implementation, because register will be executed before as, which will register greeting under Greeting, just like above. Hence you have to use parenthesis like

ctx register (greeting as classOf[AnotherInterface])

Of course we have come up with a nice operator notation which takes the neccessary precedence into account. You could register greeting under the service interface AnotherInterface like this

ctx < greeting / classOf[AnotherInterface]

There is no need to use parenthesis here, because / will be executed first, because its precedence is higher than <.

But we would still like to get rid of the parenthesis in the "wordy" style. Roman already came up with an idea which you can take from the ScalaModules Google group. But when it comes to using as and withProps at the same time this is not adequate. So the question is, whether you have an idea how we could write something like

ctx register as classOf[AnotherInterface] withProps ("x" -> "y")

I am looking forward for your suggestions!

OSGi-fied Scala libraries updated to 2.7.6

Now that we have got Scala 2.7.6 I also updated the OSGi version of the Scala libraries. Please take it from the scala-tools.org Maven repository.

Currently there is an ongoing discussion about modularizing the official Scala code base, just take a look at the scala-internals mailing list. Hopefully we will see some success soon which might make the extra OSGi version obsolete though. But right now these extra OSGi-fied libraries are the way to go if you want to run OSGi on Scala or Scala on OSGi.

OSGi on Scala slides from OSGi DevCon Europe 09 online

In my former blog post I reasoned about whether I should do a live demo of OSGi on Scala / ScalaModules at OSGi DevCon Europe 09. As I received very positive feedback from the community (thanx for that!) I decided to go for it. Now I just finished my short talk and everything (at least the hacking part) went fine. For those not able to attend, please find the slides (which try to give you some live feeling) at my Slidespace.

Running OSGi and ScalaModules in Scala’s REPL

Next Monday I will talk about OSGi on Scala at OSGi DevCon Europe 09. As I have already given this talk twice (OSGi DevCon 09 and JAX 09), I am currently searching for some kind of fresh and cool style. Sitting in a very lonely German town I have come up with a crazy idea: Why not do the (short) talk using Scala's REPL (the interactive Scala console) instead of slides? To be honest, I am not yet sure whether to go this way, but my trials were very facinating and hence I would like to share my experiences with you.

OK, one step back. What exactly am I talking about? Well, fairly simple: Run the Scala REPL, launch OSGi (Felix, because it is very easy to launch/embed) to get a BundleContext (of the system bundle) and do some ScalaModules tricks to show the power of this DSL for OSGi.

In order to have Felix and ScalaModules on the classpath we have to copy felix.jar (currently using 1.8.0), scalamodules-core-1.1-SNAPSHOT.jar and scalamodules-util-1.1-SNAPSHOT.jar to a local directory and run Scala like this:

scala -cp felix.jar:scalamodules-core-1.1-SNAPSHOT.jar:scalamodules-util-1.1-SNAPSHOT.jar
scala>

First let's import some important stuff:

scala> import org.apache.felix.framework._
import org.apache.felix.framework._

scala> import org.scalamodules.core.RichBundleContext._
import org.scalamodules.core.RichBundleContext._

Then let's create and start Felix and get the BundleContext (which subsequently will be implicitly converted into a RichBundleContext):

scala> val felix = new Felix(null)
felix: org.apache.felix.framework.Felix = org.apache.felix.framework [0]

scala> felix.start

scala> val ctx = felix.getBundleContext
ctx: org.osgi.framework.BundleContext = org.apache.felix.framework.BundleContextImpl@e0c389

Then let's create a service interface:

scala> trait Greeting { def hello: String }
defined trait Greeting

Now let's use ScalaModules to (try to) get a Greeting service and use it. If you are experienced in OSGi you will know that for this task you would have to get a ServiceReference, check for null, get the service, check for null again and finally unget the ServiceReference again => Fairly low-level and involved. Now look at ScalaModules:

scala> ctx getOne classOf[Greeting] andApply { _.hello } match {
| case Some(s) => println(s)
| case None => println("No Greeting service available!")
| }
No Greeting service available!

OK, now let's register a Greeting service:

scala> val greeting = new Greeting { def hello = "Hello" }
greeting: java.lang.Object with Greeting = $anon$1@6159e9

scala> ctx registers classOf[String] theService greeting
:13: error: type mismatch;
found : java.lang.Object with Greeting
required: String
ctx registerAs classOf[String] theService greeting
^

As you can see, service registration with ScalaModules is type-safe at compile time. Hence let's do it right now and try to use it once more:

scala> ctx registerAs classOf[Greeting] theService greeting
res4: org.osgi.framework.ServiceRegistration = ...

scala> ctx getOne classOf[Greeting] andApply { _.hello } match {
| case Some(s) => println(s)
| case None => println("No Greeting service available!")
| }
Hello

There a lot of other things we could do the easy way using ScalaModules instead of OSGi API. I will show some more of these at my talk at OSGi DevCon Europe 2009, but first I have to decide whether using REPL for the talk is a good idea. What do you think?

OSGi-fied Scala libraries updated to 2.7.5

Some days ago Scala 2.7.5 was released and today I updated the OSGi version of the Scala libraries (see my former blog), too. I received some (positive) early feedback, but I am still very interested in knowing about any kind of real-world "production" usage.

Currently I am using these libraries in an effort to add OSGi support to Lift. This is very challenging, not only because of too little time, but also because Lift still has to work without OSGi. Well, hopefully I can get some basic OSGi support ready for Lift 1.1.