Component Framework Primer for JSF Users
Upcoming SlideShare
Loading in...5
×
 

Component Framework Primer for JSF Users

on

  • 5,689 views

JSF Summit 2009 presentation covering three component-centric web frameworks: JSF, Wicket and Tapestry.

JSF Summit 2009 presentation covering three component-centric web frameworks: JSF, Wicket and Tapestry.

Statistics

Views

Total Views
5,689
Views on SlideShare
5,667
Embed Views
22

Actions

Likes
2
Downloads
164
Comments
1

2 Embeds 22

http://www.slideshare.net 21
http://webcache.googleusercontent.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • good
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Component Framework Primer for JSF Users Component Framework Primer for JSF Users Presentation Transcript

  • Component Framework Primer for JSF Users Andy Schwartz | Oracle Corporation
  • What?
    • What are we doing?
      • Comparing server-side component-centric frameworks
      • Understanding approaches to common problems
    • What is a server-side component-centric framework?
      • User interface component model defined on server
      • Components hold properties, children, fire events
      • Swing-like approach for web content
    • What frameworks?
      • JSF, Wicket and Tapestry
    • What else is there?
      • Client-side (jQuery, Dojo)
      • Hybrid (GWT)
      • MVC (Struts, RoR)
  • Why?
    • JSF has historically been a target of criticism
    • Often compared to related frameworks
    • Important to understand JSF’s limitations
    • JSF 2 addresses many of these issues
    • Still room for improvement
    • We can learn from other frameworks
    • We can continue to evolve/improve JSF
  • Why Wicket and Tapestry?
    • Similar in scope to JSF
    • Popular choices
    • Many areas of overlap
    • Different approaches
    • Interesting comparisons
    • Plenty of lessons to learn
  • Who?
    • User Interface Technology Architect, Oracle
    • Developing user interface frameworks since 1993
    • JSR-314/JSF 2.0 Expert Group Representative
    • Wicket/Tapestry Student
    • Biased, but honest :-)
  • Agenda
    • Hello, Frameworks!
    • Event Handling
    • Ajax
    • Navigation
    • Input Processing
    • Custom components
    • Wrap up
    • Hello, JSF!
  • JSF History
    • Originally standardized under JSR-127, 2004.
    • Standard piece of Java EE platform (Web Profile)
    • Sun serves as spec lead (Ed Burns, Roger Kitain)
    • JSR-252/JSF 1.2 enhancements, 2006
    • JSR-314/JSF 2.0 major release, 2009
    • Two widely used implementations
      • Mojarra (Reference Implementation)
      • MyFaces
  • JSF Vision
    • Swing-like component/event model
    • Declarative component tree specification
    • Integration with existing standards
    • Split logical (components) and physical (markup)
    • Tooling
    • Extensibility
  • What is a Page?
    • Legacy: Each page defined by a JSP (JSPX)
    • Now: Facelets standardized, preferred over JSP
    • Combines XHTML and component tags
    • Component tree definition specified via tags
    • Other view declaration languages (VDLs) available
      • JSF Templating, Gracelets
    • Saying Hello
    • (JSF)
  • Grunge: web.xml <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class> javax.faces.webapp.FacesServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping>
  • My First JSF Page <html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xmlns:h=&quot;http://java.sun.com/jsf/html&quot;> <head><title>My First JSF Page</title></head> <body> <!-- Our first JSF component usage --> Hello, <h:outputText value=&quot;World&quot;/>! </body> </html>
  • JSF Rendering
    • Page definition drives component tree creation
    • Component tree contains UIComponent instances
    • UIComponents delegate to Renderers
    • Response produced by traversing component tree
    • UIComponents/Renderers generate markup
    • Markup written via ResponseWriter
  • What Happens After Rendering?
    • Component tree state saved via StateManager
    • State stored in session or client
    • Component tree restored on postback
    • JSF 2.0 optimization: partial state saving
  • Bindings
    • Component attributes can be bound
    • Allows components to access dynamic data
    • Specified via Unified Expression Language (EL)
    • Bindings used for both reading and writing
  • A Simple Binding <h:outputText value=&quot;#{sessionScope.user.firstName}&quot;/>
  • Implicit Objects
    • Bindings have access implicit objects/scopes
    • Servlet-related scopes:
      • applicationScope
      • sessionScope
      • requestScope
    • JSF-specific scopes
      • viewScope
      • flash
      • component
    • Many more objects exposed
  • Managed Beans
    • POJOs
    • Named
    • Scoped
    • Container-managed
  • Managed Bean Registration <faces-config> <managed-bean> <managed-bean-name>user</managed-bean-name> <managed-bean-class>demo.User</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> </faces-config>
  • Managed Bean Registration @ManagedBean @SessionScoped public class User { public String getFirstName() { … } }
  • Managed Bean Reference <!-- Instead of this: --> <h:outputText value=&quot;#{sessionScope.user.firstName}&quot;/> <!-- We can now do this: --> <h:outputText value=&quot;#{user.firstName}&quot;/>
    • Hello, Wicket!
  • Wicket Quick History
    • Founded by Johnathan Locke, 2005
    • Originally hosted at SourceForge
    • Moved to Apache, 2007
    • Graduated to top level project, June 2007
    • Current version: 1.4.3 (as of November 2009)
  • Wicket Vision
    • Complete separation of markup and logic
    • Web designers do HTML
    • Application developers do Java
    • Designers benefit from previewability
    • Developers benefit from type-safety
    • No special tooling required
  • What is a Page?
    • Markup lives in a .html file
    • Code/components live in a .java file
    • Properties/messages in a .properties file
    • All files live on the class path
    • All files for a page share a name
    • Components correlated across html/java by id
    • Saying Hello
    • (Wicket)
  • Grunge: web.xml <filter> <filter-name>wicket</filter-name> <filter-class> org.apache.wicket.protocol.http.WicketFilter </filter-class> <filter-mapping> <filter-name>wicket</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </filter>
  • Grunge: web.xml <init-param> <param-name> applicationClassName </param-name> <param-value> org.demo.wicket.HelloApplication </param-value> </init-param>
  • My First Wicket Application public class HelloApplication extends WebApplication { @Override public Class<Hello> getHomePage() { return Hello.class; } }
  • My First Wicket Page (HTML) <html xmlns:wicket=&quot;…&quot;> <head><title>Hello, Wicket!</title></head> <body> <!-- My first Wicket component (html) --> Hello, <span wicket:id=&quot;name&quot; >Foo</span>! </body> </html>
  • My First Wicket Page (Java) public class Hello extends WebPage { public Hello() { // My first Wicket component (Java) add(new Label( &quot;name&quot; , &quot;World&quot;)); } }
  • Wicket Rendering
    • Markup exposed via MarkupStream
      • MarkupElements: RawText, ComponentTag
    • ComponentTags correlated with Components
    • onRender() called for each component
    • onComponentTag(): modify/render start tag
    • onComponentBodyTag(): modify/render body
    • MarkupElements written to response.
  • What Happens After Rendering?
    • Page state stored in page store
    • Pluggable page store behavior
      • DiskPageStore leverages file system for old pages
    • Page restored on postback
  • What is a Wicket Model?
    • Wicket models bind domain layer objects to components.
    • (Similar to EL ValueExpressions in JSF)
  • IModel Contract T getObject() void setObject(T object)
  • Components and Models
    • IModel<?> getDefaultModel()
    • Most components read from model.
    • Some components write to model.
  • Simple Model
    • Model class implements IModel
    • Stores model object locally
    • We have been using it already
  • Simple Model Sample // This: add(new Label(&quot;name&quot;, &quot;World&quot;); // Is shorthand for: add(new Label(&quot;name&quot;, new Model(&quot;World&quot;)));
  • Static Model
    • Simple Models are static.
    // This is static: add(new Label(&quot;random&quot;, new Model<Double>(Math.random()) ));
  • Dynamic Model
    • Override getObject() for dynamic.
    // This is dynamic: add(new Label(&quot;reallyRandom&quot;, new Model<Double>() { public Double getObject() { return Math.random(); } }));
  • Some More Models
    • PropertyModel
    • CompoundPropertyModel
    • LoadableDetachableModel
    • ResourceModel
    • Hello, Tapestry!
  • Tapestry Quick History
    • Founded by Howard Lewis Ship, 2000
    • Hosted at Apache
    • Graduated to top level project, June 2006
    • Current release: 5.1 (as of November 2009)
  • Tapestry Vision
    • Similar separation of markup/logic
    • Convention over Configuration
    • Inversion of Control
    • POJOs/annotations
    • Performance
  • What is a Page?
    • Markup lives in a .tml file
    • Code/components live in a .java file
    • Properties/messages in a .properties file
    • TML files live in web root
    • Other files on the class path
    • All files for a page share a name
    • Saying Hello
    • (Tapestry)
  • Grunge: web.xml <filter> <filter-name>tapestry</filter-name> <filter-class> org.apache.tapestry5.TapestryFilter </filter-class> </filter> <filter-mapping> <filter-name>tapestry</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
  • Grunge: web.xml <context-param> <param-name> tapestry.app-package </param-name> <param-value> org.example.tapestry </param-value> </context-param>
  • My First Tapestry Page (TML) <html xmlns:t=&quot;…&quot;> <head><title>Hello, Tapestry!</title></head> <body> <!-- My first Tapestry component. --> <!-- Note: We don't really need a component. --> Hello, <t:textoutput t:value=&quot;name&quot;/>! </body> </html>
  • My First Tapestry Page (Java) public class Index { @Property private String name; }
  • Tapestry Rendering
    • State machine/queue-based rendering
      • No recursive component tree traversal
    • Components hook into rendering phases
      • SetupRender, BeginRender, BeforeRenderBody, etc.
    • Specified via annotations or naming conventions
    • Hooks write response to MarkupWriter
      • Streaming API with access to DOM-like structure
  • What Happens After Rendering?
    • Persistent properties are state saved
      • @Persist annotation identifes properties to persist
    • Page is cleaned up and returned to pool
    • On postback, page instance retrieved from pool
    • Persistent property values are restored
    • Pooling is for performance (smaller footprint)
    • Implies mostly static page structures
    • Take 2: t:id
  • Take 2: TML <html xmlns:t=&quot;…&quot;> <head><title>Hello, Tapestry!</title></head> <body> <!-- Does this seem familiar? --> Hello, <span t:id=&quot;nameOutput&quot; >Foo</span>! </body> </html>
  • Take 2: Java public class Index { @Property private String name; @Component( parameters={&quot;value=name&quot;}) private TextOutput nameOutput; }
    • Take 3: t:type
  • Take 3: TML <html xmlns:t=&quot;…&quot;> <head><title>Hello, Tapestry!</title></head> <body> Hello, <span t:type=&quot;textoutput&quot; t:value=&quot;name&quot;>Foo</span>! </body> </html>
  • Facelets Flashback <!-- Remember this? --> <span jsfc=&quot;h:outputText&quot; value=&quot;#{name}&quot;>Foo</span>!
  • Tapestry Property Expressions
    • String notations for specifying object paths
    • Similar to EL
    • Supports referencing properties and methods
    • Used for parameters and template expansions
    • Compiled to Java classes (no reflection)
  • Property Expressions <!-- Component parameter --> <div><t:textoutput t:value=&quot;user.name&quot;/></div> <!-- Template expansion --> <div>${user.name}</div>
  • Binding Expressions
    • Parameters can bind to other types of values
    • Prefix identifies binding type:
      • prop
      • literal
      • asset
      • context
      • component
      • message
  • Binding Expressions <!-- Property Binding--> Hello, <t:textoutput t:value=&quot;name&quot;/>! <!-- Literal Binding--> Hello, <t:textoutput t:value=&quot;literal:World&quot;/>!
  • Some Initial Thoughts
    • Key difference: declarative vs programmatic component tree specification
    • JSF favors declarative approach
    • Wicket requires programmatic approach
    • Tapestry is somewhere in the middle
    • Component abstraction vs. direct access to HTML
  • Some More Thoughts
    • Implicit per-page Java object is convenient
    • Possible to simulate with JSF (viewScope bean)
    • Consider formalizing this in JSF?
    • Event Handling
  • JSF Event Handling
    • Inspired by Swing Event Model
    • Listeners registered on components
    • Components fire events
    • Declarative: listeners referenced via EL
  • JSF Event Handling <h:form> <h:commandButton value=&quot;Increment&quot; actionListener=&quot;#{counter.increment}&quot;/> <h:outputText value=&quot;#{counter.count}&quot;/> </h:form>
  • JSF Event Handling @ManagedBean @SessionScoped public class Counter { public int getCount() { return count; } public void increment() { count++; } private int count; }
  • Wicket Event Handling
    • Components expose event-specific hooks
    • Subclasses override to receive notifications
  • Wicket Event Handling <form wicket:id=&quot;form&quot;> <input type=&quot;submit&quot; value=&quot;Increment&quot; wicket:id=&quot;button&quot;/> <span wicket:id=&quot;count&quot;>count</span> </form>
  • Wicket Event Handling public class EventsPage extends WebPage { public EventsPage() { Button button = new Button(&quot;button&quot;) { @Override public void onSubmit() { count++; } }; } private int count; }
  • Wicket Event Handling
    • onSubmit() exposed at both Button and Form level
    • Button onSubmit() called first
    • Link component provides form/POST-free events
    • onClick() vs. onSubmit()
  • Tapestry Event Handling
    • Naming Conventions
    • Annotations
  • Tapestry Event Handling <t:form t:id=&quot;form1&quot;> <input type=&quot;submit&quot; value=&quot;Increment&quot; t:type=&quot;submit&quot; t:id=&quot;button1&quot;/> ${count} </t:form>
  • Tapestry Event Handling public class Events { @Persist @Property private int count; // Called when any form is submitted void onSubmit() { count++; } }
  • Tapestry Event Handling // All of these work too! // Called when form 1 is submitted void onSubmitFromForm1() { count++ } // Called when any button is selected void onSelected() { count++; } // Called when button1 is selected void onSelectedFromButton1() { count++; }
  • Tapestry Event Handling // And these too @OnEvent(value=&quot;selected&quot;, component=&quot;button1&quot;) void increment() { count++ } @OnEvent(value=&quot;submit&quot;, component=&quot;form&quot;) void foo() { count++ }
  • Tapestry Event Handling
    • Component-specific events before form
    • Global events before component-specific
    • ActionLink provides form/POST-free events
  • Event Handling Wrap Up
    • Three very different approaches
    • Managed bean annotations simplify JSF approach
    • Possible to add a Tapestry-like solution to JSF?
    • Possible to add Wicket-like solution to JSF?
      • Programmatic component creation cases, yes.
      • What about other cases?
    • Form-level submit hook is nice
    • Ajax
  • JSF Ajax
    • Before: Take your pick
      • ADF/Ice/Rich/Prime/Trinidad
    • Now: Standard Ajax APIs/implementation
    • Ajax behaviors attached to components
    • Primarily declarative solution
    • Programmatic APIs available too
  • JSF Ajax
    • <h:form>
    • <h:commandButton value=&quot;Increment&quot;
    • actionListener=&quot;#{counter.increment}&quot;>
    • <f:ajax render=&quot;count&quot;/>
    • </h:commandButton>
    • <h:outputText value=&quot;#{counter.count}&quot;
    • id=&quot;count&quot; />
    • </h:form>
  • JSF Ajax <f:ajax render=&quot;count&quot;/> <h:commandButton value=&quot;Increment&quot; actionListener=&quot;#{counter.increment}&quot;> <h:commandButton value=&quot;Reset&quot; actionListener=&quot;#{counter.reset}&quot;> </f:ajax>
  • JSF Ajax
    • All standard components support behaviors
    • Attach points are component-specific
      • Action, valueChange, focus, blur, mouse over, etc…
    • Behavior mechanism is extensible
    • Not specific to Ajax
  • Wicket Ajax
    • Ajax Components
    • Behaviors
  • Wicket Ajax AjaxButton button = new AjaxButton(&quot;button&quot;) { @Override public void onSubmit( AjaxRequestTarget target , Form form) { count++; if (target != null) { target.addComponent(label); } }});
  • Wicket Ajax label = new Label(&quot;count&quot;, …); label. setOutputMarkupId(true);
  • Wicket Ajax
    • Many convenience components, behaviors
    • Fallback behavior: AjaxFallbackLink
    • setOutputMarkupPlaceholderTag()
    • Ajax debug window
  • Tapestry Ajax
    • Ajax Zones
    • Mixins
  • Tapestry Ajax <t:form t:id=&quot;form1&quot; zone=&quot;countZone&quot; > <input type=&quot;submit&quot; value=&quot;Increment&quot; t:type=&quot;submit&quot; t:id=&quot;button1&quot;/> <t:zone t:id=&quot;countZone&quot;> Hello, ${count} </t:zone> </t:form>
  • Tapestry Ajax public class Ajax { @InjectComponent private Zone countZone; Object onSubmitFromForm1() { return countZone.getBody(); } }
  • Tapestry Ajax
    • Zone supported by Form, ActionLink, EventLink
    • MultiZoneUpdate
    • Mixins: autocomplete
  • Ajax Wrap Up
    • JSF 2.0 Ajax is competitive with other solutions
    • Wicket Ajax debug window is nice
      • JSF implementations could provide equivalent
    • Improve JSF's fallback story?
    • Resolve (or document) rendered toggling behavior
    • Navigation
  • JSF Navigation
    • Traditional: POST-based navigation
    • POST triggers action
    • Action determines outcome
    • Outcome mapped to target view
  • JSF Navigation <h:commandButton action=&quot;#{nav.goToPageB}&quot;/> @ManagedBean(name=&quot;nav&quot;) @RequestScoped public class Navigation { public String goToPageB() { return &quot;success&quot;; } }
  • JSF Navigation <navigation-rule> <from-view-id>/pageA.xhtml</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/pageB.xhtml</to-view-id> <redirect/> </navigation-case> </navigation-rule>
  • JSF Implicit Navigation
    • Declarative navigation is good for many cases
    • Perhaps too verbose for simple cases
    • Implicit navigation simplifies simple cases
    • Outcome implicitly treated as view id
    • Bypasses faces-config.xml
  • JSF Implicit Navigation <h:commandButton action=&quot;#{nav.goToPageB}&quot;/> @ManagedBean(name=&quot;nav&quot;) @RequestScoped public class Navigation { public String goToPageB() { // No faces-config entry required return &quot;pageB&quot; ; } }
  • JSF Pre-Emptive Navigation
    • Implict navigation simplifies, but still POST-only
    • Not GET/bookmark-friendly
    • Pre-emptive navigation: best of both worlds
    • Navigation rules aggressively evaluated
    • <h:link>/<h:button> produce GET requests
  • JSF Pre-Emptive Navigation <!-- Use navigation rules to determine &quot;success&quot; outcome target --> <h:button outcome=&quot;success&quot;/> <!-- Both pre-emptive and implicit. No faces-config needed. --> <h:button outcome=&quot;pageB&quot;/>
  • Wicket Navigation
    • Programmatic navigation: setResponsePage()
    • Class vs. instance
  • Wicket Navigation Button button1 = new Button(&quot;button1&quot;) { public void onSubmit() { setResponsePage(PageB.class); } };
  • Wicket Navigation Button button1 = new Button(&quot;button1&quot;) { public void onSubmit() { PageB pageB = new PageB(); // Configure PageB instance… setResponsePage(pageB); } }; Wicket Navigation
  • Wicket Navigation
    • Direct navigation also supported
    • BookmarkablePageLink
    • wicket:link
  • Wicket Navigation <!-- HTML --> <a wicket:id=&quot;bookmarkable&quot; href=&quot;PageB.html&quot;>Navigate To Page B</a> // Java form.add( new BookmarkablePageLink(&quot;bookmarkable&quot;, PageB.class));
  • Wicket Navigation <!-- No Java code required. --> <wicket:link> <ul> <li><a href=&quot;PageA.html&quot;>Page A</a></li> <li><a href=&quot;PageB.html&quot;>Page B</a></li> <li><a href=&quot;PageC.html&quot;>Page C</a></li> <li><a href=&quot;PageD.html&quot;>Page D</a></li> </ul> </wicket:link>
  • Tapestry Navigation
    • Programmatic navigation: onSubmit() return
    • Like Wicket, navigate to class or instance
    • Instance page injected
  • Tapestry Navigation public class PageA { Object onSubmitFromForm1() { return PageB.class; } }
  • Tapestry Navigation public class PageA { @InjectPage private PageB pageB; Object onSubmitFromForm1() { // Configure pageB instance... return pageB; } }
  • Tapestry Navigation
    • Direct navigation also supported
    • t:pageLink
  • Tapestry Navigation <t:pagelink t:page=&quot;PageB&quot;>Go</t:pagelink>
  • Navigation Wrap Up
    • JSF 2.0 enhancements simplify navigation
    • String outcomes vs. class/instance
    • Introduce class/instance support in JSF?
    • Redirect defaults
    • Input Processing
  • JSF Input Processing
    • EditableValueHolder lifecycle
      • Decode
      • Conversion
      • Validation
      • Update model
    • Value referenced via value expression
  • JSF Input Processing <h:inputText value=&quot;#{user.name}&quot;/> @ManagedBean public class User { public String getName() { return name; } public void setName(String name) { this.name = name; } private String name; }
  • JSF Conversion
    • Converters control transformation to/from string
    • Attached to EditableValueHolder components
    • Default conversion for most types
    • Date/time and number converters for more control
    • Custom converters
  • JSF Conversion <h:inputText value=&quot;#{user.age}&quot;> <f:convertNumber integerOnly=&quot;true&quot;/> </h:inputText>
  • JSF Validation
    • Validators verify converted value
    • Attached to EditableValueHolder components
    • Various standard validators provided with JSF
    • Also possible to implement custom validators
    • JSF 2.0 also applies JSR-303 validation constraints
  • JSF Validation <h:inputText value=&quot;#{user.age}&quot;> <f:validateLongRange minimum=&quot;18&quot;/> </h:inputText>
  • More JSF Validation
    • Feedback
      • Typically displayed via <h:messages>/<h:message>
      • More interesting feedback possible
    • Multi-component validation
      • Historically very tricky
      • PostValidate system event makes this much easier
    • Client-side validation
      • No out-of-box support
      • 3rd party solutions available (Trinidad/ADF Faces)
    • Ajax Validation
      • Facilitated by <f:ajax>
  • Wicket Input Processing
    • Similar lifecycle to JSF
      • Required field validation
      • Conversion
      • Validation
      • Push to model
      • onSubmit/onError
    • Value referenced via Model contract
  • Wicket Input Processing <!-- HTML --> <input type=&quot;text&quot; wicket:id=&quot;firstName&quot;/> // Java User user = getUser(); form.add(new TextField(&quot;firstName&quot;, new PropertyModel(user, &quot;name&quot;)));
  • Wicket Conversion
    • IConverter contract, similar to JSF Converter
    • Converts to/from string
    • Default converters
    • Type derived or hinted
    • Custom converters
      • Override getConverter()
  • Wicket Validation
    • IValidator, similar to JSF Validator
    • Validators attached programmatically
  • Wicket Validation <!-- HTML --> <input type=&quot;text&quot; wicket:id=&quot;age&quot;/> // Java add(new TextField(&quot;age&quot;, new PropertyModel(getUser(), &quot;age&quot;)) .add(NumberValidator.minimum(18)));
  • More Wicket Validation
    • Feedback
      • FeedbackPanel (like h:messages)
      • FormComponentFeedbackBorder
    • Multi-component validation
      • IFormValidator
    • Client-side validation
      • No out-of-box support
      • Ajax validation preferred
    • Ajax Validation
      • AjaxFormValidatingBehavior
  • Tapestry Input Processing
    • Similar lifecycle to JSF, Wicket
      • Conversion
      • Validation
      • Push to model
      • onSuccess/onFailure
    • Value referenced via property expressions
  • Tapestry Input Processing <!-- TML --> <input type=&quot;text&quot; t:type=&quot;textfield&quot; t:value=&quot;user.name&quot;/> // Java public class Input { @Property private User user; }
  • Tapestry Conversion
    • FieldTranslator, similar to Converter/IConverter
    • Event-based conversion
      • toclient
      • parseclient
  • Tapestry Conversion Events public class Input { String onToClientFromAge() { // Return String representation of age } Object onParseClientFromAge(String input) { // Return converted representation of age } }
  • Tapestry Validation
    • FieldValidator, similar to Validator/Ivalidator
    • Constraints attached via component parameters
    • Event and annotation-based validation
  • Parameter-Based Validation <input type=&quot;text&quot; t:type=&quot;textfield&quot; t:value=&quot;user.age&quot; t:validate=&quot;required,min=18&quot;/>
  • Event-Based Validation void onValidateFromAge(Integer value) throws ValidationException { if (value < 18) throw new ValidationException(&quot;Too young!&quot;); }
  • Anntation-Based Validation public class Input { @Property @Validate(&quot;required,min=18&quot;) private int age; }
  • More Tapestry Validation
    • Feedback
      • Border highlight, hover text
      • <t:errors>
    • Multi-component validation
      • onValidateForm()
    • Client-side validation
      • Provided automatically for standard validators
    • Ajax Validation
      • Client-side validation preferred
  • Input Processing Wrap Up
    • Similar input processing across frameworks
      • Surprise?
    • Pull client-side validation into JSF?
    • Improve feedback reporting
    • Encourage use of PostValidate system event for multi-component validation
    • Custom Components
  • JSF: Old School (Java)
    • Java class (extends UIComponent)
    • Renderer class
    • Tag class
    • faces-config.xml
    • tld
  • JSF: New School (Java)
    • Annotations replace faces-cofig.xml
    • Default Facelets handlers replace Tag class
    • taglib.xml replaces tld
  • JSF: New School (Composite)
    • Single Facelets file defines composite component
    • Installed in resources directory
    • Component namespace/name derived
    • No external configuration
    • Optional Java component class
    • Optional properties file
  • resources/demo/titleBorder.xhtml <html ... ><body> <composite:implementation> <div class=&quot;tb-root&quot;> <div class=&quot;tb-title&quot;> #{cc.attrs.title} </div> <div class=&quot;tb-body&quot;> <composite:insertChildren/> </div> </div> </composite:implementation> </body></html>
  • Composite Interface <composite:interface> <composite:attribute name=&quot;title&quot; required=&quot;true&quot;/> </composite:interface>
  • Component Usage <html … xmlns:demo= &quot;http://java.sun.com/jsf/composite/demo&quot;> <body> <demo:titleBorder title=&quot;My Favorite Greeting&quot;> Hello, World! </demo:titleBorder> </body> </html>
  • Wicket Custom Components
    • We have already seen several custom components
      • Think event handling
    • Can also define components with custom markup
    • Very similar to page
    • HTML/Java split
    • Java extends Panel or Border (not WebPage)
  • TitleBorder.html <html ... ><body> <wicket:border> <div class=&quot;tb-root&quot;> <div class=&quot;tb-title&quot; wicket:id=&quot;titleLabel&quot;>Title</div> <div class=&quot;tb-body&quot;> <wicket:body/> </div> </div> </wicket:border> </body></html>
  • TitleBorder.java public class TitleBorder extends Border { public TitleBorder(String id) { super(id); add(new Label(&quot;titleLabel&quot;, new PropertyModel(this, &quot;title&quot;))); } // Accessors private String title; }
  • Component Usage <!-- HTML --> <div wicket:id=&quot;titleBorder&quot;> Hello, World! </div> // Java add(new TitleBorder(&quot;titleBorder&quot;));
  • Tapestry Custom Components
    • Again, similar to page
    • TML/Java split
    • Java component is a POJO
    • Located in app-package/components directory
  • TitleBorder.tml <div class=&quot;tb-root&quot; ... > <div class=&quot;tb-title&quot;> ${title} </div> <div class=&quot;tb-body&quot;> <t:body/> </div> </div>
  • TitleBorder.java public class TitleBorder { @Property @Parameter(required=true, defaultPrefix=BindingConstants.LITERAL) private String title; }
  • Component Usage <t:titleborder t:title=&quot;My Favorite Greeting&quot;> Hello, World! </t:titleborder>
  • Custom Component Wrap Up
    • JSF custom component development became much, much simpler in 2.0
    • Composite components provide ease of use previously only available in other frameworks
    • Further simplifications possible?
      • Composite components
      • Java-based components
    • Wrap Up
  • So Much To Do, So Little Time
    • Many other possible points of comparison
      • Performance
      • Tooling
      • Testing
      • I18N
      • Persistence
      • REST
      • Extensions
      • Community
    • Other interesting frameworks too!
    • Presentation 2.0 :-)
  • Conclusion
    • Some differences are fundamental
    • Interesting to see many similarities too
    • Looking outward: good exercise
    • Good to see historical areas of difficulty addressed by JSF 2.0.
    • JSF2.next: Keep the progress coming!