Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JSF] In managed bean achter eigen managed name komen?

Pagina: 1
Acties:

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
Hoi,

Voor een speciale constructie waar ik programmatisch vanuit een backing bean een component toe voeg aan de JSF component tree, heb ik vanuit deze backing bean instantie mijn eigen managed naam nodig. Het component moet namelijk op deze bean een callback kunnen doen na een postback.

Het principe is dus een beetje een soort managed "this".

Momenteel gebruik ik hiervoor een beetje een work around: een custom VariableResolver die na de oorspronkelijke lookup de name via reflection in een annotated field zet. Dat werkt, maar het is een vervelende oplossing. Dit gebeurd namelijk elke keer als welke variable dan ook wordt opgevraagd, hoe vaak dat ook gebeurd.

In de SUN RI implementatie weet tenminste de BeanManager class wanneer een bean echt gemaakt wordt, maar deze class in non-pluggable. Ook de Servlet API schiet niet te help. Voor session scoped beans is wel HttpSessionBindingListener geschikt, maar voor request scoped beans is er alleen de algemene ServletRequestAttributeListener, waarin ik weer exact hetzelfde werk zou moeten doen als in de huidige VariableResolver (kijken of het object geïnteresseerd is in z'n naam en die hem dan geven).

Weet er iemand een betere oplossing?

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Een oplossing zonder variableresolvers en reflectie is om de values van de RequestMap, SessionMap en ApplicationMap te vergelijken met de 'this' en bij een match de bijbehorende key retourneren.

Zoiets dus:
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
29
30
31
32
33
34
35
36
37
38
39
40
    public static String lookupManagedBeanName(Object bean) {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();

        // Get requestmap.
        Map<String, Object> requestMap = externalContext.getRequestMap();
    
        // Lookup the current bean instance in the request scope.
        for (String key : requestMap.keySet()) {
            if (bean.equals(requestMap.get(key))) {
                // The key is the managed bean name.
                return key;
            }
        }
    
        // Bean is not in the request scope. Get the sessionmap then.
        Map<String, Object> sessionMap = externalContext.getSessionMap();

        // Lookup the current bean instance in the session scope.
        for (String key : sessionMap.keySet()) {
            if (bean.equals(sessionMap.get(key))) {
                // The key is the managed bean name.
                return key;
            }
        }

        // Bean is also not in the session scope. Get the applicationmap then.
        Map<String, Object> applicationMap = externalContext.getApplicationMap();

        // Lookup the current bean instance in the application scope.
        for (String key : applicationMap.keySet()) {
            if (bean.equals(applicationMap.get(key))) {
                // The key is the managed bean name.
                return key;
            }
        }

        // Bean is also not in the application scope.
        // Is the bean's instance actually a managed bean instance then? =)
        return null;
    }
Gebruiksvoorbeeld binnen een backing bean:
Java:
1
String managedBeanName = FacesUtil.lookupManagedBeanName(this);

Bron: http://balusc.blogspot.co...nNameInsideTheBackingBean

Verwijderd

Dat aflopen van die scopes en vergelijken met this is inderdaad wel een mooie methode.

Wat we zelf een tijdje terug gedaan hadden (beetje uit wanhoop) is de gebruikte backing bean een binding geven naar een eigen no-op custom component. Daarna kan die bean, als ie zijn eigen naam wilde weten, dan de component tree aflopen op zoek naar die ene speciale custom component en daar dan de name uit halen.

Natuurlijk moet je hiervoor onthouden een extra handeling te doen in elke view waar je de backing bean gebruikt, dus zeker geen ideale oplossing. De bean gewoon zijn naam geven via een managed property in de managed bean declaratie in faces-config is een andere oplossing, maar ook een beetje rottig om te doen.

Het nadeel van de BalusC methode is wel dat het niet gaat werken als je bean ook in hele andere scopes kan voorkomen, zoals bijvoorbeeld Spring of misschien de conversational scopes van Seam of Orchestra.

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
BalusC schreef op woensdag 26 maart 2008 @ 00:00:
Een oplossing zonder variableresolvers en reflectie is om de values van de RequestMap, SessionMap en ApplicationMap te vergelijken met de 'this' en bij een match de bijbehorende key retourneren.
Nice, en had ik natuurlijk ook zelf moeten kunnen bedenken eigenlijk :P Thanks!
Het nadeel van de BalusC methode is wel dat het niet gaat werken als je bean ook in hele andere scopes kan voorkomen, zoals bijvoorbeeld Spring of misschien de conversational scopes van Seam of Orchestra.
Das waar en sommige van onze projecten gebruiken ook daadwerkelijk Spring, maar aangezien ik daar zelf (nog) niks mee doe is het voor dit moment eigenlijk zeker wel goed genoeg. Leuk zou zijn als de JSF API hier nog eens met een expliciete methode voor zou komen.

Voor mijn VariableResolver aanpak (tegenwoordig moet dat eigenlijk de ELResolver worden, maar de code moet nog op JSF 1.1 kunnen draaien) zat ik nog wel te denken om de VariableResolver uit te rusten met een cache waarin ik onthoud of een Class die ik al eerder had gezien de annotation heeft of niet en een simpele variable in request scope die bijhoud of een class met de annotation z'n naam al heeft gehad of niet gedurende de huidige request.

Maar voorlopig ga ik denk ik maar de methode van BalusC gebruiken en hou de VariableResolver achter de hand voor als ie ooit nog nodig is.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.