I like very much object instantiation by map parameter. Anyway, it is very useful when you create complex object (for example from JSON or database).
Unfortunately, map object instantiation is not possible for classes which are @Immutable annotated and contains mutable objects.

Lets see it on the very simple groovy script (code bellow).
First create an MutableClass object with map as an constructor parameter. This class contains mutable field of type Sub.
Second try the same with ImmutableClass – it does not work.
What’s uncool : it is a RuntimeException … so be careful!

You can fix it by making Sub class also immutable – annotate it with @Immutable, too.

Target

I want to use log4j SocketAppender to log into logstash. It is pretty straight since Logstash has log4j input type – supports internally log4j.
Additionally, I want that log4j message will be send in JSON format and in that form comes into Elasticsearch. That is pretty important for me since Elasticsearch can be easily queried afterwards.
So, let’s start.

Solution

Download Logstash

Download logstash from http://logstash.net
into the project directory called „logstash”. You can download Logstash in anywhere you want but then please use a config file from „logstash” directory. In the other case example will not work for you.

Log entries, Maps, are converted to JSON String on the Java side and logged normally with log4j. Then send to Logstash by SocketAppender. Logstash gets field message, converts String to JSON format and saves it as msg field. It also mutate entry – all fields like message, path, priority, etc. are stripped – they are only a noise in my case. All stripped fields are not visible in Elsaticsearch / Kibana.
You can configure all this stuff in the logstash-log4j.conf config file.