2015-03-04 6 views
5

ich einige Legacy-Code haben, die Objekte als http-Sitzung setzen Attribute Code wie folgt verwendet:Wie eine HTTP-Session-Attribut auf eine Bohne injizieren CDI mit

MyObject object = new MyObject(); 
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap(); 
sessionMap.put("attrname", object); 

Die alten facelets den Code zugegriffen

@ManagedProperty("#{attrname}") 
private MyObject object; 
mit

Gibt es eine Möglichkeit CDI (@Inject) zu verwenden, um dieses Sitzungsattribut einer Bean zu injizieren?

In neuem Code, der CDI verwendet, ist der beste Weg, Objekte zu erstellen und zu injizieren, die auf kontrollierte Weise erstellt werden müssen.

Antwort

7

Erhalten Sie es in einer Session-Bereich verwaltete Bean mit einem @Produces@Named auf dem Getter.

@SessionScoped 
public class MyObjectProducer implements Serializable { 

    private MyObject myObject; 

    @Produces 
    @Named("attrname") 
    public MyObject getMyObject() { 
     return myObject; 
    } 

    public void setMyObject(MyObject myObject) { 
     this.myObject = myObject; 
    } 

} 

Wenn Sie es irgendwie über z. myObjectProducer.setMyObject(myObject) woanders (oder vielleicht ein CDI @Observes Ereignis), dann können Sie es überall mit @Inject @Named injizieren.

@Inject 
@Named("attrname") 
private MyObject myObject; 

Und ja, es ist immer noch über #{attrname} in EL die übliche Art und Weise. Und nein, es wird nicht automatisch erstellt, wenn es nicht festgelegt wird, es bleibt null, bis Sie es tatsächlich als eine Eigenschaft der Producer-Klasse festlegen.


Alternativ, wenn Sie wirklich das Erbe Art und Weise des Einstellens der Instanz über ExternalContext#getSessionMap() halten wollen (zB weil es Dritten ist und Sie können somit nicht geändert werden), dann können Sie alternativ lassen auch der Produzent es direkt zurück aus der Sitzung Karte:

@SessionScoped 
public class MyObjectProducer implements Serializable { 

    @Produces 
    @Named("attrname") 
    public MyObject getMyObject() { 
     return (MyObject) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("attrname"); 
    } 

} 

Dies ist jedoch nicht offensichtlich ist garantiert, wenn in einem nicht-JSF Artefakt, wie eine willkürliche @WebServlet, wie die FacesContext#getCurrentInstance() würde null zurückkehren injiziert zu arbeiten.

+0

Danke @BalusC für Ihre schnelle und vollständige Antwort. –

+2

Vielleicht könnte die Antwort noch vollständiger sein und sagen, dass für den Zugriff auf den Producer aus nicht verwaltetem Code dieser Code 'CDI.current(). Select (MyObjectProducer.class) .get()' verwendet werden kann. –

1

Dies ist der Weg zu gehen, für beide nicht-JSF und JSF-Artefakte.

@Qualifier 
@Retention(RUNTIME) 
@Target({TYPE,METHOD,FIELD,PARAMETER}); 
public @interface SessionAttribute { 

    @NonBinding 
    String value() default ""; 
} 

@ApplicationScope 
public class SessionAttributeService { 

    //Dont worry, this is a proxy, and CDI will ensure that the right one called at the right time. 
    @Inject 
    private HttpServletRequest servletRequest; 

    @Produces 
    @SessionAttribute 
    @RequestScope 
    public String sessionAttribute(final InjectionPoint ip){ 
    final SessionAttribute sa = ip.getAnnotated().getAnnotation(SessionAttribute.class); 
    final HttpSession session = servletRequest.getSession(); 
    return session.getAttribute(sa.value()); 
    } 
} 

und Anwendungsfall:

@RequestScope 
public class MyServiceBean { 

    @Inject 
    @SessionAttribute("theAttribute") 
    private String attribute; 

} 
+0

Dies ist nicht in der Lage, Nicht-String-Werte zu injizieren, wie es OP erfordert. Ich würde es definitiv nicht als "den Weg" für "Sitzungsattribute" im Allgemeinen bezeichnen. – BalusC

+1

Wirklich @BalusC Ich gab einfach ein Beispiel mit Strings, er kann einfach den Typ ändern, was immer er will ??? – maress