Je vais commencer par une petite présentation rapide de JSF en citant l'article wikipédia : Java Server Faces (abrégé en JSF) est un framework Java basé sur les composants, pour le développement d'applications Web , et fait partie du standard Java EE. Il suit la méthode de conception Modèle-Vue-Contrôleur. Ce que j'appellerai simplement JSF dans la suite de ce billet est la vue. C'est un assemblage de composants (appelés "tags") qui font appel à un ou plusieurs contrôleurs (instance d'une classe Java) pour récupérer des données et les mettre en page. Les contrôleurs font le lien entre les vues et la logique métier (partie Modèle) qui récupère et/ou "calcule" les données.

Voilà pour le principe. En pratique, on peut avoir besoin de faire des opérations très basiques dans la vue. Pour récupérer les données dans la vue via les contrôleurs, et faire ce opérations basiques, JSF utilise les Expressions Languages (EL). Elles supportent l'appel aux getters des contrôleurs ainsi qu'aux méthodes de type isQuelqueChose qui renvoient un booléen (pour les tests). Elles supportent également les opérateurs arithmétiques pour les types numériques ainsi que les opérateurs relationnels et logiques pour les types numériques, les booléens et les Strings.

Ainsi, la première limitation est de ne pas pouvoir appeler les méthodes qu'on souhaite. Si vous avez un objet (bean) et que vous voulez appeler la méthode toto, vous écrivez bean.toto (remarquer l'absence de parenthèse, on ne peut pas passer d'arguments !). Et bien à l'exécution, les EL vont chercher à appeler la méthode getToto() et non toto()...

Cependant, on peut utilisé des objets de type Map (beans mappés). Par exemple, on peut récupérer la map toto, attribut du contrôleur, via son getter, puis récupérer la valeur correspondante dans cette map à la clé tete (vous avez compris que je cherche à récupérer la valeur de la tête à Toto ! :D). Pour cela, on écrit controleur.toto["tete"]. Si j'avais voulu faire la même chose par une méthode toto qui prend un String comme argument, j'aurais écrit controleur.toto("tete")... La différence n'est pas énorme ;-).

Finalement, mettre des crochets à la place de parenthèses, ça n'a pas l'air si choquant... Enfin, il faut tout de même se dire que dans une utilisation "normal", la map toto contiendra toutes les valeurs susceptibles d'être passer en argument. Ce n'est donc pas vraiment une vrai fonction. Si on ne s'intéresse qu'à une partie de l'anatomie de Toto, ça va. Si ma méthode toto se charge de concaténer un String au String passé en argument, il faut stocker tous les Strings possibles et imaginables ?! Bref, on ne va pas faire ça !

L'astuce (appelée également bidouille ;-)), que je propose, consiste à utiliser une "fausse" map. On va se fabriquer une map qui ne stocke aucune information et dont la méthode get fera le "calcul" qu'on souhaite. Pour cela, on va utiliser la classe AbstractMap du package standard java.util.

private Map<String, String> toto =
new AbstractMap<String, String>() {
@Override
public Set<Entry<String, String>> entrySet() {
return null;
}

@Override
public String get(final Object arg0) {
return "PREFIX" + arg0.toString();
}
};

Tout ça pour ça... Si c'est pas malheureux... :(