Your SlideShare is downloading. ×
  • Like
JSF 2: Best Practices und Hidden Features
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

JSF 2: Best Practices und Hidden Features

  • 6,431 views
Published

Speaker: Lars Röwekamp …

Speaker: Lars Röwekamp
W-JAX 2012

Eine Webanwendung auf Basis von JSF 2 zu bauen ist nicht immer nur lustig. Ein ungewohntes Programmiermodell, scheinbare Spezifikationslücken und eine Menge Ungereimtheiten. Wer soll da noch durchsteigen? Die Session zeigt anhand eines praktischen Beispiels essenzielle Best Practices und Hidden Features von JSF. Zusätzlich werden einige wirklich nützliche JSF Libraries und Frameworks vorgestellt.

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
6,431
On SlideShare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
68
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Hidden FeaturesBest Practices JSF 2 Lars Röwekamp | open knowledge GmbH | @mobileLarson
  • 2. Don‘task me, RTFS!
  • 3. „Come on,that‘s wayto much.“* *JSF 2 Spec: > 500P
  • 4. AjaxBookmarking BehaviorComponents Validation Stuff
  • 5. Ajax
  • 6. It‘s sooo easy!
  • 7. Ajax 1.) „Was soll ausgeführt werden?“2.) „Was soll gerendert werden?“
  • 8. Ajax> Asynchrones Request/Response Handling> Partitial Execute/Rendering via Lifecycle> JSF Component Tree> Ajax Request Status Handling> Ajax Request Error Handling> Easy to use: f:ajax-Tag> Total control: jsf.ajax.request( )
  • 9. Ajax<!-- Das AJAX TAG --><h:form ...> <h:commandButton value=“Update“> <f:ajax execute=“@form“ render=“updateMe“ /> </h:commandButton> <h:outputTextField value=“#{aBeansValue}“ id=“updateMe“ /></h:form>
  • 10. Ajax<f:ajax execute = „wen ausführen?“ render = „wen updaten?“ event = „auf was reagieren?“ listener = „wen interessiert‘s noch?“ onevent = „zusätzliche JavaScript Callback-Funktion“ onerror = „zusätzliche JavaScript Callback-Fehler-Funktion“/>
  • 11. Ajax<!-- Das AJAX TAG (Master / Detail) --><h:selectOneMenu id="master" value="#{demo.master}"> <f:selectItems value="#{demo.masterItems}"/> <f:ajax render="detail" listener="#{demo.masterChanged}"/></h:selectOneMenu><h:selectOneMenu id="detail" value="#{demo.detail}"> <f:selectItems value="#{demo.detailItems}"/></h:selectOneMenu>
  • 12. Ajax<f:ajax execute = „wen ausführen?“ render = „wen updaten?“ event = „auf was reagieren?“ listener = „wen interessiert‘s?“ onevent = „zusätzliche JavaScript Callback-Funktion“ onerror = „zusätzliche JavaScript Callback-Fehler-Funktion“/>
  • 13. Ajax<f:ajax execute = @this render = @none event = action (Button/Link) valueChange (sonst) listener = @none onevent = status: begin, complete, success source: triggering DOM event responseCode, responseText/XML/>
  • 14. Ajax<!-- Die JavaScript API (Master/Detail) --><h:selectOneMenu id="master" value="#{demo.master}" valueChangeListener="#{demo.masterChanged}" onChange="jsf.ajax.request( this, event, {render: detail});"/><h:selectOneMenu id="detail" value="#{demo.detail}"> <f:selectItems value="#{demo.detailItems}"/></h:selectOneMenu>
  • 15. Ajax <!-- Die JavaScript API (Master/Detail) --> <h:selectOneMenu id="master"Source Event value="#{demo.master}" Option(s) valueChangeListener="#{demo.masterChanged}" onChange="jsf.ajax.request( this, event, {render: detail});" /> <h:selectOneMenu id="detail" value="#{demo.detail}"> <f:selectItems value="#{demo.detailItems}"/> </h:selectOneMenu>
  • 16. AjaxPitfalls> inner/outer Component IDs> Ajax in Custom Components> Ajax Status Feedback
  • 17. „Want some cool stuff?“
  • 18. Ajax <!-- axaj response manipulation via PartitialResponseWriter (PrimeFaces style) --> <partial-response> <changes> <update id="abc">...</update> <update id="xyz“>...</update> <extension ln="primefaces" type="args"> {"loggedIn":false} </extension> </changes> </partial-response>http://www.primefaces.org/showcase/ui/dialogLogin.jsf
  • 19. Ajax<!-- axaj response handling inside JSF view (PrimeFaces style)--><script type="text/javascript">    function handleLoginRequest(xhr, status, args) {      if(args.validationFailed || !args.loggedIn) {        jQuery(#dialog) .effect("shake", { times:3 }, 100);      } else {        dlg.hide();        jQuery(#loginLink).fadeOut();      }    }  </script>  
  • 20. Ajax// PartitialResponseWriter (PrimeFaces style)@Overridepublic void endDocument() throws IOException {  Map<String, String> attributes = new HashMap<String, String>();  attributes.put("ln", "primefaces");  attributes.put("type", "args");  startExtension(attributes);  write("{"loggedIn":false}");  endExtension();  super.endDocument();}
  • 21. Behavior
  • 22. Behavior> Idee: Komponente um clientseitige Funktionalität erweitern, die vom Autor ursprünglich nicht vorgesehen war.> Mittel: JSF Behavior API zur Erweiterung beliebiger Komponenten um Client-side Scripting
  • 23. Behavior<!-- Behavior in Action --> Standard Behavior<h:form ...> <h:commandButton value=“Update“> <f:ajax execute=“@form“ render=“updateMe“ /> </h:commandButton> <h:outputTextField value=“#{aValue}“ id=“updateMe“ /></h:form>
  • 24. Behavior> Client-side Validation> Client-side Logging> DOM & Style Manipulation> Animationen & visuelle Effekte> Alerts & Confirmation Dialoge> Lazy Data Fetching> Integration mit 3rd Party Libraries> ...
  • 25. BehaviorMain Player> ClientBehavior a.k.a. Script Generator: zuständig für Generierung von passendem Skript> ClientBehaviorHolder a.k.a. Vermittler: zuständig für das Wiring zwischen Komponente, Event und ClientBehavior
  • 26. Behavior<!-- BEHAVIOR in action --> „My“ Behavior// chain of behaviors<h:commandButton value=“Update“> // 1. ask user for permission <mystuff:confirm event=“click“ /> // 2. if YES send AJAX call <f:ajax event=“click“ render=“updateMe“ /></h:commandButton> Standard Behavior
  • 27. Behavior „My“ Behaviorpackage de.openknowledge.example.behavior;@FacesBehavior(xyz.behavior.Confirm)public class ConfirmBehavior extends ClientBehaviorBase { @Override public String getScript( ClientBehaviorContext behaviorContext) { return “return confirm(‘Are your sure?‘)“; }}
  • 28. Behavior Facelets TagLib<?xml version=1.0 encoding=UTF-8?><facelet-taglib xmlns="..." version="2.0"> <namespace>http://xyz.de/mystuff</namespace> <tag> <tag-name>confirm</tag-name> <behavior> <behavior-id> xyz.behavior.Confirm </behavior-id> </behavior> </tag></facelet-taglib> in WEB-INF o. META-INF
  • 29. Server-side Action?
  • 30. Behavior<!-- BEHAVIOR with server-side action -->// input field with behavior<h:inputText value=“#{someValue}“> // inject jsf.ajax.request/show suggestions <foo:suggest suggestions=“#{serverSuggestions}“ /></h:inputText> Server-side Action
  • 31. Behavior// BEHAVIOR with server-side action// participate in request decodingpublic void decode(FacesContext context, UIComponent uiComponent) { // create suggestion list via // behavior directly or via service or ... ...} Server-side Action
  • 32. Component
  • 33. It‘s so easy, again!
  • 34. Components <html xmlns=“http://www.w3.org/1999/xhtml“ xmlns:composite=“.../jsf/composite“ > <!--INTERFACE --> Comp Interface <composite:interface> ... </composite:interface> Comp Implementation <!--IMPLEMENTATION --> <composite:implementation> ... </composite:implementation> </html>Komponente liegt unter: ./resources/comp/util/myComp.xhtml
  • 35. Components <html xmlns=“http://www.w3.org/1999/xhtml“ ... xmnls:util= “http://java.sun.com/jsf/composite/ comp/util“ > ... <util:myComp ... /> ... Comp in Action </html>Komponente liegt unter: ./resources/comp/util/myComp.xhtml
  • 36. Components> XHTML plus> Interface & Implementation> Convention over Configuration> Convention over Code> Pitfall „couldn‘t find ID“> Pitfall „couldn‘t find ACTION“> Pitfall „couldn‘t add VALIDATOR “> Pitfall „couldn‘t add CHILDS“> Pitfall „couldn‘t add I18N“
  • 37. Components> XHTML plus> Interface & Implementation> Convention over Configuration> Convention over Code> Pitfall „couldn‘t find ID“> Pitfall „couldn‘t find ACTION“> Pitfall „couldn‘t add VALIDATOR “> Pitfall „couldn‘t add CHILDS“> Pitfall „couldn‘t add I18N“
  • 38. Components
  • 39. Components
  • 40. Components<html xmlns= ... > <!--INTERFACE --> <composite:interface> <composite:attribute name=“user“ /> <composite:attribute name=“userLabel“ /> <composite:attribute name=“pwdLabel“ /> <composite:attribute name=“loginBtnLabel“/> <composite:attribute name=“action“ method-signature=“java.lang.String action()“/> </composite:interface> ...</html>
  • 41. Components<html xmlns= ... > <!--INTERFACE --> <composite:interface> <composite:attribute name=“user“ /> <composite:attribute name=“userLabel“ /> <composite:attribute name=“pwdLabel“ /> <composite:attribute name=“loginBtnLabel“/> <composite:attribute name=“action“ method-signature=“java.lang.String action()“/> </composite:interface> ... Reserved Qualifier!</html>
  • 42. Components<html xmlns= ... > <!--INTERFACE --> <composite:interface> <composite:attribute name=“user“ /> <composite:attribute name=“userLabel“ /> <composite:attribute name=“pwdLabel“ /> <composite:attribute name=“loginBtnLabel“/> <composite:attribute name=“loginAction“ method-signature=“java.lang.String action()“/> </composite:interface> ...</html>
  • 43. Components<html xmlns= ... > ... <!--IMPLEMENTATION --> <composite:implementation> <h:form id=“form“> <h:panelGrid columns=“2“> #{cc.attrs.namePrompt} <h:inputText id=“name“ value=“#{cc.attrs.user.name}“/> ... </h:panelGrid> <h:commandButton id=“loginBtn“ value=“#{cc.attrs.loginBtnLabel}“ action=“#{cc.attrs.loginAction}“ /> </h:form> <p>Die Super-Login-Komponente von open knowledge</p> </composite:implementation/></html>
  • 44. Components<html xmlns= ... > ... <!--IMPLEMENTATION --> Dependency to User <composite:implementation> <h:form id=“form“> <h:panelGrid columns=“2“> #{cc.attrs.namePrompt} <h:inputText id=“name“ value=“#{cc.attrs.user.name}“/> ... </h:panelGrid> <h:commandButton id=“loginBtn“ value=“#{cc.attrs.loginBtnLabel}“ action=“#{cc.attrs.loginAction}“ /> </h:form> <p>Die Super-Login-Komponente von open knowledge</p> </composite:implementation/></html>
  • 45. Components<html xmlns= ... > ... <!--IMPLEMENTATION --> Dependency to User <composite:implementation> <h:form id=“form“> <h:panelGrid columns=“2“> #{cc.attrs.namePrompt} <h:inputText id=“name“ value=“#{cc.attrs.user.name}“/> ... </h:panelGrid> <h:commandButton id=“loginBtn“ value=“#{cc.attrs.loginBtnLabel}“ action=“#{cc.attrs.loginAction}“ /> </h:form> <p>Die Super-Login-Komponente von open knowledge</p> </composite:implementation/></html> I18N
  • 46. Components<html xmlns= ... > ... <!--IMPLEMENTATION --> Dependency to User <composite:implementation> <h:form id=“form“> <h:panelGrid columns=“2“> #{cc.attrs.namePrompt} <h:inputText id=“name“ value=“#{cc.attrs.user.name}“/> ... </h:panelGrid> id=“form:name“ <h:commandButton id=“loginBtn“ value=“#{cc.attrs.loginBtnLabel}“ action=“#{cc.attrs.loginAction}“ /> </h:form> <p>Die Super-Login-Komponente von open knowledge</p> </composite:implementation/></html> I18N
  • 47. ComponentsChild Tags, Facets,...?<html xmlns= ... > ... <!--IMPLEMENTATION --> Dependency to User <composite:implementation> <h:form id=“form“> <h:panelGrid columns=“2“> #{cc.attrs.namePrompt} <h:inputText id=“name“ value=“#{cc.attrs.user.name}“/> ... </h:panelGrid> id=“form:name“ <h:commandButton id=“loginBtn“ value=“#{cc.attrs.loginBtnLabel}“ action=“#{cc.attrs.loginAction}“ /> </h:form> <p>Die Super-Login-Komponente von open knowledge</p> </composite:implementation/></html> I18N
  • 48. Components<html xmlns= ... > Dependency to User <!--INTERFACE --> <composite:interface> <composite:attribute name=“user“ /> <composite:attribute name=“userName“ /> <composite:attribute name=“userPwd“ /> ... </composite:interface> ...</html>
  • 49. Components<html xmlns= ... > ... <!--IMPLEMENTATION --> I18N <composite:implementation> <h:form id=“form“> ... </h:form> <p>Die Super-Login-Komponente von open knowledge</p> <p>#{cc.resourceBundleMap.myFooterText}</p> </composite:implementation/></html>
  • 50. Components<html xmlns= ... > ... <!--IMPLEMENTATION --> I18N <composite:implementation> <h:form id=“form“> ... </h:form> <p>Die Super-Login-Komponente von open knowledge</p> <p>#{cc.resourceBundleMap.myFooterText}</p> </composite:implementation/></html>
  • 51. Components<html xmlns= ... > <!--INTERFACE --> Expose Components <composite:interface> <composite:attribute name=“userName“ /> <composite:attribute name=“userPwd“ /> <composite:editableValueHolder name=“userName“ targets=“form:name“/> <composite:editableValueHolder name=“userPwd“ targets=“form:pwd“/> <composite:editableValueHolder name=“allFields“ targets=“form:name form:pwd“/> <composite:actionSource name=“loginButton“ targets=“form:loginBtn“/> ... </composite:interface> ...</html>
  • 52. Components<html xmlns= ... > ... Facets <!--IMPLEMENTATION --> <composite:implementation> <composite:renderFacet name=“header“ /> <h:form id=“form“> ... </h:form> <composite:insertChildren/> </composite:implementation/></html> Child Tags
  • 53. Bookmark
  • 54. BookmarksJSF erlaubt „Bookmarking“, aber ...> URLs scheinen hinterher zu hängen> URLs sind unschön> URLs implizieren i.d.R. einen State
  • 55. Bookmarks
  • 56. Bookmarks
  • 57. Bookmarks
  • 58. BookmarksJSF 1.x „Bookmarking“> <h:outputLink> für GET> PhaseListener zur Manipulation> redirect um aus Post ein Get zu machen
  • 59. BookmarksJSF 1.x „Bookmarking“> <h:outputLink> für GET> PhaseListener zur Manipulation> redirect um aus Post ein Get zu machen
  • 60. BookmarksJSF 2.x „Bookmarking“> <h:link> oder <h:button> für GET> <f:viewParam> zum Setzen von Params> <f:event type=“preRenderView“ zum Laden von benötigten Daten
  • 61. Bookmarks userList.xhtml<!-- ! Bookmarkable link for user, e.g.: ! <a href=“/context/user.xhtml?id=1234“>..</a>!-->!<h:link value=“Details von #{user.name}“! outcome="user">! <f:param name="id" value="#{user.id}" />!</h:link>! Step 1: Create URL
  • 62. Bookmarks user.xhtml<!-- ! Use bookmarkable link for user, e.g.: ! <a href=“/context/user.xhtml?id=1234“>..</a>!-->!<f:metadata>! Step 2: Use URL <f:viewParam name="id" ! value="#{userManager.userId}" />! <f:event type="preRenderView" ! listener="#{userManager.loadUser}" />!</f:metadata>!<h:head>...</h:head>!<h:body>! ... <!-- display user details -->!</h:body>!
  • 63. Bookmarks user.xhtml<!-- ! Use bookmarkable link for user, e.g.: ! <a href=“/context/user.xhtml?id=1234“>..</a>!-->!<f:metadata>! Step 2: Use URL <f:viewParam name="id" ! value="#{userManager.userId}" />! <f:viewAction action="#{userManager.loadUser}" />!!</f:metadata>!<h:head>...</h:head>! ab JSF 2.2!<h:body>! ... <!-- display user details -->!</h:body>!
  • 64. Geht da noch mehr?
  • 65. BookmarksJSF 2.x URIs> Ugly www.demo.de/faces/showCust?id=54> Nice www.demo.de/customer/meier/hans
  • 66. BookmarksJSF 2.x URIs> WTH? www.demo.de/list?type=cust&f=a&t=d> Ahh, alles klar www.demo.de/customerlist/from/a/to/d
  • 67. JSF meetsPrettyFaces
  • 68. BookmarksPretty Faces - URL Rewriting> localhost:8080/faces/start.xhtml> localhost:8080/start<url-mapping id="start“> <pattern value="/start" /> <view-id>/faces/start.xhtml</view-id></url-mapping>
  • 69. BookmarksPretty Faces - URL Rewriting> .../faces/cust/d.xhtml?c=mobileLarson> .../customer/mobileLarson<url-mapping id=“customerDetails“> <pattern value=“/customer/ #{name : custBean.username}" /> <view-id>/faces/cust/d.xhtml</view-id></url-mapping>
  • 70. BookmarksPretty Faces - URL Rewriting> .../customer/mobileLarson<url-mapping id=“customerDetails“> <pattern> ... </pattern> <view-id> ... </view-id> <action>#{custBean.loadCust}</action></url-mapping>
  • 71. Validation
  • 72. Ready to use!
  • 73. Validation> Component Validation - check> Cross-Layer Validierung - kind of check> Cross-Component Validation - what?
  • 74. Validation> Component Validation - check> Cross-Layer Validierung - kind of check> Cross-Component Validation - what?
  • 75. ValidationCross-Component Validation> Validierung über mehrere Komponenten> username != password> password == password repeat> password Validation wie in Klasse XYZ
  • 76. ValidationCross-Component Validation> Alternative A: externe Validation Lib, z.B. Apache MyFaces ExtVal> Alternative B: Self-Made Validator inkl. Zugriff auf Komponente(n)> Alternative C: JSF System Events, d.h. pre/postValidate Callbacks
  • 77. Stuff
  • 78. Stuff<!-- classic “debugging“ via ui:remove --><html><h:head /><h:body><h:form>   Text to display.   <ui:remove>Text to remove</ui:remove>   Text to display.</h:form></body></html>
  • 79. Stuff<!-- classic “debugging“ via ui:debug --><html ... ><h:head> ... </h:head><body> ... <ui:debug hotkey="0" rendered= "#{initParam[javax.faces.PROJECT_STAGE] eq Development}" /></body></html>
  • 80. Stuff<!-- classic “debugging“ via ui:debug --><html ... ><h:head> ... </h:head><body> ... <ui:debug hotkey="0" rendered= "#{initParam[javax.faces.PROJECT_STAGE] eq Development}" /></body></html>
  • 81. Hidden FeaturesBest Practices Thank you Lars Röwekamp | CIO New Technologies | @mobileLarson