mercredi 17 décembre 2008

Squill : ceci n'est pas un ORM

Fichiers xml de mapping, annotations JPA, Hibernate, HQL Criteria... Voila avec quoi doivent jongler les développeurs Java pour accéder à une base de données.

Résultat :
  • un long apprentissage pour maitriser tout ça
  • le développeur est éloigné du SQL, bugs et problèmes de performances sont inévitables
  • la plupart des problèmes ne sont identifiés qu'à l'exécution, en cours de développement, il n'y a aucune vérification de la cohérence des développements avec la structure de la base
Squill propose une approche radicalement différente :
  1. une tache ant génère un ensemble de classe correspondant aux tables de la base
  2. le développeur utilise ces classes qui offrent des méthodes correspondant aux différentes instructions SQL
Les avantages sont énormes :
  • Le développeur code pratiquement du SQL
  • Aucun SQL généré automatiquement
  • Tout est vérifié à la compilation (ex : si on supprime une colonne, on a une erreur de compilation !)
  • Autocompletion
Enfin tout ça, c'est la théorie. Pour l'instant ce n'est que de la version beta, mais j'aime beaucoup l'idée.

lundi 7 juillet 2008

Portlet, bridge et servlet filter

Pour ceux qui se sont arrachés les cheveux à essayer d'intégrer des webapp en portlet via un bridge, il est possible de faire fonctionner les servlet filter dans l'application. Pour cela il faut :
1) être en servlet 2.4 ou +
Il faut donc utiliser le bon schema au niveau du fichier web.xml
Tourner sous un Tomcat 5.5 ou +
2) utiliser l'élément au niveau de chacun des filter pour indiquer s'il doit être exécuté en cas de forward/include
Attention au risque de boucle infinie !

Plus de détails :
http://www.ibm.com/developerworks/java/library/j-tomcat2/#N10082

Extrait de la spec servlet 2.4 :
SRV.6.2.5 Filters and the RequestDispatcher
New for version 2.4 of the Java Servlet specification is the ability to configure filters
to be invoked under request dispatcher forward() and include() calls.
By using the new element in the deployment descriptor, the
developer can indicate for a filter-mapping whether he would like the filter to be
applied to requests when:
1. The request comes directly from the client.
This is indicated by a element with value REQUEST,
or by the absence of any elements.
2. The request is being processed under a request dispatcher representing the
Web component matching the or using a forward()
call.
This is indicated by a element with value FORWARD.
3. The request is being processed under a request dispatcher representing the
Web component matching the or using an include()
call.
This is indicated by a element with value INCLUDE.
4. The request is being processed with the error page mechanism specified in "Error
Handling" on page 73 to an error resource matching the .
This is indicated by a element with the value ERROR.
5. Or any combination of 1, 2, 3, or 4 above.

jeudi 3 juillet 2008

Manipulation des chaines de caractères et performances en Java

En Java, dans des programmes qui doivent manipuler, analyser et traiter des chaines de caractères, la manière de coder peut avoir un gros impact sur les performances. Quelques éléments clé à prendre en compte :
  1. Une String est un objet immuable. Elle peut être utilisée en parallèle par plusieurs Threads simultanément en toute sécurité. Il est donc inutile de copier une chaine de caractère en faisant new String(s).
  2. Inutile de sortir systématiquement vos chaines de caractères comme des constantes, le compilateur le fait pour vous !
  3. Une chaine de caractère contient un char[]. Les opérations de type substring() sont très peu couteuses en mémoire ou en CPU puisqu'il n'y a pas copie de ce tableau mais simplement création d'un nouvel objet String qui pointe vers le même tableau.
  4. A la compilation, une concaténation de chaines de caractères "toto" + "titi" est automatiquement remplacée par la création d'un StringBuilder. Cette classe existe depuis le JDK 1.5 et est bien plus performante que la classe StringBuffer. L'API est la même mais il n'y a pas de synchronized (a ne pas utiliser en accès multithread donc). Donc remplacer dans une méthode les concaténation de chaine par des StringBuffer comme on le recommandait il y a quelques années fait désormais baisser les performances !
  5. Un StringBuilder ou un StringBuffer contient lui aussi un char[] dont la taille par défaut est 16. Dès que le buffer est plein, le char[] est automatiquement remplacé par un char deux fois plus grand dans lequel le premier est copié. Bien dimensionner le buffer à l'origine peut donc économiser pas mal d'opérations de copie.
  6. L'appel de la méthode toString() d'un StringBuilder ou d'un StringBuffer déclenche la copie du char[] qu'il contient. Ne pas faire writer.append(stringBuffer.toString()) mais plutôt directement writer.append(stringBuffer) permet d'éviter une opération de copie.
  7. Toutes les opérations de type replace() ou replaceall() déclenchent des copies du tableau.
  8. On peut exécuter des recherches et des remplacements directement sur des StringBuffer sans faire de toString() de la manière suivante :
    stringBuilder=Pattern.compile("expr").matcher("stringBuilder").replaceAll("newvalue"); On économise ainsi une copie.

Ne pas hésiter à décompiler les classes String et StringBuilder pour bien comprendre comment tout ça fonctionne. C'est très instructif et ça aide beaucoup à optimiser le code.

mardi 24 juin 2008

Mort aux fichiers xml de configuration

En tant que développeur Java, je déteste passer mon temps à écrire des fichiers xml. La plupart des frameworks à la mode demandent d'énormes fichiers de configuration qui ont la facheuse habitude de nécessiter à chaque modification un redémarrage des applications.

Pourquoi ne pas coder tout ça en Java directement ? Pour l'essentiel, il ne s'agit pas de paramétrages mais de choses qui ne changeront jamais dans la vie de l'application. Alors pourquoi supporter un parsing lourd et source de bugs à chaque démarrage de l'application ? Les rares paramètres qui nécessitent réellement d'être changés de temps en temps sont ceux qui dépendent de la configuration de déploiement (machines, adresses, mots de passe...), ils tiendraient dans un properties.