157
1 Component Framework Primer Component Framework Primer for JSF Users Andy Schwartz | Oracle Corporation

Component Framework Primer for JSF Users

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Component Framework Primer for JSF Users

1Component Framework Primer

Component Framework Primer for JSF Users

Andy Schwartz | Oracle Corporation

Page 2: Component Framework Primer for JSF Users

2Component Framework Primer

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)

Page 3: Component Framework Primer for JSF Users

3Component Framework Primer

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

Page 4: Component Framework Primer for JSF Users

4Component Framework Primer

Why Wicket and Tapestry? Similar in scope to JSF Popular choices Many areas of overlap Different approaches Interesting comparisons Plenty of lessons to learn

Page 5: Component Framework Primer for JSF Users

5Component Framework Primer

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 :-)

Page 6: Component Framework Primer for JSF Users

6Component Framework Primer

Agenda Hello, Frameworks! Event Handling Ajax Navigation Input Processing Custom components Wrap up

Page 7: Component Framework Primer for JSF Users

7Component Framework Primer

Hello, JSF!

Page 8: Component Framework Primer for JSF Users

8Component Framework Primer

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

Page 9: Component Framework Primer for JSF Users

9Component Framework Primer

JSF Vision Swing-like component/event model Declarative component tree specification Integration with existing standards Split logical (components) and physical (markup) Tooling Extensibility

Page 10: Component Framework Primer for JSF Users

10Component Framework Primer

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

Page 11: Component Framework Primer for JSF Users

11Component Framework Primer

Saying Hello(JSF)

Page 12: Component Framework Primer for JSF Users

12Component Framework Primer

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>

<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>

Page 13: Component Framework Primer for JSF Users

13Component Framework Primer

My First JSF Page

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html">

<head><title>My First JSF Page</title></head>

<body>

<!-- Our first JSF component usage -->

Hello, <h:outputText value="World"/>!

</body>

</html>

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html">

<head><title>My First JSF Page</title></head>

<body>

<!-- Our first JSF component usage -->

Hello, <h:outputText value="World"/>!

</body>

</html>

Page 14: Component Framework Primer for JSF Users

14Component Framework Primer

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

Page 15: Component Framework Primer for JSF Users

15Component Framework Primer

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

Page 16: Component Framework Primer for JSF Users

16Component Framework Primer

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

Page 17: Component Framework Primer for JSF Users

17Component Framework Primer

A Simple Binding

<h:outputText value="#{sessionScope.user.firstName}"/>

<h:outputText value="#{sessionScope.user.firstName}"/>

Page 18: Component Framework Primer for JSF Users

18Component Framework Primer

Implicit Objects Bindings have access implicit objects/scopes Servlet-related scopes:

– applicationScope– sessionScope– requestScope

JSF-specific scopes– viewScope– flash– component

Many more objects exposed

Page 19: Component Framework Primer for JSF Users

19Component Framework Primer

Managed Beans POJOs Named Scoped Container-managed

Page 20: Component Framework Primer for JSF Users

20Component Framework Primer

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>

<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>

Page 21: Component Framework Primer for JSF Users

21Component Framework Primer

Managed Bean Registration

@ManagedBean@SessionScopedpublic class User{ public String getFirstName() { … }}

@ManagedBean@SessionScopedpublic class User{ public String getFirstName() { … }}

Page 22: Component Framework Primer for JSF Users

22Component Framework Primer

Managed Bean Reference

<!-- Instead of this: --><h:outputText value="#{sessionScope.user.firstName}"/>

<!-- We can now do this: --><h:outputText value="#{user.firstName}"/>

<!-- Instead of this: --><h:outputText value="#{sessionScope.user.firstName}"/>

<!-- We can now do this: --><h:outputText value="#{user.firstName}"/>

Page 23: Component Framework Primer for JSF Users

23Component Framework Primer

Hello, Wicket!

Page 24: Component Framework Primer for JSF Users

24Component Framework Primer

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)

Page 25: Component Framework Primer for JSF Users

25Component Framework Primer

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

Page 26: Component Framework Primer for JSF Users

26Component Framework Primer

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

Page 27: Component Framework Primer for JSF Users

27Component Framework Primer

Saying Hello(Wicket)

Page 28: Component Framework Primer for JSF Users

28Component Framework Primer

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>

<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>

Page 29: Component Framework Primer for JSF Users

29Component Framework Primer

Grunge: web.xml

<init-param> <param-name> applicationClassName </param-name> <param-value> org.demo.wicket.HelloApplication </param-value></init-param>

<init-param> <param-name> applicationClassName </param-name> <param-value> org.demo.wicket.HelloApplication </param-value></init-param>

