# Wie eine stateful session bean erneut "aufgreifen"



## Raphalon (3. Sep 2012)

Hallo,

wenn man einen Warenkorb serverseitig, nicht persistent speichern möchte (@Stateful), wie kann man zu einem späteren Zeitpunkt (etwa wenn der Anwender nach einigem Surfen wieder ein Produkt hinzufügen möchte), auf dieselbe stateful session Bean zugreifen, in der z.B. das bereits als erstes ausgewählte und hinzugefügte Produkt enthalten ist? Wird diese im session Scope unter einem Namen in der Attributmap abgelegt? Wie macht man so etwas? Sollte man StatefulBeans überhaupt verwenden oder nicht doch gleich im Session-Objekt den Warenkorb speichern?

Gruß

Raphalon


----------



## F.S.WhiTeY (3. Sep 2012)

Moin,

wenn ich mich nicht irre, ist 
	
	
	
	





```
@Statefull
```
 ja eine reine EJB geschichte. Es kommt nun drauf an wie du den Rest deiner Applikation aufgebaut hast. Sprich was du als UI-Komponente verwendest.

Wenn du JSF verwendest würde ich dir von einer reinen EJB abraten. Ansonsten ist es so gerergelt, dass eine 
	
	
	
	





```
statefull session bean
```
 sich selbst verwaltet. Der Zugriff des Usesers wird vom Container automatisch geregelt. Dabei werden weder Cookies noch sonstige authentifizierungen angelegt. Der User muss lediglich immer ein und die selbe Refferenz nutzen.

Um also genauer auf deine Frage einzugehen: Mir ist es nicht bekannt, das man auf eine 
	
	
	
	





```
statefull session bean
```
 per 
	
	
	
	





```
SessionMap
```
 zugreifen kann. Der Hintergrund ist, dass diese Bean stirbt wenn der "Talk" zu Ende ist oder die Session ausläuft. 
Theoretisch sollte also jedes "Produkt-Objekt" automatisch im "Warenkorb-Objekt" landen ohne das du etwas dazu tust. 

LG


----------



## Raphalon (3. Sep 2012)

F.S.WhiTeY hat gesagt.:


> Wenn du JSF verwendest würde ich dir von einer reinen EJB abraten.


Warum? Was würde man statt dessen verwenden?



F.S.WhiTeY hat gesagt.:


> Ansonsten ist es so gerergelt, dass eine
> 
> 
> 
> ...


Ich verwende JSF. Wie stelle ich diese "Referenz" her? Beim ersten Produkt wird die Bean erzeugt und das Produkt hinzugefügt. Wird dann *automatisch* dieselbe Instanz der SFSB referenziert, wenn ein zweites Produkt hinzugefügt wird? (genügt es praktisch, in der JSF-Seite z.B. über einen h:commandButton die Methode der entsprechenden Bean aufzurufen und der Container erkennt dann automatisch, dass es sich um dieselbe Bean wie beim ersten mal handelt?)


----------



## F.S.WhiTeY (3. Sep 2012)

> Beim ersten Produkt wird die Bean erzeugt und das Produkt hinzugefügt. Wird dann automatisch dieselbe Instanz der SFSB referenziert, wenn ein zweites Produkt hinzugefügt wird?



Falsch und richtig zugleich 

Erstens arbeitet JSF 2.0, das 2.0 ist wichtig, mit ManagedBeans. ManagedBeans sind eine abwandlung der reinen EJBs. Das bedeutet eine SessionScoped ManagedBean ( was ganz anderes als eine Statefull Session Bean ) wird genau dann erzeugt wenn eine Session beginnt. Diese Session kann nach einem Login anfangen, aber auch nach einem Request. 

Das was du bei JSF suchst sieht so aus:


```
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped

public class WarenkorbBean {

public WarenkorbBean(){
}

@PostConstruct
public void init(){

//Wird genau dann aufgerufen wenn dieses Objekt initialisiert wurde
//Also genau nach dem Konstruktor 

}

@PreDestroy
public void destroy(){

//Wird genau dann aufgerufen wenn dieses Objekt kurz vor dem sterben liegt
// Sozusagen der Destroktor

}


}
```

