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.