Page 30: Component Framework Primer for JSF Users

30Component Framework Primer

My First Wicket Application

public class HelloApplication

extends WebApplication {

@Override

public Class<Hello> getHomePage() {

return Hello.class;

}

}

public class HelloApplication

extends WebApplication {

@Override

public Class<Hello> getHomePage() {

return Hello.class;

}

}

Page 31: Component Framework Primer for JSF Users

31Component Framework Primer

My First Wicket Page (HTML)

<html xmlns:wicket="…">

<head><title>Hello, Wicket!</title></head>

<body>

<!-- My first Wicket component (html) -->

Hello, <span wicket:id="name">Foo</span>!

</body>

</html>

<html xmlns:wicket="…">

<head><title>Hello, Wicket!</title></head>

<body>

<!-- My first Wicket component (html) -->

Hello, <span wicket:id="name">Foo</span>!

</body>

</html>

Page 32: Component Framework Primer for JSF Users

32Component Framework Primer

My First Wicket Page (Java)

public class Hello extends WebPage {

public Hello() {

// My first Wicket component (Java)

add(new Label("name", "World"));

}

}

public class Hello extends WebPage {

public Hello() {

// My first Wicket component (Java)

add(new Label("name", "World"));

}

}

Page 33: Component Framework Primer for JSF Users

33Component Framework Primer

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.

Page 34: Component Framework Primer for JSF Users

34Component Framework Primer

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

Page 35: Component Framework Primer for JSF Users

35Component Framework Primer

What is a Wicket Model?

Wicket models bind domain layer objects to components.

(Similar to EL ValueExpressions in JSF)

Page 36: Component Framework Primer for JSF Users

36Component Framework Primer

IModel Contract

T getObject()void setObject(T object)

T getObject()void setObject(T object)

Page 37: Component Framework Primer for JSF Users

37Component Framework Primer

Components and Models

IModel<?> getDefaultModel()

Most components read from model.Some components write to model.

Page 38: Component Framework Primer for JSF Users

38Component Framework Primer

Simple Model

Model class implements IModel Stores model object locally We have been using it already

Page 39: Component Framework Primer for JSF Users

39Component Framework Primer

Simple Model Sample

// This:

add(new Label("name", "World");

// Is shorthand for:

add(new Label("name", new Model("World")));

// This:

add(new Label("name", "World");

// Is shorthand for:

add(new Label("name", new Model("World")));

Page 40: Component Framework Primer for JSF Users

40Component Framework Primer

Static Model

Simple Models are static.

// This is static:

add(new Label("random",

new Model<Double>(Math.random())

));

// This is static:

add(new Label("random",

new Model<Double>(Math.random())

));

Page 41: Component Framework Primer for JSF Users

41Component Framework Primer

Dynamic Model

Override getObject() for dynamic.

// This is dynamic:

add(new Label("reallyRandom",

new Model<Double>() {

public Double getObject() {

return Math.random();

}

}));

// This is dynamic:

add(new Label("reallyRandom",

new Model<Double>() {

public Double getObject() {

return Math.random();

}

}));

Page 42: Component Framework Primer for JSF Users

42Component Framework Primer

Some More Models PropertyModel CompoundPropertyModel LoadableDetachableModel ResourceModel

Page 43: Component Framework Primer for JSF Users

43Component Framework Primer

Hello, Tapestry!

Page 44: Component Framework Primer for JSF Users

44Component Framework Primer

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)

Page 45: Component Framework Primer for JSF Users

45Component Framework Primer

Tapestry Vision Similar separation of markup/logic Convention over Configuration Inversion of Control POJOs/annotations Performance

Page 46: Component Framework Primer for JSF Users

46Component Framework Primer

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

Page 47: Component Framework Primer for JSF Users

47Component Framework Primer

Saying Hello(Tapestry)

Page 48: Component Framework Primer for JSF Users

48Component Framework Primer

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>

<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>

Page 49: Component Framework Primer for JSF Users

49Component Framework Primer

Grunge: web.xml

<context-param>

<param-name>

tapestry.app-package

</param-name>

<param-value>

org.example.tapestry

</param-value>

</context-param>

<context-param>

<param-name>

tapestry.app-package

</param-name>

<param-value>

org.example.tapestry

</param-value>

</context-param>

Page 50: Component Framework Primer for JSF Users

50Component Framework Primer

My First Tapestry Page (TML)

<html xmlns:t="…">

<head><title>Hello, Tapestry!</title></head>

<body>

<!-- My first Tapestry component. -->

<!-- Note: We don't really need a component. -->

Hello, <t:textoutput t:value="name"/>!

</body>

</html>

<html xmlns:t="…">

<head><title>Hello, Tapestry!</title></head>

<body>

<!-- My first Tapestry component. -->

<!-- Note: We don't really need a component. -->

Hello, <t:textoutput t:value="name"/>!

</body>

</html>

Page 51: Component Framework Primer for JSF Users

51Component Framework Primer

My First Tapestry Page (Java)

public class Index {

@Property

private String name;

}

public class Index {

@Property

private String name;

}

Page 52: Component Framework Primer for JSF Users

52Component Framework Primer

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

Page 53: Component Framework Primer for JSF Users

53Component Framework Primer

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

Page 54: Component Framework Primer for JSF Users

54Component Framework Primer

Take 2: t:id

Page 55: Component Framework Primer for JSF Users

55Component Framework Primer

Take 2: TML

<html xmlns:t="…">

<head><title>Hello, Tapestry!</title></head>

<body>

<!-- Does this seem familiar? -->

Hello,

<span t:id="nameOutput">Foo</span>!

</body>

</html>

<html xmlns:t="…">

<head><title>Hello, Tapestry!</title></head>

<body>

<!-- Does this seem familiar? -->

Hello,

<span t:id="nameOutput">Foo</span>!

</body>

</html>

Page 56: Component Framework Primer for JSF Users

56Component Framework Primer

Take 2: Java

public class Index {

@Property

private String name;

@Component(

parameters={"value=name"})

private TextOutput nameOutput;

}

public class Index {

@Property

private String name;

@Component(

parameters={"value=name"})

private TextOutput nameOutput;

}

Page 57: Component Framework Primer for JSF Users

57Component Framework Primer

Take 3: t:type

Page 58: Component Framework Primer for JSF Users

58Component Framework Primer

Take 3: TML

<html xmlns:t="…">

<head><title>Hello, Tapestry!</title></head>

<body>

Hello,

<span t:type="textoutput"

t:value="name">Foo</span>!

</body>

</html>

<html xmlns:t="…">

<head><title>Hello, Tapestry!</title></head>

<body>

Hello,

<span t:type="textoutput"

t:value="name">Foo</span>!

</body>

</html>

Page 59: Component Framework Primer for JSF Users

59Component Framework Primer

Facelets Flashback

<!-- Remember this? -->

<span jsfc="h:outputText"

value="#{name}">Foo</span>!

<!-- Remember this? -->

<span jsfc="h:outputText"

value="#{name}">Foo</span>!

Page 60: Component Framework Primer for JSF Users

60Component Framework Primer

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)

Page 61: Component Framework Primer for JSF Users

61Component Framework Primer

Property Expressions

<!-- Component parameter -->

<div><t:textoutput t:value="user.name"/></div>

<!-- Template expansion -->

<div>${user.name}</div>

<!-- Component parameter -->

<div><t:textoutput t:value="user.name"/></div>

<!-- Template expansion -->

<div>${user.name}</div>

Page 62: Component Framework Primer for JSF Users

62Component Framework Primer

Binding Expressions Parameters can bind to other types of values Prefix identifies binding type:

– prop– literal– asset– context– component– message

Page 63: Component Framework Primer for JSF Users

63Component Framework Primer

Binding Expressions

<!-- Property Binding-->

Hello, <t:textoutput t:value="name"/>!

<!-- Literal Binding-->

Hello, <t:textoutput t:value="literal:World"/>!

<!-- Property Binding-->

Hello, <t:textoutput t:value="name"/>!

<!-- Literal Binding-->

Hello, <t:textoutput t:value="literal:World"/>!

Page 64: Component Framework Primer for JSF Users

64Component Framework Primer

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

Page 65: Component Framework Primer for JSF Users

65Component Framework Primer

Some More Thoughts Implicit per-page Java object is convenient Possible to simulate with JSF (viewScope bean) Consider formalizing this in JSF?

Page 66: Component Framework Primer for JSF Users

66Component Framework Primer

Event Handling

Page 67: Component Framework Primer for JSF Users

67Component Framework Primer

JSF Event Handling Inspired by Swing Event Model Listeners registered on components Components fire events Declarative: listeners referenced via EL

Page 68: Component Framework Primer for JSF Users

68Component Framework Primer

JSF Event Handling

<h:form>

<h:commandButton value="Increment"

actionListener="#{counter.increment}"/>

<h:outputText value="#{counter.count}"/>

</h:form>

<h:form>

<h:commandButton value="Increment"

actionListener="#{counter.increment}"/>

<h:outputText value="#{counter.count}"/>

</h:form>

Page 69: Component Framework Primer for JSF Users

