Jeff Mesnil
Weblog · About

Jazz a Vienne 2010

July 2, 2010

Yesterday, Joe Cocker was at Jazz a Vienne and it was thrilling to listen to him:

I love going to Jazz a Vienne: the location is spectacular, the sound is great and the artists are always top notch!

I was annoyed that the security did not let me keep my camera. I wanted to take some nice pictures with my 70-300mm and all I had was my iPhone and some low-quality HDR snapshots...

Surf & Volcanoes at Lanzarote

June 23, 2010

I just spent one week at Lanzarote in the Canary Islands to learn surfing, do some sightseeing and take some pictures.

It was my first surf experience and I managed to ride some waves at the end of the week (no, it's not me on the picture above, my waves were smaller) and loved the feeling. Once up on the board, it reminded me of snowboard but even more intense and more lively as I have to adapt to the wave, its shape, its speed and direction.
However I was also surprised by the amount of paddling which was required, I must have paddled 10 minutes against the waves for every 10 seconds up on the board. But every one of these 10 seconds was worth it :)

If you want to learn surfing at Lanzarote, I recommend Volcano Surf School. Sabine and Seb are very friendly, passionate about surf and Nico is a great teacher. Tell'em hi from me!

Just before going to Lanzarote, I bought a new zoom lens: a Nikon 70-300mm /4.5 AF-S VR which was great to shoot surfers and birds. Unfortunately I did not have a lot of time to get used to it and learnt on the fly how to use it properly. The surfer picture above is one of the last I took when I finally started to get a handle on the lens.

Lanzarote's landscape is spectacular with many volcanoes of different heights and shapes.
The volcano below was the main location of the greatest recorded eruptions which occurred between 1730 and 1736:

Volcano of Timanfaya National Park

The wineyards are also spectacular: they are buried in the volcanic soil and protected from the wind by small stone walls:

Canaries 953

This week was lots of fun, lots of sport and lots of good food and wine!
I made some good new friends and I am looking forward to surfing again. Next time won't come soon enough!

Cocoa Programming

May 20, 2010

I just received my copy of Cocoa Programming. At first glance, the book seems a good update for Mac OS X development.

It has been quite a few months since I did Mac (and iPhone) programming. I have not looked deeply at Core Data and Grand Central Dispatch yet. I also want to experiment with Objective-C blocks.

I need to find a suitable idea for a Mac application to prototype and experiment. Any idea or suggestion is welcome!

Web Sockets Support for HornetQ

April 29, 2010

Exchanging messages directly between a Web browser and a messaging server is an interesting use case. There are many ways to do this (AJAX, Comet, etc.). The most recent way is to use Web Sockets.

What are Web Sockets?

Web Sockets are "TCP for the Web". A Web Socket is a bi-directional communication between a browser and a server that follows the HTTP same-origin model (you can only connect to a server on the same origin than the HTTP request that served the page).

Web Sockets support has been checked in HornetQ Subversion repository. Since Web Sockets are like TCP sockets, we needed to add a protocol on top of it with messaging semantic. A perfect candidate for this was Stomp, a text-base messaging protocol.
I have created a JavaScript library, stomp-websocket, which makes it very simple to send and receive Stomp messages over Web Sockets.

This library is not bound to HornetQ implementation. Dejan Bosanac, from Apache ActiveMQ, also added Web Sockets support to ActiveMQ. A browser can use the stomp-webscoket library to exchange messages with either HornetQ or ActiveMQ.

Example

How do you send a message from the browser to a Stomp broker? The steps are always the same:

  1. create a Stomp.client with the broker endpoint URL
  2. connect to the broker with user credentials
  3. register a callback to be notified when the client is connected and authenticated
  4. send a message to the broker on a given destination
var client = Stomp.client("ws://blackbook.local:61614/stomp");
client.connect("guest", "guest", function() {
   // called back after the client is connected and authenticated to the Stomp server
   client.send("/queue/test", {priority: 9}, "Hello, from the browser");
});

Receiving messages from the broker involves an additional step where the client subscribes to a destination:

