flowerp schreef op donderdag 07 augustus 2008 @ 22:48:
[...]
Dat mag je even uitleggen (als je wilt

) want dat snap ik niet helemaal. Ik neem aan dat je de MVC varianten push en pull bedoelt en niet de netwerk variant. Wat betreft het netwerk is elk gangbaar framework pull (request naar server, server stuurt response terug), tenzij je iets als comet gebruikt (server pushed naar client wanneer het daar aanleiding voor ziet). In het netwerk geval heeft het zeker gevolgen voor de back button, maar dat is onafhankelijk van JSF.
JSF is qua MVC pull, in de zin dat je in de view bindings naar managed beans definieert (liefst slechts 1 en dan spreken we in het algemeen over een backing bean). In zekere zin pulled je view dus data vanuit je bean(s) naar zich toe.
Vergeet echter niet dat je beans makkelijk geinitialiseerd kunnen worden -voordat- er zo'n pull plaats vind. Voor een conversation scope implementatie (die je vrij makkelijk zelf kunt maken, of kant en klaar kunt gebruiken van add-ons zoals Orchestra of Seam) vind er ook dikwijls een push plaats naar je backing bean voordat een UI component een pull uitvoert.
Een expliciete push van data vanuit je backing bean naar je UI components is inderdaad niet mogelijk, maar wat is het grote verschil? Ik kan in een backing bean na een post back eerst processing doen en dan forwarden naar een specifieke view. De components waaruit deze view bestaat komen de data dan bij mijn bean halen. Dat pattern wijkt IMHO amper af van wat je in een MVC push implementatie doet. Maar misschien weet jij iets wat ik niet weet. Hoe dan ook zie ik zeker niet waarom de back button hier een onderscheid in maakt.
[...]
True, ik doelde op de MVC variant. Wat ik hiermee bedoelde heeft niet direct met back button support te maken, maar kan wel voor problemen zorgen. Als één request scoped backing bean achter elk scherm hangt EN JSF 1.2 gebruikt zodat je @PostConstruct kunt gebruiken, kun je het goed afvangen.
Ik kom in mijn klantenkring echter nog maar weinig JSF 1.2 enabled servers tegen. En zonder JSF 1.2 kom je bij zelfbouw of third party plugins. Voor beiden heb je al relatief veel JSF kennis nodig om ze foutloos in ze zetten.
[...]
Waarom denk je dat die er niet in zitten?
[...]
Al met al meer dan genoeg mogelijkheden lijkt me toch?
[...]
En het zijn er nog veel meer. Denk aan Variable-/Property-/ELResolver, NavigationHandler, etc...
Heb je ook al de publish/subscribe system events gezien die in JSF 2.0 komen? In de huidige staat nog absoluut niet bruikbaar, maar al wel vrij elegant qua API.
Maar wat ik bedoel, is dat je wederom vrij veel kennis van het framework moet hebben om iets fatsoenlijks neer te zetten. Bij Spring hoef je toch ook geen custom factories te schrijven als je iets productie waardigs wilt bouwen? Of entitylisteners bij JPA? Dat zijn constructies die je nodig hebt als je iets afwijkends wilt. Bij JSF moet je vrij snel terugvallen op constructies die je op zijn minst 'lastig' mag noemen. Je kunt (of je projectleden kunnen) er zonder veel moeite hele irritante bugs mee introduceren.
[...]
Waarom impliceert een postback het gebruik van session scoped data?
[...]
Ik bedoelde geen state management, maar dat je gewoon relatief vaak terug moet vallen op sessiedata als je een beetje performende applicatie wilt bouwen.
Zie opmerking over datatable verderop.
[...]
Eigenlijk heb ik die nadelen nog helemaal niet gehoord. Dat jij denkt dat het een nadeel is, maakt het nog niet automatisch tot een nadeel

