mercredi 30 mars 2011

Faire tourner GWT sur un environnement .NET, qui a dit impossible ?

Après avoir réussi à faire tourner et à compiler des applications Java Spring / Hibernate sous environnement .NET à l'aide de IKVM, l'étape suivante : faire tourner une application web java dans IIS. Pour tester, quel meilleur exemple qu'une application GWT ?

A priori personne n'avait tenté ça avant nous. Les articles trouvés sur internet parlaient d'essais de développement de services RPC dans d'autres technologies avec GWT utilisé uniquement pour la partie client (html et javascript). Notre objectif était différent : développer une interface web en utilisant GWT à la fois pour la partie client (html et javascript) et pour la partie serveur (servlet RPC), donc vraiment un développement standard GWT. Ensuite utiliser IKVM pour compiler cette application en .NET et la transformer en une application web .NET pour la faire tourner dans un serveur IIS.

Deux difficultés :

  1. compiler le code java, en particulier GWT à l'aide de IKVM
  2. faire un pont entre l'API Servlet Java et l'API System.web
Eh bien ça marche !

L'article complet se trouve ici :

mardi 8 février 2011

Article sur ESIGate

Pour ceux qui ne connaitraient pas encore ESIGate, un petit article qui explique ce que c'est :
http://blog.smile.fr/ESIGate-le-portail-d-un-genre-nouveau

Pas évident d'expliquer à quoi ça sert sans trop rentrer dans les détails techniques...
Sinon ESIGate c'est ici :
http://www.esigate.org

Marier Java et .NET à l'aide de IKVM

IKVM, la machine virtuelle Java écrite en .NET semble maintenant être arrivée à maturité. Rappel des principes :

  • partant du constat que le JDK et le framework .NET se ressemblent énormément (les mauvaises langues diront qu'ils se copient mutuellement) IKVM, plutôt que de réimplémenter un JDK à partir de zéro, implémente les fonctionnalités du JDK soit en utilisant la fonctionnalité correspondante du framework .NET soit en réutilisant du code de OpenJDK
  • IKVM tourne sous environnement Microsoft .NET ou Mono mais c'est déjà bien puisque on peut déjà choisir entre les environnements Windows ou Linux
  • IKVM permet de convertir une librairie Java en .NET pour utilisation dans une application .NET (un .jar devient une .dll !)
Il restait à vérifier que l'outil est bien à la hauteur de ses promesses en faisant un proto faisant tourner une applications Java et des librairies Java complexe dans cette environnement. Le choix s'est porté sur une application utilisant Spring et Hibernate. Le résultat est au delà  des espérances :
  • l'application java fonctionne et peut même être convertie en un fichier .exe !
  • un rapide test de performances montre des résultats similaires à la même application tournant avec le JDK Oracle
L'article détaillé se trouve ici :

Prochaine étape : arriver à faire tourner une application web java dans IIS. Les tests en cours sont encourageants.

lundi 2 novembre 2009

Parser une page HTML ou la transformer avec XSL

En Java, quelques outils open-source permettent de traiter comme un fichier xml une page HTML, même mal formée au sens xml (par exemple avec des balises non fermées type "<br>").

J'ai testé un peu les deux outils les plus connus htmlparser et CyberNeko ainsi qu'un troisième que je ne connaissais pas : validator.nu HTML Parser

Ce que j'ai noté :

htmlparser
  • pas de dépendances (pratique pour l'utiliser dans un projet)
  • le parsing se fait via une API propriétaire
  • il permet de construire un document en mémoire qu'on peut ensuite manipuler (pas terrible si on veut s'en servir sur des gros volumes)
  • l'outil peut charger une page directement depuis le web
  • assez pratique à utiliser pour réaliser un crawler de sites
  • projet peu actif (la dernière version stable date de juin 2006, autant dire que le projet est mort)
CyberNeko
  • dépend de Xerces dont il utilise l'API (assez gênant quand on l'utilise dans un projet vu qu'il ramène une version de XercesImpl ainsi que de xml-apis)
  • transforme une page en un document DOM (pas idéal pour les performances)
  • normalise tous les tags en html 4 (noms de tags en majuscules, attributs en minuscules) mais sans notion de namespace. Un peu surprenant.
  • projet actif (la dernière version stable date de septembre 2009)
  • donne de bon résultats en performances d'après le benchmark réalisé par le projet PortletBridge
Validator.nu HTML Parser
  • projet récent et actif
  • implémentation de l'algorithme de parsing standardisé html 5
  • pas de dépendances (pratique pour l'utiliser dans un projet)
  • permet de faire du SAX
  • permet de transformer directement un document via xslt
  • nécessite un parser xml pas trop ancien (ne fonctionne pas par exemple avec le plugin maven cargo et jetty embedded)
  • compilable avec GWT (ça peut servir ?)
  • attribue par défaut aux tags html le namespace xmlns="http://www.w3.org/1999/xhtml" donc il vaut mieux bien connaitre la manipulation des namespaces avant de s'en servir
Personnellement, je préfère largement le troisième qui m'a permis de transformer une page html non conforme xml en seulement quelques lignes de code et sans faire de DOM, uniquement en SAX et sans introduire de dépendances supplémentaires dans mon projet.

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.