27 janvier 2012

Client Jax-WS : not thread-safe

Ahhhh, là c'était un peu tricky. ClassCastExeption à la sortie du Web Service.
Mince, l'objet reçu n'est pas celui attendu par JAXB ! Et le plus drôle ? Impossible de reproduire en local, ben oui ce serait trop facile sinon.

Heureusement des tests de charge...avec 10 utilisateurs max en parallèles montrent un comportement imprévisible : dès fois ça marche !
Puis des tests de charge...avec 1seul utilisateur montrent que ça marche. Tout le temps.

Bref, l'appli fonctionne très bien en mode mono-utilisateur...Mais ne supporte pas le multithreading.

Tentant d'accuser les Web Services, n'est-ce pas ? Hé bien non, l'erreur est du côté client !

Mais qu'est-ce donc ? Un problème technique comme une mauvaise version de librairie jax-ws ? Un problème au niveau du dev comme un code non thread-safeLes 2 mon capitaine !


Un faisceau d'indices me conduit à étudier jax-ws :
  • les librairie jax-ws sont dans le répertoire [JBoss_Home]/lib/endorsed pour des raisons de compatibilité de JBoss 5.1 avec le jdk6
  • la version 3.2 corrige justement un bug de confusion de retour de Web Service !
Mais cela ne sera pas suffisant à corriger le problème. Finalement, je relis le code.

  • Rappel Code client de JAX-WS :
Monservice service = new MonService(url);
Mon proxy = service.getPort()

  • Pour optimisation, le programme stocke une instance de service ainsi qu'une instance de proxy. Les threads se partagent cette dernière,  potentiellement en parallèle,  pour tout appel à un Web Service. 
Aïe, le doute m'assaille ! Ces objets sont-ils thread-safe ?

L'information n'est pas si claire : 
  • sur les forums je trouve des réponses affirmatives, d'autres assurent le contraire.
  • Sur le site CXF : c'est Oui (avec CXF et non avec l'implémentation de référence).
  • Enfin, sur le site de JBoss, je trouve ma réponse : Pour l'implémentation de JBoss, service est thread-safe mais pas proxy.

En résumé, je change le comportement pour retourner à chaque demande une nouvelle instance de proxy.
Les performances risquent de s'en trouver amoindries mais tout fonctionne parfaitement.


2 commentaires:

  1. Non optimisé, ça se discute.
    D'autres corrections sont possibles, mais pas forcément meilleures...

    En bref, l'erreur initiale est l'écriture en environnement multi-threadé d'un code d'accès statique à un objet dont la Javadoc ne dit pas explicitement qu'il est thread-safe. Il faut toujours supposer d'un objet qu'il "peut le moins" et se limiter à ce qu'il dit savoir faire.

    RépondreSupprimer
  2. Il y a peut-être eu un changement de librairie : CXF d'abord, puis jbossws-native. Un vrai piège!
    J'ajoute que la spécification officielle n'était pas claire là-dessus, pour preuve les nombreuses questions sur les forums à ce sujet restées sans réponse. Comme ici, par souci de performance : http://markmail.org/message/gab5mztq33omeynf#query:+page:1+mid:gab5mztq33omeynf+state:results

    RépondreSupprimer