Eclipse IDE for Leon

This monday the first version of our Leon plugin for Eclipse was released. It adds a Leon project wizard, a Leon project property page and content assist for the Leon configuration file.

The Leon project wizard

Via the Leon project wizard a new Leon project is created. Javascript libraries and the default JRE is added automatically to the project as well as some sample files and a corresponding Leon configuration file.

Content Assistance

If you open the Leon configuration file in the Eclipse build-in javascript editor, you will find content proposals for the methods provided by the leon framework.

Posted in News | Comments Off

Building AJAX/Comet applications with Leon

In this post I will show you a simple ajax and comet-enabled web application which is implemented using Leon Framework our new baby. Leon applications are running on the JVM and are implemented in HTML, CSS and JavaScript.

What it does

The Leon JAX sample is a simple twitter-like web application. You enter your name and a channel (or room) you want to post a message to. By pressing the submit button your message will be send to the web server which distributes the message to all users which have selected the same room. This technique is called Comet and the goal of this simple demo is to show how easy it is to develop an AJAX and Comet enabled web application using Leon Framework.

Get the demo

Before I show you some aspects of the implementation you need to checkout the project from github:

$ git clone git@github.com:mrico/leon.git

Now you can start the sample application by using sbt. (Please be patient while sbt is downloading the internet …).

$ cd leon
$ bin/sbt
> container:start
...
[success] Total time: 6 s,

Navigate your browser to the following URL to see the demo application:

  • http://localhost:8080/leonjax

Leon Web application

To see Comet in action launch another browser and point it to the same URL. Enter your name and select the same room in both browser windows. Now send a message and it will be displayed on both browser windows. Please note that all browsers will only get messages from users in the same room.

How it works?

Now we come to the interesting part – the code :-)

You can find the code of the demo application in:

$ cd leon-samples/leonjax

Folder structure

Here you can see the structure of an basic Leon web application. First of all the config.js file, where all Leon modules are configured.

The configuration file

config.js

First we install the CoffeeScript module. With this single line we are now able to write our server- and client-side code in CoffeeScript which get compiled to JavaScript instantly. Leon comes with many more modules like LeonMongoModule or LessModule and additional modules can be implemented easily. In this demo we will only use CoffeeScript.

With addLocation we register a folder which holds all HTML, CSS, JavaScript (client- and server-side) files.

To implement server-side functions you write JavaScript (or better CoffeeScript) files which can be loaded into the server runtime by the loadFile command. If you look into the www folder you will only find a leonjax_server.coffee file. The corresponding .js-file will be compiled instantly by the Leon CoffeeScriptModule.

The last statement gives client access to functions of a server-side JavaScript object called leonJaxServer, which has been loaded before.

The client-side – Some HTML, a bit of CSS and CoffeeScript