Auf so eine SessionScoped ManagedBean kann man von jeder View aus zugreifen. Sie lebt die ganze Session über und lässt sich als Attribut aus der SessionMap refferenzieren. Man braucht sie aber nicht aus der SessionMap rausholen weil der Container innerhalb einer Session immer auf die selbe refferenz zugreift. Eine Session enthält eine Refferenz und somit auch nur ein Objekt dieser Bean. Für jeden User eine.




> genügt es praktisch, in der JSF-Seite z.B. über einen h:commandButton die Methode der entsprechenden Bean aufzurufen und der Container erkennt dann automatisch, dass es sich um dieselbe Bean wie beim ersten mal handelt?)



Genau das ist der Fall wenn man ManagedBeans verwendet. Daher sollte man nicht mit reinem EJB in JSF arbeiten.


Noch Fragen?

LG

David


----------



## Sym (4. Sep 2012)

Zu Plain JSF2 gehören natürlich ManagedBeans. Allerdings ist dies nur der erste Schritt Richtung CDI. Wer JSF 2 verwendet, sollte nicht @ManagedBean, sondern @Named verwenden. Dies ist auch kompatibel mit EJBs (und um entsprechende Annotationen erweiterbar).

Du kannst Deine EJBs auch einfach per @Inject in den CDI-Beans nutzen.


----------



## F.S.WhiTeY (4. Sep 2012)

> Allerdings ist dies nur der erste Schritt Richtung CDI.



Allerdings nur wenn du wirklich eine DI in eine reine EJB oder ein Servlet benötigst. Ansonsten hat JSF seine eigene DI, nämlich @ManagedProperty. Das bleibt dann bei "reinem" JSF und den ManagedBeans. 

Deine Aussage ist damit natürlich nicht falsch, allerdings kommt es halt immer auf den Anwendungsfall an. Ich brauchte das bisher nur sehr selten.


----------



## Sym (4. Sep 2012)

Die Bestrebungen gehen aber dahin, CDI für JSF2 zu nutzen. Und wenn ich das damals richtig verstanden habe, wurde das nur nicht getan, weil CDI noch nicht final war und deshalb eine eigene Lösung her musste. 

Immerhin gehört CDI zum EE-Stack und ist ohne Probleme mit JSF2 nutzbar.


----------



## F.S.WhiTeY (4. Sep 2012)

> Immerhin gehört CDI zum EE-Stack und ist ohne Probleme mit JSF2 nutzbar.



Das ist richtig, da kann ich nicht wiedersprechen. Allerdings nutzt man dann dennoch die @EJB-Annotation und bleibt bei ManagedBeans  

Was deine vorrangegangende Aussage dennoch nicht falsch macht. Die Annotationen @Named, @Inject und so weiter lassen sich natürlich problemlos in ManagedBeans nutzen. 

@ManagedProperty ist alledings kürzer und funktioniert bestens. Ich benutze es wo ich es kann


----------



## Sym (4. Sep 2012)

Wo benutze ich eine @EJB-Annotation? Das ist nirgends notwendig - nicht einmal in EJBs selbst. 

@ManagedProperty ist kürzer? Als @Inject? Oder verstehe ich Dich einfach nicht?

Der Vorteil bei CDI ist halt, das neuere Frameworks dies nutze und Du diese in Deine Managedbeans (als CDI-Bean) injecten kannst.

Das was ich dazu in Zeitschriften und im Netz lese geht auf jeden Fall in diese Richtung.


----------



## F.S.WhiTeY (4. Sep 2012)

Du benutzt eine @EJB-Annotation genau dann, wenn du eine ManagedBean verwendest und auf eine EJB zugriff benötigst.

Mann kann den DI auch abkürzen und das sieht dann so aus:


```
@ManagedBean(name="wasAuchImmerMB")
@ViewScoped
public class WasAuchImmerMB{

@EJB
private IrgendEineEJB eineEJB;

//und weiter im Text


}
```


----------



## Sym (4. Sep 2012)

Mit CDI würde das so aussehen:


```
@Named
@MyScoped
public class WasAuchImmerMB{
 
@Inject
private IrgendEineEJB eineEJB;
 
//und weiter im Text
 
}
```

Und dabei ist es eigentlich egal, ob das eine EJB oder nur eine CDI-Bean ist. Finde ich persönlich sprechender. Und mir ists auch egal, was ich da injecte.