69Component Framework Primer

JSF Event Handling

@ManagedBean

@SessionScoped

public class Counter {

public int getCount() { return count; }

public void increment() { count++; }

private int count;

}

@ManagedBean

@SessionScoped

public class Counter {

public int getCount() { return count; }

public void increment() { count++; }

private int count;

}

Page 70: Component Framework Primer for JSF Users

70Component Framework Primer

Wicket Event Handling

Components expose event-specific hooks Subclasses override to receive notifications

Page 71: Component Framework Primer for JSF Users

71Component Framework Primer

Wicket Event Handling

<form wicket:id="form">

<input type="submit" value="Increment"

wicket:id="button"/>

<span wicket:id="count">count</span>

</form>

<form wicket:id="form">

<input type="submit" value="Increment"

wicket:id="button"/>

<span wicket:id="count">count</span>

</form>

Page 72: Component Framework Primer for JSF Users

72Component Framework Primer

Wicket Event Handling

public class EventsPage extends WebPage {

public EventsPage() {

Button button = new Button("button") {

@Override

public void onSubmit() { count++; }

};

}

private int count;

}

public class EventsPage extends WebPage {

public EventsPage() {

Button button = new Button("button") {

@Override

public void onSubmit() { count++; }

};

}

private int count;

}

Page 73: Component Framework Primer for JSF Users

73Component Framework Primer

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()

Page 74: Component Framework Primer for JSF Users

74Component Framework Primer

Tapestry Event Handling

Naming Conventions Annotations

Page 75: Component Framework Primer for JSF Users

75Component Framework Primer

Tapestry Event Handling

<t:form t:id="form1">

<input type="submit" value="Increment"

t:type="submit" t:id="button1"/>

${count}

</t:form>

<t:form t:id="form1">

<input type="submit" value="Increment"

t:type="submit" t:id="button1"/>

${count}

</t:form>

Page 76: Component Framework Primer for JSF Users

76Component Framework Primer

Tapestry Event Handling

public class Events {

@Persist

@Property

private int count;

// Called when any form is submitted

void onSubmit() { count++; }

}

public class Events {

@Persist

@Property

private int count;

// Called when any form is submitted

void onSubmit() { count++; }

}

Page 77: Component Framework Primer for JSF Users

77Component Framework Primer

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++; }

// 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++; }

Page 78: Component Framework Primer for JSF Users

78Component Framework Primer

Tapestry Event Handling

// And these too

@OnEvent(value="selected", component="button1")void increment() { count++ }

@OnEvent(value="submit", component="form")void foo() { count++ }

// And these too

@OnEvent(value="selected", component="button1")void increment() { count++ }

@OnEvent(value="submit", component="form")void foo() { count++ }

Page 79: Component Framework Primer for JSF Users

79Component Framework Primer

Tapestry Event Handling

Component-specific events before form Global events before component-specific ActionLink provides form/POST-free events

Page 80: Component Framework Primer for JSF Users

80Component Framework Primer

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

Page 81: Component Framework Primer for JSF Users

81Component Framework Primer

Ajax

Page 82: Component Framework Primer for JSF Users

82Component Framework Primer

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

Page 83: Component Framework Primer for JSF Users

83Component Framework Primer

JSF Ajax

<h:form>

<h:commandButton value="Increment"

actionListener="#{counter.increment}">

<f:ajax render="count"/>

</h:commandButton>

<h:outputText value="#{counter.count}"

id="count"/>

</h:form>

<h:form>

<h:commandButton value="Increment"

actionListener="#{counter.increment}">

<f:ajax render="count"/>

</h:commandButton>

<h:outputText value="#{counter.count}"

id="count"/>

</h:form>

Page 84: Component Framework Primer for JSF Users

84Component Framework Primer

JSF Ajax

<f:ajax render="count"/>

<h:commandButton value="Increment"

actionListener="#{counter.increment}">

<h:commandButton value="Reset"

actionListener="#{counter.reset}">

</f:ajax>

<f:ajax render="count"/>

<h:commandButton value="Increment"

actionListener="#{counter.increment}">

<h:commandButton value="Reset"

actionListener="#{counter.reset}">

</f:ajax>

Page 85: Component Framework Primer for JSF Users

85Component Framework Primer

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

Page 86: Component Framework Primer for JSF Users

86Component Framework Primer

Wicket Ajax

Ajax Components Behaviors

Page 87: Component Framework Primer for JSF Users

87Component Framework Primer

Wicket Ajax

AjaxButton button = new AjaxButton("button") {

@Override

public void onSubmit(

AjaxRequestTarget target, Form form) {

count++;

if (target != null) {

target.addComponent(label);

}

}});