On the client-side we use normal HTML, CSS (or use Less) and AngularJS, a MVC framework written in JavaScript. AngularJS keeps your model and view in sync automatically, without the need of extra boiler-plate code. See the AngularJS documentation for more details. Our controller LeonJaxCtrl is located in browser/controllers.coffee. (If you don’t want to read CoffeeScript you can navigate your browser to http://localhost:8080/leonjax/browser/controllers.js to see the generated JavaScript code).

controllers.coffee

Calling server-side functions via Ajax

In the Leon configuration we had the following statement to expose a server-side function to clients: browser("leonJaxService").linksToServer();. Now you can see the invocation of a server-side function called postMessage from the browser:

  server.leonJaxService("postMessage")(@user.name, @user.room.name, message)

The postMessage function publishes the message to the clients via Comet. (see the lenjax_server.coffee file).

Subscribe a page to a Comet channel.

With Leon you use a server-side tag <leon:subscribe /> in your HTML file to subscribe to a Comet channel. In our demo application we have the following Comet subscription in www/index.html:

Leon Web application

In this example the page subscribes to a topic called leonjax.room.messages and it registers a callback function called handleMessage (which is implemented in browser/controller.coffee). The function gets called every time the page receives a new message from the server. If you publish a message to a topic, every user who stays on a page which is subscribed to that topic will receive the message

Filter messages by the current room

In our demo we only want to receive messages of users who stay in the same room. For that case, you can set and update some filter rules. All filters will be applied on the server-side and only messages which have passed the filter will be send to the client.

Filter values are valid for one unique page view. Means, that every single requested page has its own filter rules.

To set a filter, we have to declare the fields we are interested in with the attribute filterOn in <leon:subscribe /> first. Here you specify the field names seperated by comma.

Then we can update our filter by calling a JavaScript function called leon.comet.updateFilter. This is the updateFilter call in our demo application which will be executed every time the user selects another room.

leon.comet.updateFilter("leonjax.room.messages", "room", @user.room.name)

So now I have shown you all the implementation of the key functionalities of the demo application. Wasn’t it easy? In summary, the main implementation of our demo application lives in three files:

  • the index.html with the HTML code
  • the browser/controller.coffee file with the client-side logic (~ 20 lines of code)
  • the leonjax_server.coffeee file with the server-side logic (3 lines of code)

I hope you enjoyed this short exploration through a simple Leon Web Application. Check out http://leon.io for more …

Posted in News | Comments Off

SBT-Eclipse Integration

Yay, we finally have got a really good Eclipse plugin for Scala. Thanks to all the contributors for their great work (as a former Eclipse committer I know that it was hard work). But as lots of Scala projects use SBT as their build tool, a new need is arising, the need for an integration of SBT and Eclipse. For the last one and a half years or so I have been using SBT and IntelliJ IDEA, because the Scala plugin for IDEA is awesome and, most important, there is a really good SBT-IDEA integration. It is provided by the sbt-idea project which I take as an inspiring example for what I would like to achieve for SBT-Eclipse integration.

Therefore I started the sbteclipse project which aims at providing the same features as sbt-idea, i.e. the ability to create Eclipse project files (.project and .classpath) from an SBT project. As SBT will soon be on version 0.9 which differs a great lot from version 0.7 from a plugin developer’s perspective, I decided to develop sbteclipse as a plugin for SBT 0.9.

While there is still a very long way to go, I just released the very first version 0.1 of sbteclipse to the Typesafe repository which means that you can use it easily. Right now it will only create a single project with its source- and class-directories. Libraries and multi-module projects are not yet supported. And of course you will have to build SBT 0.9 on your own, because there are no binaries yet.

If you are interested, please take a look at the “Usage” section of the sbteclipse README. I would be glad to get your feedback, of course. Have fun!


Posted in Scala | Comments Off

Applicatives are generalized functors

In my previous blog post about categories and functors I already threatened you with the possibility of a follow-up. Well, here we go. Actually I won’t talk about category theory this time, but about an important abstraction from the world of advanced (at least in my understanding) functional programming which turns out to be a close relative to the now well understood functor.

Functors

Just in case you don’t remember exactly what a functor looks like, here comes the definition:

trait GenericFunctor[->>[_, _], ->>>[_, _], F[_]] {

  def fmap[A, B](f: A ->> B): F[A] ->>> F[B]
}

trait Functor[F[_]] extends GenericFunctor[Function, Function, F] {

  final def fmap[A, B](as: F[A])(f: A => B): F[B] =
    fmap(f)(as)
}

For the sake of simplicity we will stick to the more specific Functor definition throughout the rest of this post. Such a functor is an endofunctor, because its source and target are the same (the category of Scala types and Scala functions). Maybe you remember that such a functor can be regarded as a provider of a computational context: The function f: A => B you give to fmap is lifted into the functor’s context which means that it is executed (maybe once, maybe several times or maybe even not at all) under the control of the functor.

As an example let’s look at how the OptionFunctor defined in the previous blog post is working: If we give fmap a Some the given function will be invoked, if we give it a None it won’t be invoked.

scala> fmap(Option(1)) { x => println("I was invoked!"); x + 1 }
I was invoked!
res0: Option[Int] = Some(2)

scala> fmap(None: Option[Int]) { x => println("I was invoked!"); x + 1 }
res1: Option[Int] = None

So far, so good. Using functors we can lift functions of arity-1 into a computational context.

Applicatives

But what if we have a function of higher arity? Can we still use a functor to lift a function of, let’s say, arity-2?

Let’s look at what happens if we call fmap to partially apply an arity-2 function to its first argument within the computational context of an Option:

scala> val f = (x: Int) => (y: Int) => x + y + 10
f: (Int) => (Int) => Int = <function1>

scala> fmap(Option(1))(f)
res0: Option[(Int) => Int] = Some()

What we get back is an Option[Int => Int], i.e. the “rest” of the partially applied function wrapped in an Option. Now we have a problem, because we cannot give this lifted function to another call of fmap.

scala> fmap(Option(2))(fmap(Option(1))(f))
:13: error: type mismatch;
 found   : Option[(Int) => Int]
 required: (Int) => ?
       fmap(Option(2))(fmap(Option(1))(f))

Of course we cannot, because fmap expects a pure function, not a lifted one. And that’s the moment when applicatives enter the stage. The idea is simple and follows intutively from what we have just seen: Instead of fmap taking a pure function, an Applicative defines the method apply taking a lifted function. And it defines the method pure to lift pure functions. Using these it is perfectly possible to partially apply an arity-n function to all of its arguments within a computational context. Before we look at our example from this new perspective, let’s code up our new abstraction:

trait Applicative[F[_]] extends Functor[F] {

  def pure[A](a: A): F[A]

  def apply[A, B](f: F[A => B]): F[A] => F[B]

  final def apply[A, B](fa: F[A])(f: F[A => B]): F[B] =
    apply(f)(fa)

  override def fmap[A, B](f: A => B): F[A] => F[B] =
    apply(pure(f))
}

As you can see, there is a strong relation between functors and applicatives: Each applicative is a functor and by one of the laws for applicatives the following has to hold true: fmap = apply ο pure. Well, this law is pretty intuitive, because it makes sure we can use an applicative as a functor, i.e. for a pure arity-1 function, and it will behave as expected.

In order to be able to work with applicatives we need some scaffolding and for our Option example we need an implementation of Applicative:

object Applicative {

  def pure[A, F[_]](a: A)(implicit applicative: Applicative[F]): F[A] =
    applicative pure a

  def apply[A, B, F[_]](fa: F[A])(f: F[A => B])(implicit applicative: Applicative[F]): F[B] =
    applicative.apply(fa)(f)

  implicit object OptionApplicative extends Applicative[Option] {

    override def pure[A](a: A): Option[A] =
      Option(a)

    override def apply[A, B](f: Option[A => B]): Option[A] => Option[B] =
      o => for { a <- o; p <- f } yield p(a)
    }
}

Now let’s look at our example from above with an arity-2 function. Using a functor we got stuck, but using an applicative we can make it all the way through the two arguments:

scala> apply(Option(1))(apply(Option(2))(pure(f)))
res0: Option[Int] = Some(13)

Ain’t that nice? You might answer, that this code looks cumbersome and is not necessary at all. Regarding the first argument please read on. Regarding the second: Yes, of course we don’t need an applicative for Option, because it already offers flatMap which does the job. But with this type class approach we can deal with any class, e.g. with Either from the Scala standard library or with classes from our own projects.

Conclusion

You have seen the basic principle of applicatives: We can apply functions of arbitrary arity (well, greater or even one) to its arguments within a computational context. As functors provide exactly this for arity-1, applicatives are generalized functors.

Thanks to Scala’s flexibility we can of course do much better than above. Using a little pimp my library and some operators we can get something that’s elegant and useful. Luckily the scalaz folks have already done this, so I will just show two ways of expressing the above example using this awesome library:

scala> Option(1) <*> (Option(2) <*> Option(f))
res0: Option[Int] = Some(13)

scala> (Option(1) <**> Option(2)) { _ + _ + 10 }
res1: Option[Int] = Some(13)

Now this is really nice, isn’t it? Especially the second one looks very concise and intuitive. And as I stated above we can use it for types that don’t bring helpful methods like flatMap. Let’s conclude with another example using Either which is a perfect candidate to be used for results that might fail with well defined errors:

scala> (1.right[String] <**> 2.right[String]) { _ + _ + 10 }     
res0: Either[String,Int] = Right(13)

scala> (1.right[String] <**> "Error".left[Int]) { _ + _ + 10 }
res1: Either[String,Int] = Left(Error)

If you are interested in the code examples shown above, you can find these here: https://github.com/weiglewilczek/fun


Posted in Functional Programming, Scala | Comments Off

Introduction to Category Theory in Scala

If you are a former Java developer and have become a Scala fanboy like me, you will probably sooner or later encounter terms like monad, functor or other mysteries from the realm of category theory which make you feel like a little dummkopf (screamingly funny for a German like me, according to www.dict.cc this seems to be a proper English verb). If you already feel comfortable with these, don’t waste your time and move along. But if not, I would like to invite you to a little sightseeing trip that reflects my efforts to get to know this secret realm somewhere in between abstract mathematics and computer science.

This blog post is meant to be an introduction. Depending on the effect on my health (while writing I’m often afraid that my head might explode), my future spare time (understanding comes very slowly, if at all) and your feedback, I am going to write a follow-up. But for now let’s get started.

What’s a category?

Obviously this should be the first question when talking about category theory, although in my opinion the concept of a category is not too useful for programming. Here comes a comprehensive answer:

A category is made up from objects and maps (aka morphisms or arrows) between these objects. Maps can be composed in an associative fashion and for each object there is an identity map which is neutral with regard to composition.

Objects can be anything, but let’s look at a simple case: The category of finite sets. The diagram below depicts two such finite sets as well as a map from the one called source (aka domain) to the other called target (aka codomain).

A little more formally, we can call the domain A and the codomain B and write the map like this:

f: A → B

Now what’s composition? Let’s look at the next diagram, where I added another finite set and another map. Please don’t worry that in this strange world eating habits are different from what you might know ;-)