----------



## F.S.WhiTeY (4. Sep 2012)

Ja das ist so, nur das mit @Named und mit @MyScoped keine ManagedBean mehr vorliegt  
Der Import ist ja auch javax.enterprise und nicht javax.faces. Da liegt der Unterschied. Das die Komponenten damit umgehen können ist richtig, aber wir reden dann nicht mehr von ManagedBeans sondern von JSF-Komponenten und EJBs.

Edit: Womit man dien FacesContext auch nicht mehr allzuleicht ansprechen kann und die faces-config wegfällt.


----------



## Sym (4. Sep 2012)

Hmm, ich würde gerne mal die Definition sehen, dass eine Managedbean nur eine Bean mit Annotationen aus javax.faces ist.

Nur weil die Annotation eben so heißt, ist das nicht die Definition dafür.

Siehe z.B. hier: What is MBean (managed bean)? - Definition from WhatIs.com

CDI-Beans werden durch Nutzung in JSF ebenfalls als managed Beans behandelt.

Und wir reden dann auch nicht von EJBs, denn diese haben per se erst einmal nichts mit CDI zu tun.


----------



## F.S.WhiTeY (4. Sep 2012)

Dann lies dir mal die JavaEE 6 Spec zu Managed Beans durch   JSR-316 ist das was für mich zählt. 



> MB.2.2.2Naming
> An extension specification may offer alternative ways to name a Managed Bean, e.g. as a side-effect of placing some other annotation on the bean class, but, if specified, the ManagedBean(”...”) annotation takes priority, and with it the rules in Section MB.2.1.2, “Naming”.
> Of course an extension specification may also introduce one or more additional namespaces in which some or all Managed Beans get registered, either with the Managed Bean name defined in Section MB.2.1.2, “Naming” or with an independently defined name.


----------



## Sym (4. Sep 2012)

Ich lese da jetzt nicht heraus, dass eine CDI-Bean keine Managed-Bean sein kann.


----------



## F.S.WhiTeY (4. Sep 2012)

Eine CDI Managed Bean ist zwar per Definition eine Managed Bean, bietet aber nicht den JSF support den man braucht. 

Das fängt schon damit an, das eine CDI-Bean ( übrigens eine EJB ) nicht mit ViewScoped umgehen kann. Was dann wiederum dazu führt das man den meisten AJAX-Support in die Tonne kloppen kann. Damit ist eine laut JSR 316 definierte Mannaged Bean keine CDI-Bean. Die werden auch Managed Bean genannt sind aber im J2EE Context etwas ganz anderes. Das eine ist eine EJB abwandlung und das Andere ist reines J2EE. Die Annotationen kommen ja zum größten Teil auch aus dem JSR 330 und der wurde uhrsprünglich mal für Java SE entwickelt. 
CDI ist was den Inject angeht weitaus mächtiger aber wenn ich mit JSF und eine View arbeite ist es ratsamer eine wirkliche JSF-ManagedBean zu verwenden. Das andere sind Handler-Objecte die irgendwo im Kontext rumfliegen.

Nochmal: der Facescontext und die Faces-config bestehen auf @ManagedBean. CDI braucht eine beans.xml und die Verwaltet der Server, nicht das Framework. 

CDI find ich ja nicht schlecht aber bitte da lassen wo es hingehört und das ist nicht hinter einer View als BackingBean sondern im Controller. Und JSF ist View, nicht Controller.


----------



## Sym (4. Sep 2012)

Plain CDI hat keinen ViewScope, das ist richtig. Allerdings ist dieser schnell selbst implementiert oder man nutzt ein entsprechendes Framework, welches diesen bietet. Damit ist es dann eine Managed-Bean.

ich weiß nicht, warum eine @ManagedBean-Annotation ratsamer sein sollte. Und natürlich werden CDIs vernünftig verwaltet. Mit JSF 2.2 wird sogar noch mehr auf CDI gesetzt. Dann lassen sich CDIs sogar in PhaseListener und Validatoren injecten - was aktuell selbst bei @ManagedBeans nicht der Fall ist, oder?

Eine CDI gehört genau da hin und kann und soll als Backing-Bean verwendet werden.