AjaxButton button = new AjaxButton("button") {

@Override

public void onSubmit(

AjaxRequestTarget target, Form form) {

count++;

if (target != null) {

target.addComponent(label);

}

}});

Page 88: Component Framework Primer for JSF Users

88Component Framework Primer

Wicket Ajax

label = new Label("count", …);

label.setOutputMarkupId(true);

label = new Label("count", …);

label.setOutputMarkupId(true);

Page 89: Component Framework Primer for JSF Users

89Component Framework Primer

Wicket Ajax Many convenience components, behaviors Fallback behavior: AjaxFallbackLink setOutputMarkupPlaceholderTag() Ajax debug window

Page 90: Component Framework Primer for JSF Users

90Component Framework Primer

Tapestry Ajax

Ajax Zones Mixins

Page 91: Component Framework Primer for JSF Users

91Component Framework Primer

Tapestry Ajax

<t:form t:id="form1" zone="countZone">

<input type="submit" value="Increment"

t:type="submit" t:id="button1"/>

<t:zone t:id="countZone">

Hello, ${count}

</t:zone>

</t:form>

<t:form t:id="form1" zone="countZone">

<input type="submit" value="Increment"

t:type="submit" t:id="button1"/>

<t:zone t:id="countZone">

Hello, ${count}

</t:zone>

</t:form>

Page 92: Component Framework Primer for JSF Users

92Component Framework Primer

Tapestry Ajax

public class Ajax {

@InjectComponent

private Zone countZone;

Object onSubmitFromForm1() {

return countZone.getBody();

}

}

public class Ajax {

@InjectComponent

private Zone countZone;

Object onSubmitFromForm1() {

return countZone.getBody();

}

}

Page 93: Component Framework Primer for JSF Users

93Component Framework Primer

Tapestry Ajax

Zone supported by Form, ActionLink, EventLink MultiZoneUpdate Mixins: autocomplete

Page 94: Component Framework Primer for JSF Users

94Component Framework Primer

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

Page 95: Component Framework Primer for JSF Users

95Component Framework Primer

Navigation

Page 96: Component Framework Primer for JSF Users

96Component Framework Primer

JSF Navigation Traditional: POST-based navigation POST triggers action Action determines outcome Outcome mapped to target view

Page 97: Component Framework Primer for JSF Users

97Component Framework Primer

JSF Navigation

<h:commandButton action="#{nav.goToPageB}"/>

@ManagedBean(name="nav")

@RequestScoped

public class Navigation {

public String goToPageB() {

return "success";

}

}

<h:commandButton action="#{nav.goToPageB}"/>

@ManagedBean(name="nav")

@RequestScoped

public class Navigation {

public String goToPageB() {

return "success";

}

}

Page 98: Component Framework Primer for JSF Users

98Component Framework Primer

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>

<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>

Page 99: Component Framework Primer for JSF Users

99Component Framework Primer

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

Page 100: Component Framework Primer for JSF Users

100Component Framework Primer

JSF Implicit Navigation

<h:commandButton action="#{nav.goToPageB}"/>

@ManagedBean(name="nav")

@RequestScoped

public class Navigation {

public String goToPageB() {

// No faces-config entry required

return "pageB";

}

}

<h:commandButton action="#{nav.goToPageB}"/>

@ManagedBean(name="nav")

@RequestScoped

public class Navigation {

public String goToPageB() {

// No faces-config entry required

return "pageB";

}

}

Page 101: Component Framework Primer for JSF Users

101Component Framework Primer

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

Page 102: Component Framework Primer for JSF Users

102Component Framework Primer

JSF Pre-Emptive Navigation

<!-- Use navigation rules to determine "success" outcome target -->

<h:button outcome="success"/>

<!-- Both pre-emptive and implicit. No faces-config needed. -->

<h:button outcome="pageB"/>

<!-- Use navigation rules to determine "success" outcome target -->

<h:button outcome="success"/>

<!-- Both pre-emptive and implicit. No faces-config needed. -->

<h:button outcome="pageB"/>

Page 103: Component Framework Primer for JSF Users

103Component Framework Primer

Wicket Navigation

Programmatic navigation: setResponsePage() Class vs. instance

Page 104: Component Framework Primer for JSF Users

104Component Framework Primer

Wicket Navigation

Button button1 = new Button("button1") {

public void onSubmit() {

setResponsePage(PageB.class);

}

};

Button button1 = new Button("button1") {

public void onSubmit() {

setResponsePage(PageB.class);

}

};

Page 105: Component Framework Primer for JSF Users

105Component Framework Primer

Wicket Navigation