Let’s call the new set C and the new map g: B → C. Obviously we can get from A to C by first following f and then g. Therefore we get a new map from composing f and g:

g ο f: A → C

Now that we know composition, we have to talk about associativity and identity. Let’s add another map h: C → D. Then the associativity law requires the following to hold true:

(h ο g) ο f = h ο (g ο f)

Associativity should become clear pretty fast from thinking of addition or multiplication of numbers. Therefore let’s move along towards the identity laws. These require that for each object X of the category there is an identity map 1X: X → X which satisfies the following rules:

  • f ο 1A = f
  • 1B ο f = f

The following diagram depicts an identity map in our example category of finite sets. Obviously for identity maps the domain and codomain are the same object.

OK, that’s it. That’s categories. Objects, maps, composition, associativity and identity. If you would like to dive a little deeper into the theory, I recommend Wikipedia or “Conceptual Mathematics” by Lawvere and Schanuel. I will move along and look at categories from a Scala point of view.

Categories in Scala

Note: In the following I will borrow a lot of ideas and even some (slightly modified) code from the scalaz project. This Scala library, together with the Apocalisp blog, provides an incredibly valuable source of information and inspiration about advanced functional programming in Scala.

Now that we have investigated the category of finite sets, let’s implement another one in Scala. Therefore we consider the category made up from Scala types as objects and Scala functions as maps. We still have to prove that this is a category, but first let’s code it up:

object Category {
  def id[A]: A => A = a => a
  def compose[A, B, C](g: B => C, f: A => B): A => C =
    g compose f // This is Function.compose, not a recursive call!
}

OK, it looks like we have all the ingredients we need: Types are objects, functions with one argument (trait Function) are maps, id returns the identity function for each A and compose composes two functions.

It looks obvious, that the associativity and identity laws are satisfied, but better let’s check using a simple unit test written using the awesome specs and ScalaCheck frameworks:

class CategorySpec extends Specification with ScalaCheck {
  import Category._

  "A Category" should {

    val f = (i: Int) => i.toString
    val g = (s: String) => s.length
    val h = (i: Int) => i * i

    "satisfy associativity" in {
      Prop forAll { (i: Int) =>
        compose(h, compose(g, f))(i) == compose(compose(h, g), f)(i)
      } must pass
    }

    "satisfy identity" in {
      Prop forAll { (i: Int) =>
        compose(f, id[Int])(i) mustEqual compose(id[String], f)(i)
      } must pass
    }
  }
}

OK, so now we know that Category indeed adheres to the category laws. But that’s not the end of our story! Let’s move along to a more general category in Scala: While sticking to the Scala types as objects we will use the type constructor ->> for the maps.

trait GenericCategory[->>[_, _]] {
  def id[A]: A ->> A
  def compose[A, B, C](g: B ->> C, f: A ->> B): A ->> C
}

