Arquillian testing

Arquillian testing is very convenient to get a full environment deployed on an application server and test quickly. However sometimes we need to debug what’s inside.

Launch Maven in Debug mode

One way of doing it can be launching Maven in debug mode with the mvnDebug command instead of the classical mvn. It will open a JPDA debugger on port 8000 by default, you then just need to connect to it with your preferred IDE. But, if there is forked processes, you won’t be able to debug inside them.

Launch Failsafe Integration Tests in Debug mode

When using Arquillian, there is a high probability that Arquillian is running in a forked process (with embedded containers).

There is an easy way to tell maven-failsafe-plugin to wait for a debugger when starting : use the -Dmaven.failsafe.debug property.

You can even specify the options as you would in $JAVA_OPTS to change ports / wait…

Oops

A few days ago, I finally decided to upgrade the installed Linux on my dedicated box hosted at OVH. As with every task you tend to postpone until it is too late, it failed miserably, Murphy’s law I am looking at you right now !

During the install process, the machine hanged (I am not sure whether the machine is faulty or not, it seems to shut down under heavy load). Fortunately for me, OVH is kind enough to send a tech resets the machine, and if it does not ping when booted, the tech reboots the machine in rescue mode.

Rescue mode

The rescue mode is a lightweight Linux booted on the machine so you can run fsckand other commands to rescue your filesystem (you can even scp files to backup before a reinstall for example.

My problem was simple, I needed to allow dpkg to finish its job in order for me to get a working machine. Then I think of the good old powerful chroot command and I remembered how powerful Unixes are !

Mounting filesystems

As you should know, chroot is a command allowing to change the root of a file system, litterally jailing it into a directory (popular things of today like pico containers like Docker are improved versions of chroot).

The partition layout of my machine is the following :

  • sda1 contains the root filesystem
  • sda2 contains home directories

I issued the following commands to “jail” the rescue mode into my machine :

$ mount /dev/sda1 /mnt
$ mount /dev/sda2 /mnt/home
    
$ mount -o bind /proc /mnt/proc
$ mount -o bind /dev /mnt/dev
$ mount -o bind /dev/pts /mnt/dev/pts
$ mount -o bind /sys /mnt/sys 
$ chroot /mnt/
    

From then, I was on my machine, with my files and so on, so I have been able to run dpkg to finish the install :

$ dpkg --configure --a
    

Finally, dpkg sent me back to a working prompt and I have been able to reboot the machine (do not forget to change boot disk in OVH manager to hd or netboot to prevent rebooting in rescue mode).

Lors de nos développements, nous reposons beaucoup sur des projets externes qui nous fournissent énormément de services utiles. Dans un récent projet, nous avons eu besoin de faire fonctionner Neo4j conjointement à ElasticSearch. Jusqu’ici, aucun soucis n’est à déplorer, mais nous avions une exigence particulière : il fallait que l’application puisse démarrer automatiquement un serveur Neo4J ainsi qu’un serveur ElasticSearch sur les postes de développements (ainsi que pour les tests d’intégration).

Problème existant

Les deux outils que nous utilisons se basent sur Apache Lucene pour toute la partie indexation et accès aux données. Mais, et c’est là que le problème se situe, ils n’utilisent pas les mêmes versions de Lucene.

<!-- Extrait du pom d'ElasticSearch -->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>4.9.0</version>
    <scope>compile</scope>
</dependency>

<!-- Extrait du pom de Neo4j -->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>3.6.2</version>
</dependency>

ElasticSearch utilise la version 4.9.0, alors que Neo4J utilise la version 3.6.2. Ainsi, en fonction du bon vouloir du Classloader qui sera utilisé par l’application, il se peut qu’ElasticSearch ou Neo4J refuse de fonctionner. La difficulté pour comprendre et détecter le problème est qu’il se manifeste souvent par un obscur NoClassDefFoundError ou NoSuchMethodError qui n’est pas des plus explicites (d’autant plus lorsque notre IDE nous montre une version qui contient ledit symbole non trouvé).

Solution de contournement

Le conflit est assez simple à contourner une fois qu’on a compris ce qui se passe. En fait, il y a deux classes portant le même nom dans les classes chargées, par exemple org.lucene.MaClass, l’une effaçant l’autre aux yeux du ClassLoader. Une pratique courante est de renommer (ou relocate) le package de base d’une bibliothèque utilisée et de l’inclure dans le fichier de package du projet, le plugin maven-shade est conçu dans cette optique. Le choix fait est de renommer la dépendance Lucene dans Neo4J pour notre part, ainsi, nous avons forké le projet et configuré le plugin shade pour qu’il inclue le contenu de la dépendance d’Apache Lucene et qu’il fasse le renommage de org.apache.lucene en shaded.org.apache.lucene.

 <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.2</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <createDependencyReducedPom>true</createDependencyReducedPom>

                    <artifactSet>
                        <includes>
                            <include>org.apache.lucene:*</include>
                        </includes>
                    </artifactSet>
                    <relocations>
                        <relocation>
                            <pattern>org.apache.lucene</pattern>
                            <shadedPattern>shaded.org.apache.lucene</shadedPattern>
                        </relocation>
                    </relocations>
                </configuration>
            </execution>
        </executions>
  </plugin>

Déploiement et nommage

Pour ne pas polluer les dépôts, le numéro de version modifié a été postfixé par -shaded. Le déploiement a été fait sur un dépôt Maven qui est en fait un simple repository Github. Le commit correspondant à cette modification est consultable ici.

Command line nerd

As a command line geek, I always have at least one open and tend to use it for everything on my machine.

HomeBrew is a very convenient tool to install command line tools to your Mac without cluttering up your environment. You can use it like your Linux friends are using apt-get or yum and it feels really nice.

One thing that your friend can do and you cannot, is installing Google Chrome only using command line, this is where HomeBrew Cask comes to the rescue.

Installation guide

Cask will be up and running in a very few steps :

$ brew tap phinze/cask
$ brew install brew-cask
$ brew cask install dropbox #for example

Usage hint

This tool is really nice because it allows you to script your machine setup. No more headaches forgetting the installation of when you want to use it.

Don’t hesitate to add a small script in your .dotfiles to seed your software on new machines, and if your preferred software is missing, it is really easy to add new casks.

Manage your services

If you’re using HomeBrew to manage your software installation on your Mac, there is a thing that is not that easy to do : launchd or launchctl service management. Often you need to manually tell launchd to load the plist of your newly installed service. It leads to a lot of things launched at boot on your machine, and they are not easy to manage.

LaunchRocket provides a simple PreferencePane allowing you to start/stop services when you only need to with a clean and simple GUI.

LaunchRocket in action

You can easily install it via brew cask (more to come on brew cask soon) or download the zip distribution