Tapestry Components for Web 2.0 - PowerPoint PPT Presentation

1 / 55
About This Presentation
Title:

Tapestry Components for Web 2.0

Description:

Howard Lewis Ship TWD Consulting, Inc. hlship_at_gmail.com Login Form Border.html Placeholder for tacos:Dialog component Dialogs are invisible until un-hidden Active ... – PowerPoint PPT presentation

Number of Views:127
Avg rating:3.0/5.0
Slides: 56
Provided by: apac151
Category:

less

Transcript and Presenter's Notes

Title: Tapestry Components for Web 2.0


1
Tapestry Components for Web 2.0
  • Howard Lewis Ship
  • TWD Consulting, Inc.
  • hlship_at_gmail.com

2
What is Tapestry?
Application
Page
Page
Component
Component
Component
Component
Component
Component
3
Controller
Model
View
Java Beans
HTML template
Dynamic HTML output
Links / Form Submissions
4
Login Form
5
Border.html
ltdiv jwcid"loginDialog"gt ltdiv class"dialog"gt
ltform jwcid"form"gt ltpgt Enter your email
address and password to log in. lt/pgt ltspan
jwcid"errors_at_Errors"/gt ltlabel
jwcid"_at_FieldLabel" field"componentemail"/gt
ltinput jwcid"email" size"30"/gt ltlabel
jwcid"_at_FieldLabel" field"componentpassword"/gt
ltinput jwcid"password" size"30"/gt
ltinput type"submit" value"Login"/gt ltinput
jwcid"_at_Cancel" ajax"true"/gt lt/formgt ltpgt
Not registered yet? lta jwcid"register2"gt
Click here to setup an accountlt/agt. lt/pgt
lt/divgt lt/divgt
6
Border.html
ltdiv jwcid"loginDialog"gt . . . lt/divgt
  • Placeholder for tacosDialog component
  • Dialogs are invisible until un-hidden
  • Active dialogs mask the rest of the page

7
Border.jwc
ltcomponent id"loginDialog" type"tacosDialog"gt
ltbinding name"hidden" value"dialogHidden"/gt lt/c
omponentgt
  • Dialog visibility from dialogHidden property of
    page
  • Login link
  • Set dialogHidden to false
  • Re-render just the loginDialog

8
Border.jwc
ltcomponent id"login" type"tacosAjaxDirectLink"gt
ltbinding name"listener" value"listenerdoShow
Login"/gt ltbinding name"updateComponents"
value" 'loginDialog' "/gt lt/componentgt
  • Invoke the listener method
  • Re-render just the loginDialog component

9
Form component
ltform jwcid"form"gt . . . lt/formgt
  • Tapestry forms are inside a Form component
  • Unique names ids for fields (even inside loops)
  • Tracking of user input and errors
  • Handling submit, refresh cancel
  • AjaxForm Partial page refreshes

10
Form Component
ltcomponent id"form" type"tacosAjaxForm"gt
ltbinding name"updateComponents" value"
'errors' "/gt ltbinding name"success"
value"listenerdoLogin"/gt ltbinding
name"cancel" value"listenerdoCancel"/gt
ltbinding name"delegate" value"delegate"/gt lt/comp
onentgt
  • listener ? Name of listener method to invoke
  • delegate ? Object that tracks user input and
    errors

11
OGNL
  • Object Graph Navigation Language
  • Expression language used by Tapestry
  • ognl prefix when used in HTML template
  • No prefix when used in XML file

12
OGNL
  • Simple property names delegate ? getDelegate(),
    setDelegate()
  • Complex property paths poll.title ?
    getPoll().getTitle(), getPoll().setTitle()
  • Much more!

13
TextField Component
ltlabel jwcid"_at_FieldLabel" field"componentemail"
/gt ltinput jwcid"email" size"30"/gt
  • _at_FieldLabel ? anonymous component of type
    FieldLabel
  • Nothing in the Login.page file
  • componentemail ? reference to email component