Button button1 = new Button("button1") {

public void onSubmit() {

PageB pageB = new PageB();

// Configure PageB instance…

setResponsePage(pageB);

}

};

Button button1 = new Button("button1") {

public void onSubmit() {

PageB pageB = new PageB();

// Configure PageB instance…

setResponsePage(pageB);

}

};

Wicket Navigation

Page 106: Component Framework Primer for JSF Users

106Component Framework Primer

Wicket Navigation

Direct navigation also supported BookmarkablePageLink wicket:link

Page 107: Component Framework Primer for JSF Users

107Component Framework Primer

Wicket Navigation

<!-- HTML -->

<a wicket:id="bookmarkable"

href="PageB.html">Navigate To Page B</a>

// Java

form.add(

new BookmarkablePageLink("bookmarkable",

PageB.class));

<!-- HTML -->

<a wicket:id="bookmarkable"

href="PageB.html">Navigate To Page B</a>

// Java

form.add(

new BookmarkablePageLink("bookmarkable",

PageB.class));

Page 108: Component Framework Primer for JSF Users

108Component Framework Primer

<!-- No Java code required. -->

<wicket:link>

<ul>

<li><a href="PageA.html">Page A</a></li>

<li><a href="PageB.html">Page B</a></li>

<li><a href="PageC.html">Page C</a></li>

<li><a href="PageD.html">Page D</a></li>

</ul>

</wicket:link>

<!-- No Java code required. -->

<wicket:link>

<ul>

<li><a href="PageA.html">Page A</a></li>

<li><a href="PageB.html">Page B</a></li>

<li><a href="PageC.html">Page C</a></li>

<li><a href="PageD.html">Page D</a></li>

</ul>

</wicket:link>

Wicket Navigation

Page 109: Component Framework Primer for JSF Users

109Component Framework Primer

Tapestry Navigation

Programmatic navigation: onSubmit() return Like Wicket, navigate to class or instance Instance page injected

Page 110: Component Framework Primer for JSF Users

110Component Framework Primer

Tapestry Navigation

public class PageA {

Object onSubmitFromForm1() {

return PageB.class;

}

}

public class PageA {

Object onSubmitFromForm1() {

return PageB.class;

}

}

Page 111: Component Framework Primer for JSF Users

111Component Framework Primer

Tapestry Navigation

public class PageA {

@InjectPage

private PageB pageB;

Object onSubmitFromForm1() {

// Configure pageB instance...

return pageB;

}

}

public class PageA {

@InjectPage

private PageB pageB;

Object onSubmitFromForm1() {

// Configure pageB instance...

return pageB;

}

}

Page 112: Component Framework Primer for JSF Users

112Component Framework Primer

Tapestry Navigation

Direct navigation also supported t:pageLink

Page 113: Component Framework Primer for JSF Users

113Component Framework Primer

Tapestry Navigation

<t:pagelink t:page="PageB">Go</t:pagelink><t:pagelink t:page="PageB">Go</t:pagelink>

Page 114: Component Framework Primer for JSF Users

114Component Framework Primer

Navigation Wrap Up JSF 2.0 enhancements simplify navigation String outcomes vs. class/instance Introduce class/instance support in JSF? Redirect defaults

Page 115: Component Framework Primer for JSF Users

115Component Framework Primer

Input Processing

Page 116: Component Framework Primer for JSF Users

116Component Framework Primer

JSF Input Processing EditableValueHolder lifecycle

– Decode– Conversion– Validation– Update model

Value referenced via value expression

Page 117: Component Framework Primer for JSF Users

117Component Framework Primer

JSF Input Processing

<h:inputText value="#{user.name}"/>

@ManagedBean

public class User {

public String getName() { return name; }

public void setName(String name) {

this.name = name;

}

private String name;

}

<h:inputText value="#{user.name}"/>

@ManagedBean

public class User {

public String getName() { return name; }

public void setName(String name) {

this.name = name;

}

private String name;

}

Page 118: Component Framework Primer for JSF Users

118Component Framework Primer

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

Page 119: Component Framework Primer for JSF Users

119Component Framework Primer

JSF Conversion

<h:inputText value="#{user.age}">

<f:convertNumber integerOnly="true"/>

</h:inputText>

<h:inputText value="#{user.age}">

<f:convertNumber integerOnly="true"/>

</h:inputText>

Page 120: Component Framework Primer for JSF Users

120Component Framework Primer

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

Page 121: Component Framework Primer for JSF Users

121Component Framework Primer

JSF Validation

<h:inputText value="#{user.age}">

<f:validateLongRange minimum="18"/>

</h:inputText>

<h:inputText value="#{user.age}">