Please note, that A ->> B is just another way to write ->>[A, B], which nicely reflects the fact that we are talking about maps here.

Of course our Category is an implementation of this GenericCategory:

object Category extends GenericCategory[Function] {
  def id[A]: A => A = a => a
  def compose[A, B, C](g: B => C, f: A => B): A => C =
    g compose f // This is Function.compose, not a recursive call!
}

If you are interested in further types of categories, don’t hesitate to take a look at scalaz: You can find numerous categories there, e.g. a category of partial functions or a monoid category. I will keep it that way and move along to another important concept in category theory.

Functors

Now that we know categories and how to represent certain ones in Scala, let’s look at another important concept of category theory, which is also very important for functional programming. Consider two categories C1 and C2; then a functor F is a structure-preserving mapping between these categories.

OK, but what does that mean? A mapping between categories simply means that

  • every object A ∈ C1 is mapped to to an object F(A) ∈ C2 and
  • every map A → B between two objects A, B ∈ C1 is mapped to a map F(A) → F(B) between two objects F(A), F(B) ∈ C2.

In order to preserve the category structure this mapping must preserve the identity maps and the compositions. More formally:

  • F(1A) = 1F(A) ∀ A ∈ C1
  • F(g ο f) = F(g) ο F(f) ∀ f: A → B, g: B → C where A, B, C ∈ C1

Before thinking about the “meaning” of a functor, let’s code it up in Scala using our GenericCategory (of Scala types and arbitrary maps between these) as foundation:

trait GenericFunctor[->>[_, _], ->>>[_, _], F[_]] {
  def fmap[A, B](f: A ->> B): F[A] ->>> F[B]
}

Again, ->> and ->>> as well as F are type constructors. Looking at the ingredients, we find all that we need: Types A and B are mapped to types F[A] and F[B] and maps A ->> B are mapped to maps F[A] ->>> F[B].

Now let’s move along from arbitrary maps to Scala functions, i.e. choose our Category as source and target of the functor. This results in a so called endofunctor (same source and target) and looks like the following:

trait Functor[F[_]] extends GenericFunctor[Function, Function, F] {
  final def fmap[A, B](as: F[A])(f: A => B): F[B] =
    fmap(f)(as)
}

Please note, that the new fmap method is just for convenience and delegates to the inherited one. Using the higher kinded type for the first parameter list makes it possible to infer the type of A for the function in the second parameter list.

In order to code up some examples, we have to specify the type constructor F. Let’s start with good old List:

object ListFunctor extends Functor[List] {
  def fmap[A, B](f: A => B): List[A] => List[B] = as => as map f
}

This one let’s us map a function over a List, which means that this functor looks like a container that allows us to apply a function to all of its elements. This is a very intuitive way to think about functors. And it makes clear, that functors are a very important concept for functional programming, because if you look at the collections of the Scala library, you will see, that all of them provide this “mapping a function over the elements”.

OK, let’s see how we can use that. Therefore we add a Functor object, move our ListFunctor into that and make it implicit and add a generic fmap method:

object Functor {

  def fmap[A, B, F[_]](as: F[A])(f: A => B)(implicit functor: Functor[F]): F[B] =
    functor.fmap(as)(f)

