Jeff Mesnil
Weblog · About

The Hobbit: An Unexpected Disappointement

December 19, 2012

I watched "The Hobbit: An Unexpected Journey" yesterday in 3D HFR and was disappointed by the experience. The 3D HFR is technically impressive but it prevented to immerse in the story.

Vincent Laforet provides a good explanation on why 3D HFR was disengaging me from the movie. I could not better explain my disappointment. Like him, I could watch it again in 2D to have a better visual experience but I did not enjoy the story enough. This is not the Lord Of the Ring's "Phantom Menace" (no Jar Jar Binks in sight) but the script could have been tighter and the characters more developped.

I did not think there was enough material in The Hobbit book for three movies. Watching the first one confirmed my opinion.

⇨ Go is PHP for the Backend

November 18, 2012

Brian McCallister writes about his introduction to Go:

I know of folks having great success with Go, and it offers a lot that I want (native code, UNIX friendly, higher level then C, lower level then Python or Ruby, garbage collected, strongly typed, good performance, good concurrency support, etc), so I tried to stop programming my way, and start programming Go’s way.

I have read both good and bad things about Go. I need to use it to make my own opinion about it.

I am pondering which new programming language to learn in 2013 and it will either be Go or Ceylon.

⇨ Learnable Programming

October 23, 2012

Thought-provoking reading about learning to program. The essay is gorgeous with fantastic visuals to understand its arguments:

Being a server-side programmer during the day, I think the essay makes the wrong assumption that programs inherently have a visual representation that helps learn the language.
What is the visual representation of an algorithm code other than a single number for each step? Not all algorithms have a visual interpretation like the Fibonnacci sequence... Maybe I am not thinking outside of the box and such a representation do exist but I have not found it yet.

This essay makes a compelling argument that through the use of a graphic library (where the visual representation is the output of the program), we can learn the underlying programming language features (for loop, variable assignments) and abstractions (decomposition, abstraction).

(via daring fireball)

⇨ An Intimate Portrait Of Innovation, Risk, And Failure Through Hipstamatic's Lens

October 19, 2012

Fascinatic story about the demise of Hipstamatic.

There are many reasons why Instagram succeeded1 and Hipstamatic did not. The article insists on the social aspect but that's not the only one.

"The biggest problem with Hipstamatic is that [Lucas] didn’t focus on Hipstamatic. What did Instagram do when lightning struck? They did nothing but focus on Instagram. What happened when Hipstamatic got successful? They made [separate products such as] Swankolab, Incredibooth, D Series, Family Album, Snap Magazine, and splintered off in so many different directions."
Stuart Norrie, former Hipstamatic designer

Focus. Focus. Focus.

(via James Duncan Davidson)


  1. At least in term of user base and engagement. Financially, how would have Instagram make any money other than being acquired by some bigger company? 

Three Customer Services

October 2, 2012

This is a tale of three customer services I have to deal with recently. I will continue to buy and recommend products from two of these companies. The third company will never hear from me again.

Giotto's

I bought 2 years ago a Vitruvian tripod from Giotto's:

Giotto's Vitruvian Tripod
Giotto's Vitruvian Tripod

This is a great tripod, small enough to fit in any luggage, lightweight to bring it anywhere, and sturdy. However, I recently noticed one of the leg adjuster was not working properly and the tripod could not stand on its lowest position with a heavy zoom lens at the longest focal length.

The tripod is under a 5-year warranty. It took me 5 minutes to go to Giotto's web site on the tripod's product page and send a mail about this issue. On the same day, I had a reply with instructions to send my tripod for replacement. I followed the instructions and three weeks later, I received my repaired tripod.

Apple

One year ago, I bought an iPhone 4S. Last friday, the on/off button stopped working (it was no longer "clicking"). I browsed Apple customer service web site for an hour. There was a form to report the issue but the HTML form was not working (there were also missing i18n keys on the page).