14
TextField Component
ltcomponent id"email" type"TextField"gt
ltbinding name"value" value"email"/gt ltbinding
name"validators" value"validatorsrequired"/gt
ltbinding name"displayName" value"messageemail-l
abel"/gt lt/componentgt
  • value ? property to read and update
  • validators ? validations to perform
  • displayName ? Used in error messages, and by
    FieldLabel

15
Password TextField
ltcomponent id"password" type"TextField"gt
ltbinding name"value" value"password"/gt
ltbinding name"validators" value"validatorsrequi
red"/gt ltbinding name"displayName"
value"messagepassword-label"/gt ltbinding
name"hidden" value"true"/gt lt/componentgt
16
Register Link
ltpgtNot registered yet? lta jwcid"register"gtClick
here to setup an accountlt/agt. lt/pgt
ltcomponent id"register" type"PageLink"gt
ltbinding name"page" value"literalRegister"/gt
lt/componentgt
  • literal ? value is just a string, not an OGNL
    expression

17
Java Class
public abstract class Border extends
BaseComponent public abstract String
getEmail() public abstract String
getPassword() . . .
18
Abstract?
  • Pages are stateful
  • Hold transient data during request
  • Hold persistent data between requests
  • Pages are expensive to create
  • Pages are pooled
  • Like database connections

19
No, Really, Abstract?
  • Tapestry extends abstract class
  • Adds getter, setter, instance variables
  • Adds end-of-request cleanup
  • Lots of injections based on getters and
    annotations (or XML)

20
Page Behavior
21
Java Class
public abstract class Border extends
BaseComponent public abstract String
getEmail() public abstract String
getPassword() . . .
  • getEmail() setEmail()
  • getPassword() setPassword()

22
Listener Methods
public void doCancel() getLoginDialog().hide(
)
  • Public method
  • Changes server side state
  • Form will re-render