  implicit object ListFunctor extends Functor[List] {
    def fmap[A, B](f: A => B): List[A] => List[B] =
      as => as map f
  }
}

Welcome type classes! The new generic fmap method takes an additional and implicit parameter of type Functor parameterized with a higher kinded type. When we call this method with an instance of this higher kinded type and a function but no functor, the compiler will look for a matching implicit value. Let’s see it in action:

scala> import com.weiglewilczek.cats.Functor._
import com.weiglewilczek.cats.Functor._

scala> fmap(List(1, 2, 3))(x => x + 1)        
res0: List[Int] = List(2, 3, 4)

While we could have reached the same result by simply calling map on the List instance, we now have something more general: A fmap method that works for any type for which we provide a functor.

We still have to verify that our ListFunctionFunctor satisfies the functor laws. Hence we write another unit test:

class ListFunctorTest extends Specification with ScalaCheck {
  import Functor.ListFunctor._

  "A ListFunctor" should {

    "preserve identity" in {
      val stringID = (s: String) => s
      val stringListID = (ss: List[String]) => ss
      Prop forAll { (ss: List[String]) =>
        fmap(stringID)(ss) == stringListID(ss)
      } must pass
    }

    "preserve composition" in {
      val f = (i: Int) => i.toString
      val g = (s: String) => s.length
      Prop forAll { (is: List[Int]) =>
        fmap(g compose f)(is) == (fmap(g) compose fmap(f))(is)
      } must pass
    }
  }
}

Fine! Now let’s look at another example. Why not use Option as type constructor for the Functor trait?

implicit object OptionFunctor extends Functor[Option] {
  def fmap[A, B](f: A => B): Option[A] => Option[B] =
    o => o map f
}

This one let’s us map a function over an Option, which can be thought of as applying the function in the context of the Option. If it is None, the function won’t be applied, if it is Some, it will be applied. This “computational context” is another way of looking at functors which sometimes is called “lifting” of functions: The function is lifted from its normal context to the functor’s context.

Let’s code up another example that makes this interpretation even more obvious. Now we use Function0 as type constructor for the Functor trait:

implicit object Function0Functor extends Functor[Function0] {
  def fmap[A, B](f: A => B): Function0[A] => Function0[B] =
    a => () => f(a())
}

Let’s see this one in action:

scala> val f = (s: String) => s.length
f: (String) => Int = <function1>

scala> val lifted = fmap(() => "abc")(f)
lifted: () => Int = <function0>

scala> lifted()
res1: Int = 3

As you can see, the function f is lifted into the context of the given Function0, i.e. it works on the output of that.

Conclusion

In this blog post we looked at two basic objects from category theory: Categories and functors. Of course there are others, some of them heavily used (e.g. monads), but I will keep it like that for now. Hopefully I could show you that category theory offers some interesting and valuable concepts that can be applied to and expressed in Scala. As I consider myself still a rookie in category theory, I’d be happy to get your feedback.

If you are interested in the code examples shown above, you can find these here: https://github.com/weiglewilczek/fun


Posted in Category Theory, Functional Programming, Scala | Comments Off

Our Blog reloaded

Our blog has been there for quite a while, but lately we didn’t give much love to it. As we believe that blogging is still a valuable means of communication, even in times of the likes of Twitter and Facebook, we decided to reload our blog. Hoping that you like it, please let us know if you have any kind of feedback.

Posted in News | Comments Off

Fully automated Web Application Testing with Selenium and Hudson

Lately i have been setting up a fully autometd Web Application Test environment. I just wanted to share my experiences!

My application has a number of selenium tests that i wanted to run on our continious integration server (hudson). My current scenario includes the following steps:
  1. Start the Selenium-RC server from Hudson
  2. Compile the application and the test cases
  3. Reinitialization of the database via DBUnit
  4. Starting the Tomcat - application server
  5. Running the Selenium test cases
  6. Publish the test results in Hudson

Start the Selenium-RC server on Hudson
The Selenium RC server is started from Hudson at the beginning of each build as a shell call.