<f:validateLongRange minimum="18"/>

</h:inputText>

Page 122: Component Framework Primer for JSF Users

122Component Framework Primer

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>

Page 123: Component Framework Primer for JSF Users

123Component Framework Primer

Wicket Input Processing Similar lifecycle to JSF

– Required field validation– Conversion– Validation– Push to model– onSubmit/onError

Value referenced via Model contract

Page 124: Component Framework Primer for JSF Users

124Component Framework Primer

Wicket Input Processing

<!-- HTML -->

<input type="text" wicket:id="firstName"/>

// Java

User user = getUser();

form.add(new TextField("firstName",

new PropertyModel(user, "name")));

<!-- HTML -->

<input type="text" wicket:id="firstName"/>

// Java

User user = getUser();

form.add(new TextField("firstName",

new PropertyModel(user, "name")));

Page 125: Component Framework Primer for JSF Users

125Component Framework Primer

Wicket Conversion IConverter contract, similar to JSF Converter Converts to/from string Default converters Type derived or hinted Custom converters

– Override getConverter()

Page 126: Component Framework Primer for JSF Users

126Component Framework Primer

Wicket Validation

IValidator, similar to JSF Validator Validators attached programmatically

Page 127: Component Framework Primer for JSF Users

127Component Framework Primer

Wicket Validation

<!-- HTML -->

<input type="text" wicket:id="age"/>

// Java

add(new TextField("age",

new PropertyModel(getUser(), "age"))

.add(NumberValidator.minimum(18)));

<!-- HTML -->

<input type="text" wicket:id="age"/>

// Java

add(new TextField("age",

new PropertyModel(getUser(), "age"))

.add(NumberValidator.minimum(18)));

Page 128: Component Framework Primer for JSF Users

128Component Framework Primer

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

Page 129: Component Framework Primer for JSF Users

129Component Framework Primer

Tapestry Input Processing Similar lifecycle to JSF, Wicket

– Conversion– Validation– Push to model– onSuccess/onFailure

Value referenced via property expressions

Page 130: Component Framework Primer for JSF Users

130Component Framework Primer

Tapestry Input Processing

<!-- TML -->

<input type="text" t:type="textfield" t:value="user.name"/>

// Java

public class Input {

@Property

private User user;

}

<!-- TML -->

<input type="text" t:type="textfield" t:value="user.name"/>

// Java

public class Input {

@Property

private User user;

}

Page 131: Component Framework Primer for JSF Users

131Component Framework Primer

Tapestry Conversion

FieldTranslator, similar to Converter/IConverter Event-based conversion

– toclient– parseclient

Page 132: Component Framework Primer for JSF Users

132Component Framework Primer

Tapestry Conversion Events

public class Input {

String onToClientFromAge() {

// Return String representation of age

}

Object onParseClientFromAge(String input) {

// Return converted representation of age

}

}

public class Input {

String onToClientFromAge() {

// Return String representation of age

}

Object onParseClientFromAge(String input) {

// Return converted representation of age

}

}

Page 133: Component Framework Primer for JSF Users

133Component Framework Primer

Tapestry Validation

FieldValidator, similar to Validator/Ivalidator Constraints attached via component parameters Event and annotation-based validation

Page 134: Component Framework Primer for JSF Users

134Component Framework Primer

Parameter-Based Validation

<input type="text" t:type="textfield"

t:value="user.age"

t:validate="required,min=18"/>

<input type="text" t:type="textfield"

t:value="user.age"

t:validate="required,min=18"/>

Page 135: Component Framework Primer for JSF Users

135Component Framework Primer

Event-Based Validation

void onValidateFromAge(Integer value)

throws ValidationException

{

if (value < 18)

throw new ValidationException("Too young!");

}

void onValidateFromAge(Integer value)

throws ValidationException

{

if (value < 18)

throw new ValidationException("Too young!");

}

Page 136: Component Framework Primer for JSF Users

136Component Framework Primer

Anntation-Based Validation

public class Input { @Property @Validate("required,min=18") private int age;}

public class Input { @Property @Validate("required,min=18") private int age;}

Page 137: Component Framework Primer for JSF Users

137Component Framework Primer

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

Page 138: Component Framework Primer for JSF Users

138Component Framework Primer

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

Page 139: Component Framework Primer for JSF Users

139Component Framework Primer

Custom Components

Page 140: Component Framework Primer for JSF Users

140Component Framework Primer

JSF: Old School (Java) Java class (extends UIComponent) Renderer class Tag class faces-config.xml tld

Page 141: Component Framework Primer for JSF Users

141Component Framework Primer

JSF: New School (Java)