Die @ManagedBean Annotation war der erste Wurf, weil anfangs CDI noch nicht so weit war. Warten wir noch ein wenig, dann ist @ManagedBean deprecated.  

Nenne mir bitte ansonsten einen konkreten Vorteil, der nicht der ViewScope ist?

Ich kann einen für CDI nennen: Testbarkeit


----------



## F.S.WhiTeY (4. Sep 2012)

Seit wann sind JSF-ManagedBeans mit ManagedPropertys nicht testbar? Ich meine das JSF 2 nicht gerade das schönste zum testen sind ist mir schon klar aber sie sind testbar und das auch nicht wirklich schwer wenn man es richtig macht. Mal davon abgesehen das man auch für testbarkeit ein Framework verwenden kann genauso wie bei deinem ViewScope-Beispiel. JSFUnit z.B.

Außerdem läuft CDI meines wissen nach nicht auf Servletconatinern sondern nur auf Applicationservern.

Und zum PhaseListener:


```
ELContext elContext = FacesContext.getCurrentInstance().getELContext();

FacesContext.getCurrentInstance().getApplication()
    .getELResolver().getValue(elContext, null, "myBean");
```

Nicht so schön wie 
	
	
	
	





```
@Inject MyBean myBean;
```
 aber dennoch möglich, sauber und lauffähig.

Und wo willst du gelesen haben, das man laut der Spec von JSF 2.2 CDI nutzen SOLL und nicht einfach nur kann? Du magst es und willst es aber es ist so nicht vorgesehen.


----------



## Sym (4. Sep 2012)

Ja, natürlich kannst Du Dir die Komponente aus dem Komponentenbaum holen. Allerdings ist eine einfache Injection in einem Phaselistener oder Validator schon angenehmer, oder nicht? Als Sauber empfinde ich das in einer DI-Umgebung nicht. 

Arquillian ist z.B. eine schöne Möglichkeit, CDI-Beans zu testen. Und CDI bekommst Du auch z.B. auf einem Tomcat zum laufen, das ist nicht das Problem. 

Sorry, wenn ich mich missverständlich ausgedrückt habe: Ich meinte nicht, dass man mit JSF2.2 CDI verwenden soll, sondern dass dies die Zukunft ist. Mit JSF 2.2 werden nur einige Änderung vor allem im Bereich CDI vorgenommen.

Aber wenn Du @ManagedBean magst, dann nur zu. Ich wollte keine Grundsatzdiskussion starten, sondern nur mitteilen, was ich so mitnehme aus der Community um CDI und JSF herum.


----------



## F.S.WhiTeY (4. Sep 2012)

> Sorry, wenn ich mich missverständlich ausgedrückt habe: Ich meinte nicht, dass man mit JSF2.2 CDI verwenden soll, sondern dass dies die Zukunft ist. Mit JSF 2.2 werden nur einige Änderung vor allem im Bereich CDI vorgenommen.



Natürlich ist das die Zukunft ohne Frage! CDI ist ja auch eine wunderschöne Sache aber bei dem derzeitigen Stand kannst du doch dem TO nicht einfach sagen das er die CDI/EJB - Annotationen nutzen soll!

Der will JSF lernen und da gehört derzeit noch einiges an Geraffel und Wissen dazu CDI und JSF in Einklang zu bringen. Es ist halt nicht Sinn der Sache auf andere Frameworks zurückgreifen zu müssen damit alles läuft. Wenn man weiss was man tut, und das wissen wir beide, dann kann man das ja auch nutzen aber ein Newcommer sollte sich erstmal auf das eine beschränken.

Meine Absicht war es ja auch nicht CDI aus JSF zu verbannen aber wie gesagt: Das gehört nicht hinter die View wenn man alle Möglichkeiten haben will die JSF so bietet. Der FacesContext hat mit CDI nicht viel am Hut, jedenfalls noch nicht. 

Alles Andere in der dahinter liegenden Logik: OMG nimm CDI, was besseres gibt es da nicht. Auch wenn man in die Situation kommt ein eigenes Servlet schreiben zu müss: CDI warum nicht? 