23
Injecting Services
_at_InjectObject("serviceepluribus.LoginAuthenticato
r") public abstract LoginAuthenticator
getAuthenticator()
public interface LoginAuthenticator User
authenticateCredentials(String email, String
plaintextPassword)
  • Service defined in HiveMind IoC Container
  • Can inject Spring beans as easily
  • Keep business logic out of pages / components

24
Listener Methods
public String doLogin() String email
getEmail() String password getPassword()
User user getAuthenticator().authenticateCredent
ials( email, password) . . .
25
Listener Methods
. . . if (user null)
getDelegate().record(null, "Invalid user
name or password.") return null
getIdentity().login(user) getLoginDialog().hid
e()
26
Server Side State ASO
_at_InjectState("identity") public abstract Identity
getIdentity()
  • Application State Objects
  • Global to all pages
  • Stored in HttpSession
  • Created on demand
  • Defined in HiveMind
  • Injected into pages or components

27
Identity ASO
public class Identity implements Serializable
. . . public boolean isLoggedIn() . . .
public void login(User user) . . .
public void logout() . . .
public User getUser() . . .
28
Loops, Tables and Actions
29
Home.html
lttable class"data-grid" cellspacing"0"
jwcid"polls"/gt ltdiv jwcid"pollingEndColumnValu
e_at_Block"gt ltspan jwcid"_at_InsertDate"
date"ognlpoll.pollingEnd"/gt lt/divgt ltdiv
jwcid"statusColumnValue_at_Block"gt ltspan
jwcid"_at_Insert" value"ognlresponseCount"/gt lta
jwcid"respond"gtRespondlt/agt lt/divgt
30
Home.page
ltproperty name"rowIndex"/gt ltcomponent
id"polls" type"contribTable"gt
ltbinding name"source" value"polls"/gt
ltbinding name"columns" value"messagetable-colum
ns"/gt ltbinding name"row" value"poll"/gt
ltbinding name"index" value"rowIndex"/gt
ltbinding name"rowsClass"gt rowIndex 0 ?
"first" null lt/bindinggt lt/componentgt
31
Home.page
ltproperty name"rowIndex"/gt ltcomponent
id"polls" type"contribTable"gt
ltbinding name"source" value"polls"/gt
ltbinding name"columns" value"messagetable-colum
ns"/gt ltbinding name"row" value"poll"/gt
ltbinding name"index" value"rowIndex"/gt
ltbinding name"rowsClass"gt rowIndex 0 ?
"first" null lt/bindinggt lt/componentgt
  • Defines a new property on page
  • Alternately create abstract property

32
Home.page
ltproperty name"rowIndex"/gt ltcomponent
id"polls" type"contribTable"gt
ltbinding name"source" value"polls"/gt
ltbinding name"columns" value"messagetable-colum
ns"/gt ltbinding name"row" value"poll"/gt
ltbinding name"index" value"rowIndex"/gt
ltbinding name"rowsClass"gt rowIndex 0 ?
"first" null lt/bindinggt lt/componentgt
  • contrib is name of tapestry-contrib.jar library

33
Home.page
ltproperty name"rowIndex"/gt ltcomponent
id"polls" type"contribTable"gt
ltbinding name"source" value"polls"/gt
ltbinding name"columns" value"messagetable-colum
ns"/gt ltbinding name"row" value"poll"/gt
ltbinding name"index" value"rowIndex"/gt
ltbinding name"rowsClass"gt rowIndex 0 ?
"first" null lt/bindinggt lt/componentgt
  • source ? total list of Poll objects

34
Home.page
ltproperty name"rowIndex"/gt ltcomponent
id"polls" type"contribTable"gt
ltbinding name"source" value"polls"/gt
ltbinding name"columns" value"messagetable-colum
ns"/gt ltbinding name"row" value"poll"/gt
ltbinding name"index" value"rowIndex"/gt
ltbinding name"rowsClass"gt rowIndex 0 ?
"first" null lt/bindinggt lt/componentgt
  • columns ? how to break a Poll object into columns

35
Home.properties
table-columns\ titleTitletitle, \
questionsQuestionsquestionCount, \
pollingEndEnd of PollingpollingEnd, \
!statusStatusnull
  • column-id title OGNL expression
  • poll.title
  • poll.questionCount
  • null ? calculated elsewhere
  • !status ? status is not sortable

36
Home.page
ltproperty name"rowIndex"/gt ltcomponent
id"polls" type"contribTable"gt
ltbinding name"source" value"polls"/gt
ltbinding name"columns" value"messagetable-colum
ns"/gt ltbinding name"row" value"poll"/gt
ltbinding name"index" value"rowIndex"/gt
ltbinding name"rowsClass"gt rowIndex 0 ?
"first" null lt/bindinggt lt/componentgt
  • row ? Property to update with each rendered row
    (each Poll)

37
Home.page
ltproperty name"rowIndex"/gt ltcomponent
id"polls" type"contribTable"gt
ltbinding name"source" value"polls"/gt
ltbinding name"columns" value"messagetable-colum
ns"/gt ltbinding name"row" value"poll"/gt
ltbinding name"index" value"rowIndex"/gt
ltbinding name"rowsClass"gt rowIndex 0 ?
"first" null lt/bindinggt lt/componentgt
  • index ? Stores index into row (used to set row
    CSS class)

38
Home.page
ltproperty name"rowIndex"/gt ltcomponent
id"polls" type"contribTable"gt
ltbinding name"source" value"polls"/gt
ltbinding name"columns" value"messagetable-colum
ns"/gt ltbinding name"row" value"poll"/gt
ltbinding name"index" value"rowIndex"/gt
ltbinding name"rowsClass"gt rowIndex 0 ?
"first" null lt/bindinggt lt/componentgt
  • rowsClass ? CSS class value for the lttrgt
  • Identify first row to change its formatting

39
Home.html
lttable class"data-grid" cellspacing"0"
jwcid"polls"/gt ltdiv jwcid"pollingEndColumnValu
e_at_Block"gt ltspan jwcid"_at_InsertDate"
date"ognlpoll.pollingEnd"/gt lt/divgt ltdiv
jwcid"statusColumnValue_at_Block"gt ltspan
jwcid"_at_Insert" value"ognlresponseCount"/gt lta
jwcid"respond"gtRespondlt/agt lt/divgt
40
Home.html
lttable class"data-grid" cellspacing"0"
jwcid"polls"/gt ltdiv jwcid"pollingEndColumnValu
e_at_Block"gt ltspan jwcid"_at_InsertDate"
date"ognlpoll.pollingEnd"/gt lt/divgt ltdiv
jwcid"statusColumnValue_at_Block"gt ltspan
jwcid"_at_Insert" value"ognlresponseCount"/gt lta
jwcid"respond"gtRespondlt/agt lt/divgt
41
Home.page
ltcomponent id"respond" type"DirectLink"gt
ltbinding name"listener" value"listenerdoRespond
"/gt ltbinding name"parameters"
value"poll.id"/gt lt/componentgt
  • DirectLink invokes a listener method when clicked
  • Can pass parameters into the listener method

42
Home.java
_at_InjectPage("RespondToPoll") public abstract
RespondToPoll getRespondToPoll() public void
doRespond(long pollId) Poll poll
getPollAccess().getPoll(pollId) // TODO A
few checks, i.e., Poll is active
getRespondToPoll().activate(poll)
  • Parameters show up with proper type (not just
    String)

43
Creating New Components
44
FCKEditor
  • "the text editor for the Internet"
  • Open Source
  • http//www.fckeditor.net/

45
FCKEditor
  • Primarily a JavaScript library
  • FCKeditor/fckeditor.js
  • Goal
  • Component to take place of TextArea

46
FCKEditor Component
  • FCKEditor.jwc ? Copy of TextArea.jwc
  • FCKEditor extends TextArea

47
FCKEditor.java
protected void renderFormComponent(IMarkupWriter
writer, IRequestCycle cycle)
super.renderFormComponent(writer, cycle) //
Now, we want to work with the script.
PageRenderSupport support TapestryUtils.getPageR
enderSupport(cycle, this) support.addExternalS
cript(getEditorScript().getResourceLocation())
String contextPath getRequest().getContextPath(
) String id getClientId() String
clientObject "editor_" id StringBuffer
buffer new StringBuffer()
buffer.append(String.format("var s new
FCKeditor('s')\n", clientObject, id))
buffer.append(String.format("s.BasePath
's/FCKeditor/'\n", clientObject,
contextPath)) buffer.append(String.format("s.R
eplaceTextarea()\n", clientObject))
support.addInitializationScript(buffer.toString())

48
FCKEditor.java
super.renderFormComponent(writer,
cycle) PageRenderSupport support
TapestryUtils.getPageRenderSupport(cycle,
this) support.addExternalScript(
getEditorScript().getResourceLocation())
_at_Asset("contextFCKeditor/fckeditor.js") public
abstract IAsset getEditorScript()
49
FCKEditor.java
String contextPath getRequest().getContextPath()
String id getClientId() String
clientObject "editor_" id
50
FCKEditor.java
StringBuffer buffer new StringBuffer() buffer.
append(String.format( "var s new
FCKeditor('s')\n", clientObject,
id)) buffer.append(String.format( "s.BasePath
's/FCKeditor/'\n", clientObject,
contextPath)) buffer.append(String.format( "s.R
eplaceTextarea()\n", clientObject)) support.ad
dInitializationScript(buffer.toString())
51
FCKEditor Summary
  • Easy to knit components JavaScript
  • Super easy to useltinput jwcid"_at_FCKEditor"
    value"ognldescription"/gt

52
Wrap Up
53
More Tapestry Topics
  • Persistent Page Properties
  • Creating New Components
  • Localization
  • Packaging component libraries
  • Integration with Hibernate and Spring
  • Unit and Integration Testing
  • Extending and Overriding Tapestry

54
ePluribus Source
  • Via Anonymous SVN
  • http//svn.javaforge.com/svn/tapestry/epluribus/tr
    unk
  • User anonymous
  • Password anon

55
Links
  • Tapestry
  • http//tapestry.apache.org
  • HiveMind
  • http//jakarta.apache.org/hivemind/
  • http//hivemind.apache.org/
  • Tacos
  • http//tacos.sf.net/
  • OGNL
  • http//www.ognl.org/
Write a Comment
User Comments (0)
About PowerShow.com