Annotations replace faces-cofig.xml Default Facelets handlers replace Tag class taglib.xml replaces tld

Page 142: Component Framework Primer for JSF Users

142Component Framework Primer

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

Page 143: Component Framework Primer for JSF Users

143Component Framework Primer

resources/demo/titleBorder.xhtml<html ... ><body>

<composite:implementation>

<div class="tb-root">

<div class="tb-title">#{cc.attrs.title}</div>

<div class="tb-body">

<composite:insertChildren/>

</div>

</div>

</composite:implementation>

</body></html>

<html ... ><body>

<composite:implementation>

<div class="tb-root">

<div class="tb-title">#{cc.attrs.title}</div>

<div class="tb-body">

<composite:insertChildren/>

</div>

</div>

</composite:implementation>

</body></html>

Page 144: Component Framework Primer for JSF Users

144Component Framework Primer

Composite Interface

<composite:interface> <composite:attribute name="title" required="true"/></composite:interface>

<composite:interface> <composite:attribute name="title" required="true"/></composite:interface>

Page 145: Component Framework Primer for JSF Users

145Component Framework Primer

Component Usage

<html … xmlns:demo=

"http://java.sun.com/jsf/composite/demo">

<body>

<demo:titleBorder title="My Favorite Greeting">

Hello, World!

</demo:titleBorder>

</body>

</html>

<html … xmlns:demo=

"http://java.sun.com/jsf/composite/demo">

<body>

<demo:titleBorder title="My Favorite Greeting">

Hello, World!

</demo:titleBorder>

</body>

</html>

Page 146: Component Framework Primer for JSF Users

146Component Framework Primer

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)

Page 147: Component Framework Primer for JSF Users

147Component Framework Primer

TitleBorder.html<html ... ><body>

<wicket:border>

<div class="tb-root">

<div class="tb-title"

wicket:id="titleLabel">Title</div>

<div class="tb-body">

<wicket:body/>

</div>

</div>

</wicket:border>

</body></html>

<html ... ><body>

<wicket:border>

<div class="tb-root">

<div class="tb-title"

wicket:id="titleLabel">Title</div>

<div class="tb-body">

<wicket:body/>

</div>

</div>

</wicket:border>

</body></html>

Page 148: Component Framework Primer for JSF Users

148Component Framework Primer

TitleBorder.javapublic class TitleBorder extends Border {

public TitleBorder(String id) {

super(id);

add(new Label("titleLabel",

new PropertyModel(this, "title")));

}

// Accessors

private String title;

}

public class TitleBorder extends Border {

public TitleBorder(String id) {

super(id);

add(new Label("titleLabel",

new PropertyModel(this, "title")));

}

// Accessors

private String title;

}

Page 149: Component Framework Primer for JSF Users

149Component Framework Primer

Component Usage

<!-- HTML -->

<div wicket:id="titleBorder">

Hello, World!

</div>

// Java

add(new TitleBorder("titleBorder"));

<!-- HTML -->

<div wicket:id="titleBorder">

Hello, World!

</div>

// Java

add(new TitleBorder("titleBorder"));

Page 150: Component Framework Primer for JSF Users

150Component Framework Primer

Tapestry Custom Components Again, similar to page TML/Java split Java component is a POJO Located in app-package/components directory

Page 151: Component Framework Primer for JSF Users

151Component Framework Primer

TitleBorder.tml

<div class="tb-root" ... >

<div class="tb-title">${title}</div>

<div class="tb-body">

<t:body/>

</div>

</div>

<div class="tb-root" ... >

<div class="tb-title">${title}</div>

<div class="tb-body">

<t:body/>

</div>

</div>

Page 152: Component Framework Primer for JSF Users

152Component Framework Primer

TitleBorder.java

public class TitleBorder {

@Property

@Parameter(required=true,

defaultPrefix=BindingConstants.LITERAL)

private String title;

}

public class TitleBorder {

@Property

@Parameter(required=true,

defaultPrefix=BindingConstants.LITERAL)

private String title;

}

Page 153: Component Framework Primer for JSF Users

153Component Framework Primer

Component Usage

<t:titleborder t:title="My Favorite Greeting">

Hello, World!

</t:titleborder>

<t:titleborder t:title="My Favorite Greeting">

Hello, World!

</t:titleborder>

Page 154: Component Framework Primer for JSF Users

154Component Framework Primer

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

Page 155: Component Framework Primer for JSF Users

155Component Framework Primer

Wrap Up

Page 156: Component Framework Primer for JSF Users

156Component Framework Primer

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 :-)

Page 157: Component Framework Primer for JSF Users

157Component Framework Primer

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!