Meine Intention war es lediglich die Abgenzung zwischen diesen beiden Technologien deutlich zu machen. JSF 2 und vor allem JSF 2.2 bieten einiges an neuen Techniken und Annotationen um CDI so nahe wie möglich zu kommen und es auch einfacher zu integrieren. Dazu gehören auch die @EJB und die @Ressource Annotationen. 
Das trifft halt auf die BackingBeans der Views zu, da gehören IMHO derzeit einfach keine CDI-Beans hin weil CDI nicht darauf ausgelegt ist JSF-Views in dem maße zu supporten. 

Vielleicht haben wir auch einfach eine unterschiedliche Meinung darüber wie das MVC-Pattern zu implementieren ist aber ich grenze halt JSF mit den @ManagedBean als View von meinen EJB und anderen POJO's im Controller ab.

Es ist zwar ein wenig mehr Aufwand aber was hält mich davon ab aus einer Bean die die View repräsentiert kurz mal etwas in eine CDIB oder EJB zu schupsen? Von dort aus kann ich doch mit CDI arbeiten und ich kann mir sicher sein dass alles auf die View bezogen läuft ohne Neuimplementierung oder zuzügliche Frameworks.  

Ich weiss nicht ob du verstehst worauf ich mit diesen Aussagen hinaus will. Vilt. drücke ich mich ja auch Missverständlich aus  

BTW: Arquillian ist auch eine schöne Möglichkeit um reine JSF-Anwendungen ohne CDI zu testen. Ich denke sogar eine der Besten derzeit.


----------



## Sym (4. Sep 2012)

Ich würde im Gegenteil jedem Anfänger raten, direkt CDI zu verwenden, weil der Aufwand dafür eine beans.xml ist. Man lernt es jedoch gleich "richtig", sofern man von richtig sprechen kann. 

Ich nutze CDI auch gerne als View und EJBs weiter hinten.

Ich wusste überhaupt nicht, dass Arquillian auch @ManagedBean abdeckt. Ich denke einfach mal, dass das nicht spezifisch so ist, sondern eine CDI ja alles sein kann und nicht direkt die javax.faces.* Annotation verwendet werden.


----------



## Raphalon (5. Sep 2012)

Was ich aus eurer Diskussion und auch nach einer weiteren Recherche im Web entnehme: Das Thema CDI Beans (hier: SFSB) scheint sehr komplex zu sein. Gerade in Bezug auf SFSB meinen manche Authoren, man könne eine SFSB direkt an eine JSF Managed Bean binden, andere meinen, das gehe nicht, weil dadurch Concurrency - Probleme entstehen können. Statt dessen müsse man die SFSB zunächst per JNDI Lookup auffinden und dann an die HttpSession binden. Siehe z.B. Link1, Link2, Link3, Link4.

Wie ich SFSB in Kombination mit dem Framework (hier JSF) "sicher" verwenden kann, scheint mir unklar. Bevor ich daher keine verlässliche Quellen zu diesem Thema (und seine Verwendung in JSF) finde, werde ich da wohl eher die Finger von lassen (SFSB). Ist es denn dann so, dass man in Verbindung mit JSF in einem AS wie z.B. Glassfish nur S*L*SB verwendet (z.B. für den Zugriff auf die DB)? Hat jd. eine Empfehlung auf ein Buch? Kann mir zudem jemand sagen, ob die Verwendung von SFSB in anderen Frameworks empfehlbar, bzw. einfach ist? Habe zwar schon zwei Bücher zu JSF durchgewälzt und auch schon programmiert, aber CDI von JSF-Beans abzugrenzen und korrekt anzuwenden empfinde ich als nicht einfach.

Nach dem Studieren des Buchs "Proj JPA2" ist mir auf jeden Fall an einer einfachen Testbarkeit gelegen meiner JEE - Beans gelegen. Arquillian mit Drone habe ich schon ausprobiert. Mir ist nicht klar, was da einfach dran sein soll.

Wenn ich also JSF verwende, dann sollte ich diesen "F.S.WhiTeY" zufolge als ManagedBean im SessionScope realisieren. Damit kann ich erst mal weiter leben.


----------



## Sym (5. Sep 2012)

Ja zum eigentlichen Thema: Den Warenkorb solltest Du nicht in einer EJB, sondern in einer Backingbean im SessionScope halten. Sorry, dass wir da abgewichen sind.


----------