Lees eens terug wat ik hierboven schreef. ASP.NET gebruikt -exact- dezelfde filosofie en dit zie ik behoorlijk vaak eigenlijk. Tapestry en de 2de opvolger van Struts zijn overigens ook component based.
[...]
Ik ga niet met je in discussie over ASP.NET, want daar heb ik geen praktijkervaring mee. Wat ik wel hoor van mensen die ermee werken, is dat het al vrij ver doorontwikkeld is. En dat kun je van JSF niet zeggen.
Om een beetje lekker met JSF te kunnen werken, heb je toch minimaal Facelets nodig. Voor AJAX iets van Ajax4jsf of meteen de complete RichFaces set. Met pageflows (en die komen vaak voor) heb je Seam of Spring Web Flow nodig. Nadeel is alleen dat veel van dergelijke libraries niet goed integreren. Bij de bovenstaande gaat het toevallig goed, maar dan hoef je niet te verwachten dat Apache Trinidad zonder problemen werkt.
Vooral op het gebied van AJAX, renderkits, e.d. zitten ze elkaar nog weleens in de weg.
Tel daarbij op dat Facelets niet echt 'IDE friendly' is en de support dus nog te wensen overlaat.
Vandaar dat ik denk dat JSF er nog lang niet is.
Over Tapestry en Struts 2 (en Wicket), die zijn niet puur component based (alsus Ed Burns), aangezien ze features bieden zoals URL mounting en daardoor meer op MVC frameworks zoals Struts 1 of Spring MVC lijken dan JSF.
[...]
Dat heet dus een backing bean en dat is in nagenoeg alle gevallen sowieso al de standaard best practice. 1 page met daarachter 1 backing bean in request scope. JSF enforced die methode echter niet, maar laat de programmeur vrij om het ook anders te doen. Dat kan misbruik in de hand werken, ik ben de eerste die dat toe zal geven. Het lukraak binden van diverse UI components aan diverse session scoped beans (of nog erger, application scoped beans) is in de regel een beginners fout en kan vrij onvoorspelbaar gedrag veroorzaken.
In zekere zin is het jammer dat JSF dit toe staat. Alleen iemand die -echt- weet wat ie doet zou het heel af en toe wel eens nuttig kunnen inzetten. Ik denk dat de JSF designers er voor gekozen hebben om mensen vrij te laten in hun aanpak. Volgens mij staat er in het boek van Ed Burns ook ongeveer zoiets over.
[...]
LOL, ik zit mijn posts terug te lezen en ik zie dat ik al tig keer page bean gezegd heb.
Zal wel al te lang bij dezelfde klant zitten...
Ik zeg zelf doorgaans liever Request Scoped Managed Bean of Session Scoped Managed Bean, omdat mensen anders in de war raken met Spring beans, EJB, JavaBeans spec, Mr Bean, etc...
Maar ik ben het wel met je eens. Gewoon 1 backing bean per pagina. Je kunt eventueel afwijken als je met Facelets (of JSP tag files) werkt en van een pagina een component wilt maken, maar zelfs dan is het meestal niet echt nuttig.
[...]
Het mooie is dat JSF dit allemaal toe staat. Veel mensen denken dat JSF de custom tags zijn die je op een JSP page neer zet. Net zoals veel mensen denken dat Eclipse een Java IDE is (Eclipse zelf is niet alleen geen Java IDE (JDT is een plugin), maar zelfs nog niet eens een IDE). Zo is het ook met JSF. Je kunt diverse onderdelen vrij krachtig gebruiken zonder andere dingen die mensen soms als volledig geïntegreerd met JSF zien te gebruiken.
[...]
Over Eclipse en JSF, dat begrijp ik gelukkig, maar ik ben het er niet mee eens dat het mooi is, omdat ik het vaak fout zie gaan.
[...]
Dat is niet altijd een best practice en hangt ervan af wat je aan het doen bent. Zit je in een sequence van dialogen (een conversatie) waar het dikwijls volledig onzinnig is om naar een pagina midden in zo'n sequence te linken, dan voldoet de commandlink uitstekend. Je conversatie state wordt mooi meegenomen van page naar page zonder dat je expliciet de session scope hoeft te gebruiken. Ga je echter naar een compleet nieuwe view (page) dan zijn normale links te prefereren.
[...]
Ik had het ook over normale navigatie. Ik weet het, het woord normaal is voor interpretatie vatbaar, maar ik doelde op pure navigatie, zonder dat de server moet ingrijpen, dus niet zoals in een wizard.
[...]
2x laden probleem?
[...]
Bekend probleem. Al veel besproken op o.a. de MyFaces, Facelets en JSF RI fora/mailinglists.
Het komt er op neer, je hebt een JSF pagina met een datatable (of ui:repeat, etc).
XML:
1
2
3
| <h:dataTable var="person" value="#{requestScopedBean.people}">
...
</h:dataTable> |
Daarachter heb je een request scoped managed bean met daarin de lijst die getoond moet worden. Voor het gemak ga ik ervan uit dat die uit een database query komt.
Het maakt geen verschil of de data access logica in de constructor/postconstruct of getter staat. Dus zoiets:
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
| class RequestScopedBean {
private DataModel people;
public RequestScopedBean() {
this.people = new listDataModel(/* get list from database */);
}
// standaard getter
}
OF:
class RequestScopedBean {
private DataModel people;
// Default constructor
public DataModel getPeople() {
if (this.people == null) {
this.people = new listDataModel(/* get list from database */);
}
return this.people;
}
} |
XML:
1
2
3
4
5
| <managed-bean>
<managed-bean-name>peopleBean</managed-bean-name>
<managed-bean-class>nl...PeopleBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean> |
Je hebt vast weleens dergelijke code gezien.
Nu wil je in die lijst een knop om een bepaald record te openen. Master/detail dus.
Iedere tutorial, boek, etc. zegt dat je dat met een UICommand component moet doen, dus een h:commandLink/Button.
Stel dat je dat advies volgt, dan krijg je iets dergelijks:
XML:
1
2
3
4
5
| <h:dataTable var="person" value="#{requestScopedBean.people}">
<h:column>
<h:commandButton action="#{requestScopedBean.details}" value="Details" />
</h:column>
</h:dataTable> |
En een action method in je backing bean.
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
| class RequestScopedBean {
private DataModel people;
private Person person;
public RequestScopedBean() {
this.people = new listDataModel(/* get list from database */);
}
public String details() {
this.person = this.people.getRowData();
return "personDetails";
}
// standaard getter
}
OF:
class RequestScopedBean {
private DataModel people;
// Default constructor
public DataModel getPeople() {
if (this.people == null) {
this.people = new listDataModel(/* get list from database */);
}
return this.people;
}
public String details() {
this.person = this.people.getRowData();
return "personDetails";
}
} |
Als je deze code draait (na de typo's eruit gehaald te hebben) zul je zien dat bij het submitten de ValueExpression achter de UIData opnieuw uitgevoerd wordt, nog voordat het ActionEvent afgehandeld wordt. Om precies te zijn, tijdens het decoden in de Apply Request Values phase.
Het moge duidelijk zijn dat dit een onnodige performance penalty geeft. Zeker als je met een ORM werkt, die hele objectbomen gaat aanmaken, terwijl dat in dit geval niet nodig is.
Je kunt vanalles gaan hacken in de lifecycle, maar dit effect voorkom je niet zolang je met request scoped beans werkt. Op de Facelets mailinglist werd op een gegeven moment zelfs geopperd om het dan maar in de 2nd level cache van Hibernate op te lossen.
Je kunt je datamodels ook in de session scope stoppen, maar dat is bij grote overzichten ook geen optie.
Heel verhaal, maar dat komt dus doordat JSF postbacks sterk promoot. Als je gewoon een GET naar het detailscherm doet, met daarin een parameter, kun je daar een query voor één resultaat doen.
Nadeel is dat je zelf een link met parameters moet klussen. En je moet ze in de volgende pagina weer uitlezen. En dat is niet echt "des JSF's", want op o.a. dit gebied claimt JSF een abstractieniveau boven MVC frameworks te zitten. Als je dan zelf constructies gaat maken om weer low level te gaan werken, waarom kies je dan voor JSF?
Dat is eigenlijk het hele punt dat ik wil maken. Als je request parameters wilt uitlezen, kun je beter voor Struts of Spring MVC kiezen. Die zijn er specifiek voor gemaakt. En tegenwoordig kun je dat zelfs component based doen, met Spring Faces.
[...]
In mijn JSF applicaties (ondertussen al diversen) ben ik eigenlijk nooit events kwijtgeraakt. Ik gebruik alleen maar request scoped beans als backing beans. Welke events bedoel je? Wanneer gebeurt dit?
[...]
Laat maar, oude bug. Ik heb er zelf ook nooit last van gehad. Het had ermee te maken dat per request steeds andere ID's gegenereerd werden waardoor een ID niet terug gemapped kon worden naar een component, met als gevolg dat je actionlistenet niet uitgevoerd werd.
[...]
Absoluut. Zal ik zeker niet ontkennen. JSF heeft eerst de basis geïmplementeerd en is daar zoals gezegd rijkelijk laat mee. De ellenlange 'preview' periode (voordat het officieel in Java EE 5 kwam) lijkt meer kwaad te hebben gedaan dan goed. Voornamelijk de nice-to-haves en de fancy features moeten nog komen. Het concept, het fundamentele idee is echter IMHO wel degelijk ok en dat gaat ook zeker in JSF 2.0 niet radicaal veranderen.
JSF gaat vooral een aantal features toevoegen die noodzakelijk zijn om lekker te kunnen werken. Bijvoorbeeld een view scope (process/conversational/pageflow komt er niet in, maar in WebBeans. Ben daar niet echt blij mee), maar ook publish subscribe events bieden leuke mogelijkheden.
Heel lang verhaal, en volgens mij zijn we al erg ver afgedwaald.

Ik moet er eerlijk bij zeggen dat ik pas een paar JSF 1.2 klussen heb gedaan en dus nog niet echt de best practices van JSF 1.2 features ken. Maar ik heb niet de indruk dat de veranderingen zo groot zijn dat dat mijn punt niet meer klopt.
Gaat JSF 2.0 alles gaat oplossen? Ik verwacht het eerlijk gezegd niet. Ik denk dat ze erg achter de feiten aan lopen. Ik ben bang dat ze de EG te groot hebben gemaakt en dat daardoor alles vertraagt.
Verwijderd schreef op vrijdag 08 augustus 2008 @ 09:49:
[...]
Dat is nou al de zoveelste keer dat je dat claimed zonder enige onderbouwing. Timing is compleet irrelevant aangezien de grotere frameworks gekomen en weer 'verdwenen' zijn: Kijk maar naar Struts. De reden dat JSF het gat niet te vult is gewoon doodsimpel: Het voegt projectmatig helemaal niets toe, want:
- Ontwikkeling gaat niet sneller ten opzichte van basic JSP's
- Request flow wordt nodeloos complex
- Je introduceert een leercurve
Ontwikkelsnelheid:
Met JSF kun je prima snel ontwikkelen. Het is aan te raden om een ervaren JSF-er op het project te hebben. Maar geldt dat niet voor alles?
Bovendien, hoewel het voordeel van JSF bij een CRUD applicatie misschien beperkt is, als je applicatie groter en complexer wordt, zul je snel genoeg de voordelen zien. Zeker als je een mooie component library kunt gebruiken. Of maak jij je JavaScript kalendertjes en picklists zelf?
Verder sluit ik me bij flowerp aan v.w.b. dit punt. Ik heb genoeg JSP-spaghetti nachtmerries gehad.
Complexe request flow:
Je moet een tot in detail gespecificeerde flow niet verwarren met een complexe flow. JSF doet in essentie hetzelfde als ieder ander framework, maar het verschil is dat alle ervaren JSF developers op die lifecycle met zijn subtiliteiten zitten te hameren, zodat mensen die net beginnen, vrijwel meteen afhaken. Als je op je eerste Struts dag meteen de interne werking te horen krijgt, gaan je oren ook flapperen.
Leercurve:
Dusss, jij denkt dat een zelfbouw JSP/Servlet oplossing gemakkelijker te leren is dan JSF? Tenzij het niet meer is dan een simpele tag library, lijkt het me sterk. Al is het maar dat er voor JSF ontzettend veel bronnen te vinden zijn.
Ten slotte vind ik het wel leuk dat je het woord "projectmatig" noemt, aangezien JSF zover ik weet het enige web framework is waar ze expliciet rekening houden met teamsamenstelling en rollen.