IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement Web en Java Discussion :

[Conception] ThreadLocal dans un context web


Sujet :

Développement Web en Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    68
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 68
    Par défaut [Conception] ThreadLocal dans un context web
    Bonjour à tous,

    Certains design pattern (AuthenticatedUserHolder, SessionHolder, ...) sont basés sur un ThreadLocal. En réalité derrière cet objet se cache une map (WeakHashMap) dont la clé est un thread ID et la valeur est un objet quelconque. La question est la suivante : dans une application web comment Java se débrouille-t-il pour récupérer la valeur sachant que chacune des request est exécutée dans un thread différent ?

    Merci à tous ceux ont tenté ou réussi à m'aider.

    Coyote

  2. #2
    Membre Expert
    Avatar de azerr
    Homme Profil pro
    Ingénieur Etude JEE/Eclipse RCP
    Inscrit en
    Avril 2006
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Etude JEE/Eclipse RCP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 942
    Par défaut
    Bonjour coyote999,

    La question est la suivante : dans une application web comment Java se débrouille-t-il pour récupérer la valeur sachant que chacune des request est exécutée dans un thread différent ?
    J'adore ThreadLocal. Et ta remarque est tres pertinente. En fait lorsque tu appele une page cela instancie une nouvelle Thread ou reutilise une Thread du pooling. Donc pour utiliser une ThreadLocal il faut la mettre a jour l'instance stocke dans le ThreadLocal a chaque appel (a l'iade d'un fileter par exemple).

    En ce qui me concerne, je mets souvent le user Session dans une ThreadLocal comme ca je peux le recuperer sans avoir le contexte HTTP Session. Et je mets a jour l'instance session a chaque fois qu'uen URL est appele (avec Struts tu peux utiliser le RequestProcessor, mais tu peux creer aussi un filtre et mettre a jour dans la methode doFilter).

    Angelo

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    68
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 68
    Par défaut AuthenticatedUserHolder
    Bonsoir Azerr,

    tout d'abord merci pour ta réponse rapide :-) . J'ai relu attentivement ta réponse mais je ne comprends pas l'intérêt d'utiliser un filter pour mettre à jour le contenu du ThreadLocal et je ne comprends toujours pas comment Java fait pour retrouver ses petits.

    Voici le code de l'AuthenticatedUserHolder :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public final class AuthenticatedUserHolder {
     
            private AuthenticatedUserHolder() {
               // do nothing - avoid to instantiate the classe from outside
            }
     
    	private static ThreadLocal userHolder = new ThreadLocal();
     
    	public static void setUser(User user){
    		userHolder.set(user);
    	}
     
    	public static User getUser(){
    		return (User) userHolder.get();
    	}
    }
    Ce bout de code semble bien fonctionner (je dis semble) et ce même si il y a plusieurs utilisateurs connectés. Je n'emploie pas de Filter. Pourrais-tu m'expliquer comment le tout fonctionne ? Et éventuellement (si je n'abuse pas) me donner un bout de code ou une piste pour l'implémentation du filter à mettre en place pour mettre à jour le contenu du ThreadLocal ?

    Je t'en remercie d'avance. J'insiste sur le ThreadLocal car je suis consultant J2EE et que le côté technique m'intéresse énormément.

    Coyote

  4. #4
    Membre Expert
    Avatar de azerr
    Homme Profil pro
    Ingénieur Etude JEE/Eclipse RCP
    Inscrit en
    Avril 2006
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Etude JEE/Eclipse RCP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 942
    Par défaut
    Ce bout de code semble bien fonctionner (je dis semble) et ce même si il y a plusieurs utilisateurs connectés.
    Ma question est quand execute tu ce code ?:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AuthenticatedUserHolder.setUser(user);
    Une ThreadLocal est une thread qui s'attache a la tache courante. Donc imagine que tu as un pooling de connection avec 2 Thread.

    Le premier user se connecte Thread1 est execute et la ThreadLocal stocke user1.

    Le 2eme user se connecte Thread2 est execute et la ThreadLocal stocke user2.

    Le 3eme user se connecte Thread1 est execute et la ThreadLocal a user1 mais efface user1 par user3.

    Le premier user accede a une page, Thread1 est execute et la ThreadLocal a user3 et pas user1.

    Je ne sais pas si mon exemple est comprehensible. Mais j'ai tente d'explique comment se comporte ThreadLocal.

    Donc pour assurer que le user stocke dans la ThreadLocal est correcte, je mets a jour le user a chaque fois qu'il accede a une page. En fait le user est stocke a la fois dans la session HTTPP et dans la ThreadLocal.

    En gros le code (doFilter) du Filter est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    User user = (User)session.getAttribute("user");	
    if (user != null) {
        // Le user s'est conncete prealablement, maj de la ThreadLocal
          AuthenticatedUserHolder setUser(user);
    }
    else {
      // Récuperation du UserPrincipal instancié par le mecanisme std
      Principal principal = request.getUserPrincipal();
     
       // Appel du service d'authentification
       user = .....
       // Mise a jour la session HTTP + ThreadLocal
       session.setAttribute("user",user);	
       AuthenticatedUserHolder setUser(user);
    }
    Angelo

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    68
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 68
    Par défaut Cela devient plus clair
    Ah OK :-) J'avais compris la manière dont fonctionnait ThreadLocal mais j'ignorais qu'il fallait le mettre à jour à chaque fois que l'utilisateur lançait une requête.

    Voici ce que je faisais : l'utilisateur se connectait et en cas de connexion valide le User était stocké dans l'AuthenticatedUserHolder. Lorsque j'en avais besoin je faisait appel à ce ThreadLocal et faisait un get dessus. Mais étrangement je récupèrais à chaque fois le bon utilisateur. Je précise tout de même que les tests ont été faits avec 2 ou 3 utilisateurs connectés à la fois. Donc en conclusion, le fait que je récupère le bon utilisateur était dans mon cas de la chance...

    Quels sont d'après toi les cas où l'utilisation d'un ThreadLocal se justifie. Je sais que certains développeurs y stocke la request... Qu'en penses-tu ? D'après mon architecte le ThreadLocal pourrait entraîner des memory leak. D'après toi est-ce érroné ?

    Quoiqu'il en soit je te remercie pour ton aide, vraiment!!! Des collègues expérimentés n'ont pas été capable de me répondre.

  6. #6
    Membre Expert
    Avatar de azerr
    Homme Profil pro
    Ingénieur Etude JEE/Eclipse RCP
    Inscrit en
    Avril 2006
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Etude JEE/Eclipse RCP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 942
    Par défaut
    Bonjour,
    J'avais compris la manière dont fonctionnait ThreadLocal mais j'ignorais qu'il fallait le mettre à jour à chaque fois que l'utilisateur lançait une requête.
    En fait ce qu'il faut bien comprendre c'est qu'une ThreadLocale s'attache a la Thread courante. Dans un contexte WEB une requete HTTP est une Thread qui est cree ou provient du pooling de Thread du serveur. Donc c'est pour cela que dans mon cas (et ton cas) que le user doit etre mis a jour.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Je précise tout de même que les tests ont été faits avec 2 ou 3 utilisateurs connectés à la fois.
    Ca ca me chagrine quand meme. Ce que je te dis est la conclusion que je me suis faite lors de mes tests. D'avoir autant de chance c'est vraiment tres bizarre?

    Je sais que certains développeurs y stocke la request... Qu'en penses-tu ?
    Je pense que c'est une bonne idee. A verifier mais je croies que Struts2 utilise cette technique avec ServletActionContext

    D'après mon architecte le ThreadLocal pourrait entraîner des memory leak. D'après toi est-ce érroné ?
    ThreadLocal est enormement utilise dans beaucoup de frameworks (Spring, Hibernate, Struts2....) donc je pense que c'est un classe indispensable.

    Apres je ne suis pas un expert en ThreadLocal. Peut etre qu'il y a ds cas d'utilisation qui pose des problemes? Ton architecte pourrait exposer les problemes de memory leak?

    Angelo

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    68
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 68
    Par défaut Architecte = clown
    Non l'architecte a uniquement le titre, avance des affirmations mais n'a pas la connaissance :-) Enfin bref. Je te remercie pour ton aide précieuse.

    A très bientôt j'espère,

    Kevin

  8. #8
    Membre Expert
    Avatar de azerr
    Homme Profil pro
    Ingénieur Etude JEE/Eclipse RCP
    Inscrit en
    Avril 2006
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Etude JEE/Eclipse RCP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 942
    Par défaut
    Non l'architecte a uniquement le titre, avance des affirmations mais n'a pas la connaissance
    Beuuuuuuurkkkkkk, je deteste ca!!!!

    Enfin bref. Je te remercie pour ton aide précieuse.
    De rien, mais le fait que tu me dises que ca marche, me chagrine quand meme.

    Angelo

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 10/09/2010, 17h30
  2. ThreadLocal devient null dans mon application Web
    Par enjoy dans le forum Servlets/JSP
    Réponses: 8
    Dernier message: 12/02/2008, 16h32
  3. Spring context dans une appli web
    Par Sniper37 dans le forum Spring Web
    Réponses: 4
    Dernier message: 06/09/2007, 09h31
  4. [Conception] Comment utiliser une BDD dans un site WEB ?
    Par Smollben dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 12/08/2007, 15h08
  5. Charger le contexte d'application dans une appli WEB
    Par nanou2002 dans le forum Spring Web
    Réponses: 3
    Dernier message: 13/10/2006, 10h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo