[java-web] ThreadLocal icm Filter

Pagina: 1
Acties:

  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 04-05 13:54
Ik wou de de huidige gebruiker in een ThreadLocal variabele opslaan om zo in andere plaatsten van men applicatie aan de huidige gebruiker te kunnen (dit zonder telkens een object te moeten doorgeven)

ik doe dit nu in de men Filter klasse, maar blijkbaar gaat hier iets verloren, als een paar keer de filter opgeroepen wordt dan is men object plots uit men thread verdwenen, ik weet niet echt wat er verkeerd loopt.

enkel stukjes code:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserThreadManager {
    
    private static ThreadLocal threadLocal = new ThreadLocal();
    
    private UserThreadManager() {
        
    }
    public static void setUser(User user) {
        threadLocal.set(user);
    }
    public static User getUser() {
        return (User) threadLocal.get();
    }
}


dit gebruik ik om men user op te halen en te bewaren.
Hieronder een stukje van men filter. In men filter kijk ik of er al een userObject in men sessie zit, indien dit niet zo is, dan steek ik er eentje in (nu om het eenvoudig te houden enkel de userName en domein). Op dit moment plaats ik ook men user object ook in een threadLocal variabele. Via de output kan ik zien wat er zich in de sessie en thread variabele zit.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    public void doFilter(
        ServletRequest req,
        ServletResponse resp,
        FilterChain chain)
        throws ServletException, IOException {

...
        User user = StrutsUtils.getUser(req.getSession());
        

        System.err.println("voor if ---" + user + "---");
        System.err.println("voor if ---" + UserThreadManager.getUser() + "---");
        if (user == null) {
            
            NtlmPasswordAuthentication ntlm = (NtlmPasswordAuthentication) req.getSession().getAttribute("NtlmHttpAuth");
            user = new User();
            user.setUserName(ntlm.getUsername());
            user.setDomain(ntlm.getDomain());
                    
            UserThreadManager.setUser(user);

            StrutsUtils.setUser(req.getSession(), user);
            
        }
        System.err.println("na if ***" + user + "***");
        System.err.println("na if ***" + UserThreadManager.getUser() + "***");
        chain.doFilter(req, resp);
    }


als ik eerst men applicatie opstart krijg ik dit:

code:
1
2
3
4
[18/05/05 17:07:46:559 CEST] 799ae14e SystemErr     R voor if ---null---
[18/05/05 17:07:46:559 CEST] 799ae14e SystemErr     R voor if ***null****
[18/05/05 17:07:46:715 CEST] 799ae14e SystemErr     R na if ---be.oz.common.vo.User@3521e169---
[18/05/05 17:07:46:715 CEST] 799ae14e SystemErr     R na if ***be.oz.common.vo.User@3521e169***


dit klopt dus, 1ste maal geen user in de sessie noch in de threadvariable, maar na enkele keren klikken (soms slechts 1 maal) binnen men applicatie krijg ik snel het volgende als output:

code:
1
2
3
4
[18/05/05 17:09:08:260 CEST] 126ae149 SystemErr     R voor if ---be.oz.common.vo.User@3521e169---
[18/05/05 17:09:08:260 CEST] 126ae149 SystemErr     R voor if ***null****
[18/05/05 17:09:08:260 CEST] 126ae149 SystemErr     R na if ---be.oz.common.vo.User@3521e169---
[18/05/05 17:09:08:260 CEST] 126ae149 SystemErr     R na if ***null***


de variabele in men thread is dus weg

enige verklaring hiervoor ?

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 04-05 13:54
hoe zou ik kunnen achterhalen wanneer die threadlocal variabele z'n waarde verliest ?

het vorige probleem kan ik simpel oplossen door

Java:
1
UserThreadManager.setUser(user);


buiten de if blok te plaatsen, maar dan wordt deze telkens gezet als de filter opgeroepen wordt, maar zo weet ik nog altijd niet waar de gegevens verloren gaan...

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • zneek
  • Registratie: Augustus 2001
  • Laatst online: 08-02-2025
Cuball schreef op donderdag 19 mei 2005 @ 08:17:
hoe zou ik kunnen achterhalen wanneer die threadlocal variabele z'n waarde verliest ?

het vorige probleem kan ik simpel oplossen door

Java:
1
UserThreadManager.setUser(user);


buiten de if blok te plaatsen, maar dan wordt deze telkens gezet als de filter opgeroepen wordt, maar zo weet ik nog altijd niet waar de gegevens verloren gaan...
Waar raakt hij die gegevens kwijt dan? Als je die set buiten de if doet wordt de User altijd aan een threadlocal gebonden. In de gehele request afhandelende thread zou die gewoon beschikbaar moeten zijn. Kun je een concreet voorbeeld geven van de aangeroepen zaken (servlets, jsps) en waar precies de threadlocal zijn waarde kwijt is?

[edit] Overigens is die threadlocal slechts bereikbaar voor 1 request. Je zult hoe dan ook bij elke request de User uit de sessie moeten vissen en hem in de threadlocal zetten. Doe dit trouwens alleen als je de User nodig bent op plaatsen waar je niet bij de Sessie kunt. Anders kun je de user net zo goed uit de SessionContext halen (binnen een jsp of servlet kan dat)

[ Voor 20% gewijzigd door zneek op 19-05-2005 12:58 ]


  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 04-05 13:54
zneek schreef op donderdag 19 mei 2005 @ 12:54:
[...]


Waar raakt hij die gegevens kwijt dan? Als je die set buiten de if doet wordt de User altijd aan een threadlocal gebonden. In de gehele request afhandelende thread zou die gewoon beschikbaar moeten zijn. Kun je een concreet voorbeeld geven van de aangeroepen zaken (servlets, jsps) en waar precies de threadlocal zijn waarde kwijt is?
Ik heb het een beetje verkeerd geformuleerd, als hij buiten de if staat dan behoud ik weldegelijk de waarde! Maar men redenering was verkeerd met het veronderstellen dat ik slechts 1 maal die thread variabele moet zetten. Ik wist niet dat elke nieuwe request ook een nieuwe thread was
[edit] Overigens is die threadlocal slechts bereikbaar voor 1 request. Je zult hoe dan ook bij elke request de User uit de sessie moeten vissen en hem in de threadlocal zetten. Doe dit trouwens alleen als je de User nodig bent op plaatsen waar je niet bij de Sessie kunt. Anders kun je de user net zo goed uit de SessionContext halen (binnen een jsp of servlet kan dat)
Ik gebruik deze nu (voorlopig enkel) om in men datalaag de update gebruiker weg te schrijven. Alle objecten die we gebruiken hebben bv een updateUser, updateTime. De update user schrijf ik weg in de objecten in een eigen Hibernate interceptor. Deze gebruiker haal ik dus op uit de ThreadLocal.

Is dit verkeerde manier van werken ?

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • zneek
  • Registratie: Augustus 2001
  • Laatst online: 08-02-2025
Cuball schreef op donderdag 19 mei 2005 @ 13:28:
[...]


Ik heb het een beetje verkeerd geformuleerd, als hij buiten de if staat dan behoud ik weldegelijk de waarde! Maar men redenering was verkeerd met het veronderstellen dat ik slechts 1 maal die thread variabele moet zetten. Ik wist niet dat elke nieuwe request ook een nieuwe thread was

[...]


Ik gebruik deze nu (voorlopig enkel) om in men datalaag de update gebruiker weg te schrijven. Alle objecten die we gebruiken hebben bv een updateUser, updateTime. De update user schrijf ik weg in de objecten in een eigen Hibernate interceptor. Deze gebruiker haal ik dus op uit de ThreadLocal.

Is dit verkeerde manier van werken ?
Ik kan daar zo niet iets zinnigs over roepen. Ik heb zelf ook wel eens een vergelijkbare constructie gebruikt. Zolang je de garantie hebt dat de datalaag alleen vanuit de webapplicatie gebruikt wordt is het prima. Vraag je echter eens af wat er gebeurt als een andere thread, van een of ander server proces, ook een update actie probeert uit te voeren. Dan zal de threadlocal met de user erin niet bestaan.