10 mars 2010

Fonzie s'invite dans Javac



Julien Viet m'a suggéré une évolution sur Fonzie : Utilise le processeur d'annotations (APT) de JavaC à la place du compilo AspectJ.

AspectJ fait très bien l'affaire pour Fonzie mais apporte de nombreuses contraintes :
  • la compilation n'est pas des plus véloces,
  • l'environnement de dev AJDT est particulièrement gourmand,
  • le plugin AspectJ doit être configuré dans le build Maven.
Rien de bloquant, mais un ensemble de petites choses qui rendent Fonzie "moins" attractif qu'il le mérite (AMHA).

L'idée de Julien est de détourner APT pour s'intégrer directement dans la compilation JavaC, ce qui est possible depuis Java6 avec une API standard. En utilisant des API internes de javac (com.sum.tools*) on peut faire plus que transformer les annotations en fichiers de ressources ou en nouveau code Java -- l'objectif initial d'APT. On peut aller directement modifier le code source qui va être compilé - sa représentation AST plus précisément - sans toucher pour autant au fichier source.

Lombok utilise ce principe pour ajouter des getter/setter (entre autre) dans les beans. Plus besoin de polluer le code .java avec ces méthodes sans valeur, qui seront bel et bien présentes dans le code compilé.

Ca, c'est la théorie.

Reste à mettre en oeuvre. Même avec l'aide du code source de Julien (chromattic, reflext) et de Lombok, la manipulation des ces API internes est délicate, et leur code source n'est pas proposé dans le SRC.ZIP qui accompagne le JDK. Il y a heureusement google et OpenJDK pour retrouver ces sources, mais bien peu d'infos sur comment utiliser ces APIs.

Toujours est-il qu'un premier jet bien modeste - mais faut bien commencer par quelque chose - est en place. Sur la base de ce code source :
@Entity
public class User
{
public native void persist();
}
Pour un projet utilisant le JDK6 pour compiler, et sans rien faire sauf ajouter Fonzie-0.4-SNAPSHOT en dépendance, le fichier .class décompilé donne ceci :
@Entity
public class User
{
public void persist()
{
Fonzie.instance();
}
}
Pour ce premier jet, le code introduit dans la méthode n'est pas passionnant, mais au moins le squelette est en place. Reste à construire via l'AST le code d'invocation Fonzie qui va bien -- et ça, ça va être tout de suite plus toochy.

Wait & See ...