However, it was quite straightforward to find the phone number to call. The support guy was helpful and offered me an express replacement as my iPhone was still under warranty (for a week!). He also offered the transportation and replacement fees (30€) since it was the first time I asked to replace an Apple product.

On monday, UPS brought me the new iPhone and took the broken one (it took me the rest of the day to restore it with a backup from iCloud and set it up again correctly but that's another story).

Lenovo

For my work at Red Hat, I use a Lenovo laptop (until I buy a 13' Retina MacBook). When I received it, I noticed a green stuck pixel, right in the middle of the screen. This is quite annoying on the dark background I use for my terminal.

I tried without success to fill a form on Lenovo web site (or was it IBM?). I got lost in all the choices and subchoices to find the right category. I was not able to find any customer service email address on their web site for French customer support. Finally, after some extensive Google searcher, I found a phone number on an blog post. The support guy was clueless, he opened a new case for me and asked me to send an email to IBM support with the case number and an explanation of my issue (the address is support_fr@uk.ibm.com for what is worth).

I sent a first mail on June, 21st and got a reply asking me to write to another email address instead (tssent@fr.ibm.com). I did as instructed. I did not get any reply, nor for the two other messages I sent.

Then out of the blue, one week later, I got a reply from the 1st address requiring a invoice for my support and asking me not to send mails to the 2nd address! I did as instructed and 5 days later, I got an email telling me that they have opened a new case for me and their customer support will reach me soon.

I waited for 1 week before sending an email asking for a status update. No response.

I waited another week to send another email and I was starting to lose patience. One week after, I finally got a reply telling me that they could not repair or change my laptop since it needed at least 2 dead or stuck pixels.

I sent my 1st email on June, 21st. I got an informative reply after 7 other emails on July, 27th.

I have had such a bad experience with Lenovo support that I would not recommend any of their laptops, even if they were good (spoiler, they are not...).

I can't generalize too much from these 3 cases but it seems I have encountered 3 different type of customer service:

  • Customer service for enthousiast consumers with Giotto's
  • Customer service for mainstream consumers with Apple
  • Customer service for enterprise consumers with Lenovo

Needless to say which one is the worst.

⇨ Fender's Struggles

October 1, 2012

New York Times:

But this heart of rock isn’t beating quite the way it once did. Like many other American manufacturers, Fender is struggling to hold on to what it’s got in a tight economy. Sales and profits are down this year. A Strat, after all, is what economists call a consumer discretionary item — a nonessential.

I always wanted to have a Stevie Ray Vaughan Stratocaster for the sound and the look of it...

Stevie Ray Vaughan Stratocaster
Stevie Ray Vaughan Stratocaster

(via The loop)

WebSocket alternatives for STOMP

September 7, 2012

I wrote previously about a hack to use SockJS with Stomp over WebSockets:

Stomp.WebSocketClass = SockJS;
// same as usual
var client = Stomp.client(url);
[...]

However, this was ugly and of limited use: the instantiation of the Web Socket was still done inside Stomp.client() function.

Marek Majkowski then proposed to update the library to be able to pass any object conforming to the WebSocket type to enable all kind of cool stuff.

I have updated the library to use STOMP over any kind of WebSocket objects:

var ws = new SockJS(url);
var client = Stomp.over(ws);
// the rest of the code is the same
[...]

As written in the documentation, you can use Stomp.client(url) to let the library create regular WebSockets or use Stomp.over(ws) if you required another type of WebSocket.

Web Sockets for everyone!

Cherry Tomatoes

August 13, 2012

Cherry Tomatoes
Cherry Tomatoes

These cherry tomatoes from our little garden are delicious!

⇨ Mars Rover Camera Has a 2MP Sensor

August 10, 2012

Malin Space Science Systems' project manager Mike Ravin:

There's a popular belief that projects like this are going to be very advanced but there are things that mitigate against that. These designs were proposed in 2004, and you don't get to propose one specification and then go off and develop something else. 2MP with 8GB of flash [memory] didn't sound too bad in 2004. But it doesn't compare well to what you get in an iPhone today.

Two-image panorama shot with the rover's 1024 x 1024 mono navigation cameras
© NASA/JPL-Caltech

The images are hauntingly beautiful.

Week-end en Savoie

August 9, 2012

We had a lovely time (and cloudy weather!) last week-end in Savoie, driving through the Maurienne, Tarentaise and Beaufortain valleys.

Fort Ste-Th&eacuterèse
Fort Ste-Thérèse

Bonneval sur Arc
Bonneval sur Arc

Manège en Bois
Manège en Bois

Manège en Bois
Manège en Bois

This wooden carousel was put in motion by the parents using a swing. The parents were having more fun than the children!

Barrage de Roselend
Barrage de Roselend

That was a great week-end!

I Am Awestructed

August 2, 2012

Did you notice something different on my Web site or my Atom feed?
You shouldn't as I have successfully migrated from Jekyll to Awestruct.

A few months ago, I switched my Weblog from Wordpress to Jekyll because I wanted to have a simpler, slimmer publishing system that could generate a static Web site and be simple to customize. At first, Jekyll fit the bill nicely but as I was starting to tweak it, I was slowed down by its lack of documentation and customization. I want to be able to extend my publishing system, not fork it.

Searching for an alternative, I looked at Awestruct, written by my Red Hat colleague, Bob McWhirter, and liked it. It is an evolution from Jekyll with a nice extensible architecture and good documentation.

As an example of Awestruct extensibility, I wrote an extension to provide an Archive page for my Weblog. Awestruct defines an extension to create a weblog from a single directory with files matching the format of YYYY-MM-DD-post-title (like Jekyll does):

Awestruct::Extensions::Pipeline.new do
  ...
  extension Awestruct::Extensions::Posts.new '/weblog', :posts
  ...
end

I wanted to add a page which lists all my posts sorted by ear and month. I added an extension to Awestruct pipeline for this:

Awestruct::Extensions::Pipeline.new do
  ...
  extension Awestruct::Extensions::Posts.new '/weblog', :posts
  extension Awestruct::Extensions::PostsArchiver.new '/weblog/archive', :posts, :archive
  ...
end

This extension takes the :posts that were added to the site by the Posts extension, sort them in a hierarchy of year / month / posts and put them in the variable named :archive that can be used inside the template file /weblog/archive (source code).

I could then have a very simple Haml template to display the archive:

---
layout: page
title : Archive
---    

- site.archive.each do |year, monthly_archive|
  %h2= year
  - monthly_archive.each do |month, posts|  
    %h3= month
    %ul
      - posts.each do |post|
        %li
          = "#{post.date.strftime('%d %B %Y')} »"
          - if post.link
            %a.link{ :href=>post.url }= "#{site.linked_list.link} #{ post.title}"
          - else
            %a{ :href=>post.url }= post.title

Et voila the result!

In similar fashion, I have been able to add a Daring Fireball-style linked list to my Web site and Atom feed by simply adding a link metadata to the file front-matter and a few lines of HAM to process it.

On JMS ObjectMessage And Its Pitfalls

July 27, 2012

I have been working on head scratching issues related to JMS ObjectMessage all week, ranting about it aloud, on IRC, in JIRA comments... Let's try to be constructive and address exactly why ObjectMessage is a bad idea and what should be used instead.

From JMS Message javadoc:

The JMS API defines five types of message body:

Stream - A StreamMessage object's message body contains a stream of primitive values in the Java programming language ("Java primitives"). It is filled and read sequentially.
Map - A MapMessage object's message body contains a set of name-value pairs, where names are String objects, and values are Java primitives. The entries can be accessed sequentially or randomly by name. The order of the entries is undefined.
Text - A TextMessage object's message body contains a java.lang.String object. This message type can be used to transport plain-text messages, and XML messages.
Object - An ObjectMessage object's message body contains a Serializable Java object.
Bytes - A BytesMessage object's message body contains a stream of uninterpreted bytes. This message type is for literally encoding a body to match an existing message format. In many cases, it is possible to use one of the other body types, which are easier to use. Although the JMS API allows the use of message properties with byte messages, they are typically not used, since the inclusion of properties may affect the format.

Of those five, only two are useful: Bytes and Text messages. The three others have their own issues1 but today's rant is about ObjectMessage.

Before analyzing ObjectMessage issues, let's see how it is used.

A Java client creates a ObjectMessage and set its body to a Serializable object (let's call it payload). It then sends it to a JMS Destination. The payload is sent over the wire as a stream of bytes. Note that the JMS API does not mandate how the payload can be serialized (it can be with standard Java serialization or something else).

Other Java clients (one if the destination is a queue, many if it is a topic) will receive this message with the serialized payload. They will call ObjectMessage.getObject() to retrieve the payload Java object. It is the responsibility of the messaging provider to deserialize the stream of bytes and reconstruct the payload object before passing it to the client.

Simple, isn't it? Not really.

Architectural Issues

One of the advantage of using messaging system is loose coupling. The producers and consumers of a destination does not need to know each other or be online at the same time to exchange messages. They only need to agree on the data sent in the message.

By using an ObjectMessage, the type of the Java object is their agreement. This means that both sides MUST be able to understand the object and its whole graph type. You are losing one degree of abstraction by using an ObjectMessage, the consumer(s) of this message must know the implementation type of the payload and have all the classes required to deserialize it. This introduces a strong coupling between producers and consumers since they now must share a common set of classes (which grows with the complexity of the payload type).

There is a simple solution to reduce this issue (but not removing it entirely): use DTO for ObjectMessage payload

Technical Issues

The technical issues of using ObjectMessage are related to the deserialization of the stream of bytes sent over the wire. To be able to deserialize an object, the messaging provider must be able to recreate the instance as it was when it was serialized. This also implies that we must have access to the same classes and classloader that were used to serialize the payload. My colleague, Jason Greene, has a nice article about modular serialization. Unfortunately, this is something more complex in our case since it is possible (and often the case!) that consumers of messages run in different environments than the producer.

As an example, we can have:

  1. a Servlet that sends a message to a topic (its environment is a Java EE WAR module)
  2. a MDB that consumes it (its environment is a Java EE EJB module)
  3. a standalone Java application that also consumes it (its environment is a regular Java application)

Clients (1) and (2) will run in a modular application (e.g. JBoss AS7) while client (3) will run in a non-modular application (using regular Java classpath).

How can client (3) be expected to deserialize a class that was serialized in a different environment? Conversely if the client (1) use standard Java serialization, how can the client (2) be expected to deserialize it if it is not able to load all classes in the payload type (as modules does not export their dependencies)?

There is a simple solution to remove this issue:

  1. Do not use ObjectMessage
  2. Instead, define a data structure for the payload (using XML, JSON, protobuf, etc.) and use Text or Bytes message

Performance issues

How much space does it take to store a Java class with int and String fields as bytes instead of storing directly the int and the String?

3.7 times more2

It is not as simple to compare the size of a serialized Java object with the corresponding XML, JSON, protobuf payload. All these bytes are transported on the wire. The more bytes to serialize/transport/deserialize, the slower the message is delivered. (even though premature optimization is the root of all evil still prevails).

Conclusion

At first glance, ObjectMessage looks like a good idea. It lets application deals only with Java objects but it opens a whole can of architectural, technical and performance issues that will need to be dealt at one time or another, probably after the application is put in production...

I would suggest to reduce as much as possible the use of ObjectMessage (with the goal of getting rid of them completely) with 2 steps:

  1. Use DTO for ObjectMessage payload
  2. If possible, define a data representation for the payload (JSON, protobuf, XML) and use Text or Bytes message to carry it

It is not a huge task and your application will be all the better for it (loosely-coupled, resilient to changes, with explicit payload agreement, etc.)


  1. For example, what if messages can also produced and consumed from non-Java applications using STOMP protocol? 
  2. Meaningless numbers, so sue me... 

AS7 REST Management API

July 23, 2012

I am playing a bit with AS7 Management REST API and I want to display the full description of the server model from the Web browser.

Using the CLI, this is equivalent to

[standalone@localhost:9999 /] /:read-resource-description(recursive=true, operations=true)
{
    "outcome" => "success",
    "result" => {
        "description" => "The root node of the server-level management model.",
        "head-comment-allowed" => true,
        "tail-comment-allowed" => true,
        "attributes" => {
            "namespaces" => {
                "type" => OBJECT,
                "value-type" => STRING,
                "description" => "Map of namespaces used in the configuration XML document, where keys are namespace prefixes and values are schema URIs.",
                "required" => false,
                "head-comment-allowed" => false,
                "tail-comment-allowed" => false,
                "access-type" => "read-only",
                "storage" => "configuration"
            },
    ...
}

However, using the CLI is limiting for what I envision. The description that is returned is similar to JSON but it's not valid JSON. I want to interact with the descriptions using a programming language to iterate on resources, filter them out, etc.

The end game could be to generate a HTML documentation for each release of AS7 that could ship with the release and complement the existing documentation

To achieve this, I have first create a simple Sinatra application that queries a running AS7 server (in standalone mode) and display its resource description using the REST API.

The application is using Bundler to manage its dependencies through a Gemfile file:

source 'http://rubygems.org'
gem 'rake'
gem 'rack'
gem 'sinatra'
gem 'httparty'
gem 'json'

We use Rack to start the Web server hosting our little app with a config.ru file:

require "./application.rb"

run Sinatra::Application

The application itsel if a simple Sinatra application which calls the AS7 management REST API (with authentication) and proxies the JSON output.

require 'rubygems'
require 'bundler/setup'
Bundler.require

get '/resource-description' do
  user = params['user']
  password = params['password']

  return [500, "missing user and password parameters"] unless user and password

  url = 'http://127.0.0.1:9990/management/'
  operation = {:operation => "read-resource-description",
      :recursive => params["recursive"] || false,
      :operations => params["operations"] || false,
      :inherited => params["inherited"] || false
    }
  res = AS7.query url, user, password, operation.to_json
  if res.code == 200
    [res.code,   {'Content-type' => 'application/json'}, res.body.to_s]
  else
    [res.code, res.headers, res.body.to_s]
  end
end

class AS7
  include HTTParty
  def AS7.query(url, user, password, operation)
    digest_auth user, password
    post url , :body => operation, :headers => {"Content-type" => "application/json"}
  end
end

In itself, that's not terribly interesting but if it is coupled with a JSON prettifier extension, it displays a nice interactive JSON tree in the browser.

JSON output
JSON output

To run the application:

$ bundle # to fetch the ruby gems
$ rackup config.ru
[2012-07-23 17:14:02] INFO  WEBrick 1.3.1
[2012-07-23 17:14:02] INFO  ruby 1.9.3 (2012-04-20) [x86_64-linux]
[2012-07-23 17:14:02] INFO  WEBrick::HTTPServer#start: pid=11499 port=9292

The description is then available at http://localhost:9292/resource-description

  • Mandatory parameters
    • user - the AS7 admin user
    • password - the AS7 admin password
  • Optional parameters
    • recursive - whether the description is recursive (defaults to false)
    • operation - whether the description includes operation descriptions (defaults to false)
    • inherited - whether the children description includes inherited elements (defaults to false)

For example, to get the most comprehensive description of the server, you can use this URL.

Next step is to transform the JSON into a HTML output with a nice format and JavaScript goodies (e.g. for automatic generation of a table of contents)