client.subscribe("/queue/test", function(message)
{
  // called back every time the client receives a message from the broker for the destination
  $("#messages").append("<p>" + message.body + "</p>\n");
};

stomp-websocket documentation explains in more details how to use the library. The project is hosted on GitHub and ships with a chat example where browser clients sends and receives messages from a topic.

HornetQ Implementation

Web Socket and Stomp support in HornetQ are quite new and a bit rough around the edges (e.g. no implicit mapping between Stomp message and JMS messages, destinations mapping to addresses and queues). Do not hesitate to report issues in HornetQ bug tracker and contribute patches.

To accept Web Sockets connection from port 61614, add a <acceptor> to hornetq-configuration.xml:

<acceptor name="stomp-ws-acceptor">
   <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
   <param value="stomp_ws" key="protocol"></param>
   <param value="61614" key="port"></param>
</acceptor>

Web Sockets can then connect to ws://localhost:61614/stomp endpoint.

Web Sockets Status

Web Sockets is a recent Web technology and few browsers support it (only WebKit nightly builds and Google Chrome at the moment). The protocol is a moving target (at the time of this writing, the handshake specification is changing significantely) and applications using Web Sockets may break until browsers and servers agree on the protocol.

Besides, the specification status is a bit unclear. The protocol is at the IETF but the revised draft is at WHATWG, while the browser API is at W3C. Mozilla is cautious (with reasons) to add it to Firefox and I have not seen any indication that Internet Explorer will support it.
It is likely that its use on the desktop will not be widespread soon. However it may really shine on mobile platforms.

Both the iPhone and Android Web browsers are based on WebKit. Future releases of the platforms will likely add support for Web Sockets (but I did not find any roadmap for it...). With Web Sockets, browsers on Android, iPhone, iPad will be able to send and receive messages in a simple and efficient fashion. Combining that with offline support, Web developers have great tools to build Web applications.

I am looking forward to seeing what they will come up with!

jmx4r: How to Use Dotted MBean Attribute Names

January 20, 2010

An user reported an issue with jmx4r because he was not able to access a MBean attribute.

See for example attribute names under the amx:j2eeType=X-MonitoringDottedNames,name=na mbean of a GlassFish instance.

Trying to get the value of an attribute like server.http_service.file_cache.maxentries_lastsampletime doesn't work.

He is right that jmx4r does not work with dotted attributes. For example, this code will fail:

server = JMX::MBean.find_by_name "amx:j2eeType=X-MonitoringDottedNames,name=na"
puts server.http_service.file_cache.maxentries_lastsampletime

JMX supports dotted attributes but they can not be used directly with jmx4r because of Ruby syntax.
Ruby will read

`server.http_service.file_cache.maxentries_lastsampletime`

and will rightfully call http_service on the server object first. But there is no such method or attribute and the call will fail.

To circumvent this issue and be able to use jmx4r with dotted MBean attributes, you can use Ruby Object#send.

Instead of

server.http_service.file_cache.maxentries_lastsampletime

you will have to use

server.send("http_service.file_cache.maxentries_lastsampletime")

This looks ugly but it works.

The user proposed to have jmx4r objects implement [] and work like a Hash to support dotted names. I am not convinced that such edge cases are worth supporting [] but if you think otherwise, do not hesitate to vote for this feature and I will add it to jmx4r.

Using Stomp with HornetQ

January 14, 2010

My daily job at Red Hat is to work on HornetQ.

As the home page says:

HornetQ is an open source project to build a multi-protocol, embeddable, very high performance, clustered, asynchronous messaging system

Yesterday, we released HornetQ 2.0.0 which supports 2 messaging APIs, JMS and HornetQ's own Core messaging API.
However, we already have users who wants to use HornetQ in non-Java environments.

One solution is to use Stomp with HornetQ so that any Stomp clients can communicate with HornetQ.

To show how to setup HornetQ and Stomp together, I created a project with the source code and all the required jars on GitHub:

git clone git://github.com/jmesnil/hornetq-stomp.git

The source code consists in a single class which configures and starts a fully functional standalone HornetQ server and connects it to Stomp:

public class HornetQStompServer {
   public static void main(String[] args) throws Exception {

      Configuration configuration = new ConfigurationImpl();
      // to keep things simple, we disable security. In real use, we'd setup authentication properly
      configuration.setSecurityEnabled(false);
      // we add a In-VM acceptor to HornetQ as the server will be accessible outside using Stomp
      configuration.getAcceptorConfigurations().add(
         new TransportConfiguration(InVMAcceptorFactory.class.getName()));
      // we add a Queue which will be available to Stomp under /queue/a
      configuration.getQueueConfigurations().add(
         new QueueConfiguration("jms.queue.a", "jms.queue.a",null, true));

      // we create the HornetQ server using this config
      HornetQServer hornetqServer = HornetQServers.newHornetQServer(configuration);
      // we also create a JMS server manager as Stomp is using the JMS API
      JMSServerManager jmsServer = new JMSServerManagerImpl(hornetqServer);
      // starting the JMS server will also start theHornetQ server underneath
      jmsServer.start();

      // We create directly a JMS ConnectionFactory which will be 
      // connected to the HornetQ server using In-VM connection
      ConnectionFactory connectionFactory = HornetQJMSClient.createConnectionFactory(
         new TransportConfiguration(InVMConnectorFactory.class.getName()));

      // We inject the connection factory in Stomp
      StompConnect stompConnect = new StompConnect(connectionFactory);
      // and start it using default Stomp config
      stompConnect.start();
   }
}

As both HornetQ server and clients are in the same Virtual Machine, we use in-vm connections. There will be only one port opened: the port used by Stomp (61613 by default)

To run the server, use Apache Ant:

$ ant server

...

server:
   [java] 14 janv. 2010 10:57:30 org.hornetq.core.logging.impl.JULLogDelegate info
   [java] INFO: live server is starting..
   [java] 14 janv. 2010 10:57:30 org.hornetq.core.logging.impl.JULLogDelegate warn
   [java] ATTENTION: Security risk! It has been detected that the cluster admin user and password have not been changed from the installation default. Please see the HornetQ user guide, cluster chapter, for instructions on how to do this.
   [java] 14 janv. 2010 10:57:30 org.hornetq.core.logging.impl.JULLogDelegate info
   [java] INFO: HornetQ Server version 2.0.0.GA (Hornet Queen, 113) started
   [java] 14 janv. 2010 10:57:30 org.codehaus.stomp.tcp.TcpTransportServer doStart
   [java] INFO: Listening for connections at: tcp://BlackBook.local:61613

That's all you need to have a fully functional messaging server accessible to any Stomp clients.

To check that it works properly, we will use telnet as our Stomp client:

$ telnet localhost 61613

First, we connect to the server.
To keep things simple, we have disabled security from the server so that we can connect to it anonymously:

CONNECT
login:
passcode:

^@

(^@ is Ctl-@)

The server replies that we are connected:

CONNECTED
session:null

We send a message to the destination /queue/a:

SEND 
destination:/queue/a

hello, hornetq!
^@

To make things more interesting, you can now kill the server and restart it. The message that was sent to the queue is persisted and will be consumed after the server is restarted.

Once the server is restarted, we open a new Stomp client and connect to the server:

$ telnet localhost 61613

CONNECT
login:
passcode:

^@

And we subscribe to the destination:

SUBSCRIBE
destination: /queue/a
ack:client

^@

As soon as we are subscribed, we will receive the message that was sent to the destination:

MESSAGE
message-id:ID:7b28be24-00f1-11df-b27f-001c42000009:0000000000000000
destination:/queue/a
timestamp:1263462299779
JMSXDeliveryCount:1
expires:0
subscription:/subscription-to//queue/a
priority:4

hello, hornetq!

Finally, we acknowledge the message:

ACK    
message-id: ID:7b28be24-00f1-11df-b27f-001c42000009:0000000000000000

^@

By leveraging HornetQ & Stomp, you can use messaging queues in your applications regardless on the platform you use.

One key decision of HornetQ was to make it simple to embed and integrate with other projects. This simple example shows that we reach our goal with Stomp.

jmx4r 0.1.0 Is Released

October 22, 2009

jmx4r 0.1.0 has just been released (jmx4r is a JRuby library which makes it super easy to write simple Ruby scripts to manage Java applications using JMX).

  • fixed compatibility with Rake 0.8.7 (thanks Dan!)
  • fixed dynamic mbean issues where attributes and methods were added to all the dynamic mbeans in the thread (thanks Munesse!)

There is also two new features:

  • support for Java CamelCase style in addition to Ruby snake_case (thanks again to Dan)
logging = JMX::MBean.find_by_name "java.util.logging:type=Logging"

# Ruby syntax works
logging.set_logger_level "global", "FINEST"
# Java syntax works too
logging.setLoggerLevel "global", "FINEST"    
  • Connection to a local JVM (thanks to Mr ohtsuka). You can now connect to a JVM running on the same machine without adding the com.sun.management.jmxremote system properties.

For example, start an instance of jconsole without any additional system properties:

$ jconsole &

You can now manage this Java application locally:

require 'rubygems'
require 'jmx4r'

# :command is a regexp corresponding to the Java process to connect to
JMX::MBean.establish_connection :command => /JConsole/
memory = JMX::MBean.find_by_name "java.lang:type=Memory"
memory.gc            

In addition to the previous :host, :port and :url arguments that you can pass to establish a JMX connection, there is now :command which must be a regular expression corresponding to the local Java process you want to connect to. You can find the name of the process using jps:

$ jps
4255 JConsole
4395 Jps

You can connect to a local Java application running on Java 5 or 6. Is someone interested to contribute support for JDK7 too?

Once again, thanks to all the contributors and users who help make jmx4r even more useful!

As usual, to get this new release, just update the rubygem:

jruby -S gem install jmx4r

and do not hesitate to contribute:

git clone git://github.com/jmesnil/jmx4r.git

Automator Service to create a Gist

October 19, 2009

I created an Automator Service to create a Gist from a text selection. This service will create the gist and copy the corresponding URL to the clipboard so that it can be pasted in IRC or in a web browser

  • Open ApplicationsAutomator
  • Create a new Service

Create a new Service
Create a new Service

  • Drag and drop UtilitiesRun Shell Script
    • Select shell: /bin/bash
    • Pass input: as arguments
    • Copy the content below:
RESP_FILE=/tmp/gist.tmp
rm -f $RESP_FILE

USER=`git config --global github.user`
USERAVAIL=$?
TOKEN=`git config --global github.token`
TOKENAVAIL=$?
if [ $USERAVAIL -eq 0 -a $TOKENAVAIL -eq 0 ]; then
  AUTH="--data-urlencode login=$USER --data-urlencode token=$TOKEN"
fi

curl http://gist.github.com/gists --silent -i $AUTH --data-urlencode "file_contents[gistfile1]=$1" --data-urlencode "file_ext[gistfile1]=.txt"  -o $RESP_FILE
cat $RESP_FILE|sed -ne '/Location/p'|cut -f2- -d:|tr -d ' ' | pbcopy 
  • Since it can take a few seconds to create a Gist, I added a Grow notification: drag and drop UtilitiesShow Growl Notification
  • Save service as "Gist Code"

You will end up with this service:

Gist Code

Now, you can select any text1, right-click and select Gist Code:

Mate

It also works from the Terminal using the application menu TerminalServicesGist Code

Once the gist has been created, you will be notified by Growl when the gist URL is copied to the clipboard. You can then paste this on IRC or in a web browser: http://gist.github.com/213301

By default, the gist will be saved as plain text (you will need to change the type from the gist page directly). This service also uses Git to retrieve GitHub credentials so that the gist is added to your Gists (rather than anonymously).

This is a screencast showing how to create and use this service:

Enjoy!


  1. It only works for Cocoa text widget. At first, I wanted to use it with Eclipse but unfortunately Eclipse does not support Apple Services... 

Best First Books for Programming Languages

October 13, 2009

As a followup to my previous entry, this is the list of first books I wholly recommend to learn programming languages:

C
K & R
Clojure
Programming Clojure
Erlang
Programming Erlang
JavaScript
JavaScript: The Good Parts
Lisp
The Little Schemer
Objective-C
Cocoa Programming with Mac OS X 1
Python
Dive into Python 2
Ruby
Why's (poignant) Guide to Ruby
Smalltalk
Smalltalk Best Practice Patterns

These books are not necessarily the most complete references and they do not cover all features offered by the languages but I found that they gave me the best insight to understand and think with these languages.

One language I did not list is Java. I have used Java for so long that the last introduction book I read was for version 1.2. Which book would you recommend to learn Java?


  1. This is more than just Objective-C but I found that learning Cocoa stuff really make the language shine. 
  2. I have not read Dive into Python 3 yet but I bet it is as good or even better than Dive into Python 

How Books Shape My Appreciation of Programming Languages

September 28, 2009

This morning, I read this funny tweet from @carina:

"Javascript in a single picture": http://short.to/rwo6 - absolutely awesome. Not sure if I should laugh or cry now. ;)

Funny and true: there are few good parts in JavaScript but they are really good!

I first learnt JavaScript by reading "The Definitive Guide" and I disliked the language. Browser incompatibilities, different DOM support were not helping too, but I found that the language was not "clean" (kind of object-oriented with this weird prototype thing).

A few years later, I had a renewed interest in JavaScript as a language running on the JVM. I also started to use jQuery and I was in awe with this library. I wanted to be able to read and understand jQuery code. I read "The Good Parts" (that I reviewed last year) and, finally, I understood how great JavaScript is and how its features are leveraged by jQuery. The book is small but it gives all the keys to understand and appreciate JavaScript while reading the Definitive Guide felt like reading the yellow pages.

When I want to learn a new programming language, I read a book covering it in paralllel of writing exploratory code. This funny tweet makes me wonder how much the first book I read on a language shapes my thoughts on it.

2nd example: Ruby. I learnt Ruby by reading the pickaxe book and did not find the language compelling. I thought it was a good scripting language, more readable than Perl, but nothing really stood out. Then I read Why's (poignant) Guide to Ruby and was blown away: I better understood Ruby mindset, loved it and started to write some non-trivial code1.

I am currently "evaluating" two languages: Clojure and Scala. I started with Clojure and read Programming Clojure by Stuart Halloway. I really enjoyed the book (I plan to review it in a future entry), its examples are relevant and well-thought and it gives a good insight to understand Clojure mindset. I have started to write some pet projects with Clojure and really enjoy the experience.

I have also read Programming Scala and I am underwhelmed by the language. It looks like a nicer, evolutionary Java but I do not find it appealing. It may be a fine language but it did not click with me like JavaScript did after reading "The Good Parts" or Ruby after reading Why's "(poignant) guide", or Clojure after reading Stuart's book.
Programming Scala is a good book to learn Scala syntax, etc. but I do not have a better grasp on Scala mindset after reading it. Anybody interested in Scala should read it but I can not say that it helped me grasp what makes Scala so great.

I was teased enough reading Programming Clojure to enthusiastically dive deep into Clojure. The main reason is, of course, the Clojure language itself but a big kudos goes to Stuart and his book which made me wanting to learn more.

This is not a "Scala Vs. Clojure" argument. I plan to add both to my toolset eventually but, in the short term, I will focus on Clojure when I need a functional/concurrent programming language.
This is not specific to Scala, there are other languages that leave me cold. Python is a fine language but it does not appeal to me2., I prefer Ruby for similar tasks but I can't objectively explain why it is the case.

The common point of "JavaScript: The Good Parts", Why's "(poignant) Guide to Ruby", and "Programming Clojure" is that they describe well the mindset for their respective languages. I am not interested to write Java code in JavaScript, Ruby or Clojure. I want to understand what makes a language unique, its strengths and weaknesses and how to think in the language. Any book which helps me understand that is a book I wholly recommend.


  1. jmx4r meta code comes straight from Why's dwenthy.rb. Thank again, Why, for all your contributions. 
  2. Reading Dive Into Python 3 will perhaps change my mind...