As you can see in the picture this step is done before i trigger an ant script which includes all the following steps. Therefore it is imperative that a user is logged on to the DISPLAY =: 0.

The full command is here (As you can see, i also specified the path to a logfile):
DISPLAY=:0 java -jar ${WORKSPACE}/ecm.server/lib/test/selenium/selenium-server.jar -log ${WORKSPACE}/ecm.server/selenium.log &



Compile the application of the test cases by Ant +

The first step that is triggered from the ant script is a full build of the webapplication and the selenium test cases.

Reinitialization of the database from Ant via DBUnit

The next step is a full reset of the database used by the application with a initial set of data. Using DBUnit this can be done very easy. I just made an export from an initial dataset which is written to the database every build. Here you can see the ant target which does the job.

   

Starting the Tomcat - application server from Hudson

I also setup a dedicated tomcat on the build machine used for the selenium testcases. It is started from the Ant script in the next step. You can see the ant script here, note that ant is waiting until tomcat is started up by checking if the webport of tomcat is online.




Running the Selenium test cases from Hudson, by Ant

the Selenium tests are also run from Antwith the following ant script:


As you can see at first i delete the old test results. After that the tests are run via the testng ant task using ReportNG to generate some nice looking test results.


Publish the test results in Hudson

After the tests are run i use two hudson Post-build Actions to publish the test results.




The first is Archive the artifacts:
This Actions archives all resources of the specified folder from the last build. Thiese are the generated TestResults which provide some nice looking results.

In order to get statistics of all test cases ever run i also use the Action Publish JUnit test result report, which uses the Junit xml Resultfiles and generates statisics.

The result can be seen in the hudson project page. There you see an overview of the test statisics.



By clicking on the archived "index.html" you can display the reportng testresult:


Cheers
Posted in hudson, selenium, testing, testng | Tagged | Comments Off

IP Address based Logging in JSF

This article describes how to add more significance to your Log4J log files in a JSF (or any Web) environment, by adding the client specific information to the log files. Even if you already have decent logging in your application, log files can be often very hard to read if you have several users connecting to your website at the same time. The (nearly) only unique attribute of a user is his/her IP address.

This article will describe how to add a client’s IP address to your JSF application’s logging in a very easy way. It is based on Log4J and uses the Message Diagnostic Context (MDC) to add client based logging information.

MDC

MDC is an instrument in Log4J to distinguish interleaving log output from different sources. Log output is typically interleaved when a server handles multiple clients simultaneously. We will make use of this mechanism to distinguish different clients according to their IP addresses.

Add IP address information to Log4J’s MDC

First we need to add the client’s IP address to the MDC. Therefore we read the client’s IP address in the Faces Servlet and store it to the MDC. Below you see the definition of the Servlet in web.xml and an excerpt from the Servlet Code.

web.xml


 Faces Servlet
 
     com.weiglewilczek.jsf.CustomFacesServlet
 
 -1

Servlet

public class CustomFacesServlet implements Servlet
{
   …
   public void service(ServletRequest request, ServletResponse response)
 throws IOException, ServletException
  {
      String remoteAddress = request.getRemoteAddr();
      MDC.put("remoteAddress", remoteAddress);
       m_Delegate.service(request, response);
  }
}

First the client’s IP address is read from the request with the method request.getRemoteAddr() and stored into a variable “remoteAddress”. This information is added to the MDC with the key “remoteAddress” by calling MDC.put(”remoteAddress”, remoteAddress). Note that all MDC methods are static.

Log4J configuration

Below you see the Log4j conversion pattern which includes our MDC information added above. The argument “%X{remoteAddress}” reads the value, identified by the key “remoteAddress” from the MDC.

Log4j.appender.CONSOLE.layout.conversionPattern=%d{ABSOLUTE}
%-5p [%c{1}] - %X{remoteAddress}: %m%n

Result

The Log now includes the IP Address:

2008-08-18 09:05:48,543 INFO [com.weiglewilczek.jsf….] – 127.0.0.1: Logging Output
Posted in JSF, Log4j | Tagged | Comments Off