javaserver faces - phillyjug · javaserver faces and core rave 2nd struts committer; designed and...
TRANSCRIPT
1
Undoubtedly The Next Big Thing for Enterprise Java!
JavaServer Faces
Philadelphia JUGJanuary 19, 2004
David Gearywww.corejsf.com
20 yrs OO development; Sun from 1994-1997
Member of JSF and JSTL Expert Groups
Author of 6 Java books; coming soon: Core JavaServer Faces and Core Rave
2nd Struts committer; Designed and implemented the Struts Template library
Wrote test questions for the Web Developer Certification Exam
JavaWorld Columnist: Java Design Patterns
David Geary
2
Tonight’s demos
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Table
Stereo Deck demo
Custom components and renderers
Puzzle Demo
3
1999: Servlets
JavaServer Pages (JSP)
Struts
The JSP Standard Tag Library (JSTL)
JavaServer Faces
A brief history of server-side Java
A web application framework (like Struts)
Controller servlet, actions, beans
Server-side components (like Swing)
Components, layout managers, event model
JSP-based; rendering technology independent
Core and HTML JSP tags
A standard
What is JSF?
4
A JSF page
<h:panel_grid columns='2'>
</h:panel_grid>
<%@ taglib uri=’http://java.sun.com/jsf/core’ prefix=’f’ %><%@ taglib uri=’http://java.sun.com/jsf/html’ prefix=’h’ %>
<f:view locale=’en-US’>
</f:view>
<h:output_text value=’#{msgs.namePrompt}’/> <h:input_text value='#{user.name}'/>...<h:command_button value=’#{msgs.submitPrompt}’/>
<h:form>
</h:form>
<f:loadBundle basename=’messages’ var=’msgs’/>
The managed bean
</managed-bean> ...
</faces-config>
<faces-config>...<managed-bean>
<managed-bean-name>user</managed-bean-name><managed-bean-class>beans.User</managed-bean-class><managed-bean-scope>request</managed-bean-scope>
</managed-bean>...
</faces-config>
<managed-property><property-name>name</property-name><value>Willis</value>
</managed-property>
5
JSP custom tags
Components (independent of rendering)
Converters (String==>Object; Object==>String)
Validators (length, double-range, long-range...)
Facets
Managed beans
JSF Main Players
Event handlers (action and value changed listeners)
Actions (insert business logic here)
Renderers (encode component markup here)
Render kits (markup-specific groups of renderers)
Pluggable subsystems
Navigation and view handlers, resolvers, listeners
JSF Main Players (cont)
6
Is JSF a replacement for Struts? Yes!
Struts is more reliableStruts has better tool support
Validator, WebDoclet, Tiles, StrutsTestCase
Struts has better documentation (books and articles)
JSF and Struts
JSF is a “better Struts”
JSF has server-side components
JSF will be the standard web application framework
You can use Struts and JSF together
JSF and Struts (cont.)
7
Specification: Public Review Draft 2, July 2003
Reference implementation: EA4 (JWSDP 1.2)
1.0 Beta scheduled for December, 2003
1.0 FCS, Q1CY2004
JSF Status
http://java.sun.com/j2ee/javaserverfaces
http://www.corejsf and http://www.core-jstl.com
http://www.theserverside.com/resources/JSFInActionReview.jsp
JSF Resources
8
http://www.jsfcentral.com
http://forum.java.sun.com/forum.jsp?forum=427
http://www.javaworld.com/javaworld/jw-11-2002/jw-1129-jsf_p.html
http://www.javaworld.com/javaworld/jw-12-2002/jw-1227-jsf2_p.html
More Resources
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Table
Stereo Deck demo
Custom components and renderers
Puzzle Demo
9
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Table
Stereo Deck demo
Custom components and renderers
Puzzle Demo
Hello Willis
/index.jsp
/welcome.jsp
10
The bean class
public void setName(String name) { this.name = name; }public String getName() { return name; }public String getPassword() { return password; }public void setPassword(String password) {
this.password = password; }public String getPasswordConfirm() { return passwordConfirm; }public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm; }public void setEmail(String email) { this.email = email; }public String getEmail() { return email; }
public class RegisterForm {private String name, email, password, passwordConfirm;
}
The form<%@ taglib uri=’http://java.sun.com/jsf/core’ prefix=’f’ %><%@ taglib uri=’http://java.sun.com/jsf/html’ prefix=’h’ %>
<h:output_text value=’#{msgs.namePrompt}’/><h:input_text value=’#{registerForm.name}’/>...
<h:command_button value=’#{msgs.submitPrompt}’/>
<h:panel_grid columns=’2’>
</h:panel_grid>
<h:form>
</h:form>
<f:view locale=’en-US’><f:loadBundle basename=’messages’ var=’msgs’/>...
</f:view>
11
The properties file
emailAddressPrompt=Email addresspasswordPrompt=PasswordpasswordConfirmPrompt=Confirm password
welcomeWindowTitle=WelcomewelcomePageTitle=Welcome {0}
namePrompt=Name
submitPrompt=Register
The managed bean<faces-config>
...<managed-bean>
</managed-bean>...
</faces-config>
<managed-bean-name>user</managed-bean-name><managed-bean-class>beans.User</managed-bean-class><managed-bean-scope>request</managed-bean-scope>
<managed-property><property-name>name</property-name><value>Willis</value>
</managed-property>
12
Navigation
<faces-config>...<navigation-rule>
</navigation-rule>...
</faces-config>
<navigation-case><to-view-id>/welcome.jsp</to-view-id>
</navigation-case>
<from-view-id>/index.jsp</from-view-id>
The welcome page
<f:loadBundle basename=’messages’ var=’msgs’/>...<f:view locale=’en-US’>
</f:view>
welcomePageTitle=Welcome {0}
<f:parameter value='#{registerForm.name}'/><h:output_message value='#{msgs.welcomePageTitle}'/>
</h:output_message>
13
Adding an action
public String action() {// perform business logic
if(someCondition)return “success”;
elsereturn “failure”;
}
public class RegisterForm {...
}
<f:command_button value=’#{msgs.submitPrompt}’action=’#{registerForm.action}’/>
<f:command_button value=’#{msgs.submitPrompt}’/>
<managed-bean>
</managed-bean>
<managed-bean-name>registerForm</managed-bean-name><managed-bean-class>beans.RegisterForm</managed-bean-class><managed-bean-scope>request</managed-bean-scope>
Navigation, redux<faces-config>
<navigation-rule>
</navigation-rule></faces-config>
<navigation-case><from-outcome>success</from-outcome><to-view-id>/welcome.jsp</to-view-id>
</navigation-case>
<from-view-id>/index.jsp</from-view-id>
<navigation-case><from-outcome>failure</from-outcome><to-view-id>/error.jsp</to-view-id>
</navigation-case>
14
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Grid
Stereo Deck demo
Custom components and renderers
Puzzle Demo
The JSF Lifecycle: RAP UI
15
Value change events
What aboutCanadians?
Events wire UI logic to command and input components
Two types of events: action and value changed
Action events are fired by UICommands (buttons and hyperlinks)
Value changed events are fired by UIInputs (textfields, textareas, listboxes, etc.)
The JSF event model
16
The JSP page
<h:output_text id='cityPrompt' value='#{msgs.cityPrompt}'/>
...
<h:output_text id='statePrompt'value='#{msgs.statePrompt}'/>
...
<h:command_button value=’#{msgs.submitPrompt}’/>
<h:form>
</h:panel_grid></h:form>
<h:panel_grid columns='2'>...
The JSP page (cont)
<f:selectitems value=’#{registerForm.countryNames}'/>
<h:command_button value=’#{msgs.submitPrompt}’/></h:panel_grid>
</h:form>
... <h:output_text value='#{msgs.countryPrompt}'/> ...<h:selectone_menu onchange=’submit()’
value=’#{registerForm.country}’valueChangeListener=’#{registerForm.countryChanged}’>
</h:selectone_menu>
17
The country names
}
public class RegisterForm {
private static final String[] COUNTRY_NAMES = { "United States", "Canada" };
private static ArrayList countryItems = null;
public Collection getCountryNames() {if(countryItems == null) {
... }return countryNames();
}...
for(int i=0; i < COUNTRY_NAMES.length; ++i) {countryItems.add(new
SelectItem(COUNTRY_NAMES[i], // valueCOUNTRY_NAMES[i], // displayCOUNTRY_NAMES[i])); // descrip
}
The country names (cont)...if(countryItems == null) {
countryItems = new ArrayList();
}return countryItems;
}
18
Making the switchpublic class RegisterForm {
... public void countryChanged(ValueChangedEvent event) {
UIOutput cityPrompt = (UIOutput)c.findComponent("cityPrompt");
cityPrompt.setValueBinding ("value", app.createValueBinding(”#{msgs.cityPrompt}”);
if("United States".equals(event.getNewValue())) {
}...
statePrompt.setValueBinding ("value", app.createValueBinding(”#{msgs.statePrompt}”);
UIOutput statePrompt = (UIOutput)c.findComponent("statePrompt");
Making the switch (cont)
}...
}
...else {
}
facesContext.getCurrentInstance().renderResponse();
cityPrompt.setValueBinding ("value", app.createValueBinding(”#{msgs.municipalityPrompt}”);
statePrompt.setValueBinding ("value", app.createValueBinding(”#{msgs.provincePrompt}”);
19
Action Listeners
<h:command_button value=’#{msgs.submitPrompt}’>
</h:command_button><f:action_listener type='listeners.ImageLoader'/>
<h:command_button value=’#{msgs.submitPrompt}’/>
The listener class
public void processAction(ActionEvent event) {
}
public class ImageLoader implements ActionListener {
}
UIComponent c = (UIComponent)event.getSource();UIInput input = (UIInput)c.findComponent(”country”);String country = (String)input.getValue();
// load images for the application, based on// the selected country
20
Actions
Implement business logic
Do not have access to the component that triggered action
Return an outcome used by the Navigation Handler to determine the next view
Actions vs. Action Listeners
ActionListeners
Implement UI logic
Can access the component that fired the event through an event object
Do not participate in navigation handling
Actions vs. Action Listeners(cont)
21
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Table
Stereo Deck demo
Custom components and renderers
Puzzle Demo
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Table
Stereo Deck demo
Custom components and renderers
Puzzle Demo
22
The Data Table
A Table of Names
23
The table...<h:data_table value='#{tableData.names}'
var='name'>
</h:data_table>
<h:column>
</h:column>
<h:column>
</h:column><h:output_text value='#{name.first}’/>
<h:output_text value='#{name.last}’/><f:verbatim>,</f:verbatim>
The names...public class TableData {
private static final Name[] names = new Name[] {new Name("William", "Dupont"),new Name("Anna", "Keeney"),new Name("Mariko", "Randor"),new Name("John", "Wilson")
};
public Name[] getNames() {return names;
}}
24
Table Style Classes<h:data_table value='#{tableData.names}'
var='name'
</h:data_table>
styleClass=’nameTable’headerClass=’nameHeadings’footerClass=’nameFooters’
rowClasses=’oddRows.evenRows’columnClasses=’oddColumns,evenColumns’>
...
Headers and Footers
25
Headers and Footers, cont.<h:data_table value='#{tableData.names}'
var='name'>
</h:data_table>
<h:column>
</h:column>...
<f:facet name='header'>
</f:facet>
<f:facet name='footer'>
</f:facet><h:output_text value='#{msgs.lastnameColumn}'
style='font-weight: bold'/><h:output_text value='#{msgs.alphanumeric}'
style='font-size: .75em'/>
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Table
Stereo Deck demo
Custom components and renderers
Puzzle Demo
26
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Table
Stereo Deck demo
Custom components and renderers
Puzzle Demo
The puzzle and its pieces
27
Steps for implementing a custom component:
Implement the component, typically by extending an existing component class, such as UICommand
Optionally implement a renderer
Implement a custom tag that associates the component and the renderer
Declare the custom component and optional renderer in faces-config.xml
Create a TLD file for the custom tag
Custom components
The puzzle piece
28
The JSP page
<%@ taglib uri='WEB-INF/puzzle.tld' prefix='corejsf' %>...<body>
<f:view>
</f:view></body>
</html>
<h:form>
</h:form><corejsf:puzzle_piece/>
puzzle.tld<taglib>
<tlib-version>0.01</tlib-version><jsp-version>1.2</jsp-version><short-name>JavaServerFaces Puzzle Tag Library</short-name><description>
This tag library contains a puzzle piece tag.</description>
</taglib>
<tag>
</tag>
<name>puzzle_piece</name><tag-class>corejsf.PuzzlePieceTag</tag-class>
29
The tag
public String getComponentType() { return "PuzzlePiece";
}
public class PuzzlePieceTag extends UIComponentTag {
}
public String getRendererType() { return "PuzzlePieceRenderer";
}
faces-config.xml
<faces-config><component>
</component>...
</faces-config>
<description>a piece of a puzzle</description><component-type>PuzzlePiece</component-type><component-class>corejsf.UIPuzzlePiece</component-class>
30
faces-config.xml (cont)...<render-kit>
<renderer>
</renderer></render-kit>
</faces-config>
<description>puzzle piece renderer</description><renderer-type>PuzzlePieceRenderer</renderer-type><renderer-class>
corejsf.PuzzlePieceRenderer</renderer-class>
The componentpublic class UIPuzzlePiece extends UICommand {
private String name = "1";
public void setName(String name) { this.name = name; }public String getName() { return name; }
}
public UIPuzzlePiece() {
}
setRendererType("PuzzlePieceRenderer");addActionListener(new PuzzlePieceListener());
31
The puzzle piece listener
public void processAction(ActionEvent event) {UIPuzzlePiece piece = (UIPuzzlePiece)event.getSource();
}
public class PuzzlePieceListener implements ActionListener
}
int name = Integer.parseInt(piece.getName());name = (name < 3) ? name + 1 : 1;piece.setName(Integer.toString(name));
The rendererpublic class PuzzlePieceRenderer {
public void decode(FacesContext context, UIComponent component)throws java.io.IOException {
// decode request parameters}public void encodeEnd(FacesContext context,
UIComponent component)throws java.io.IOException {
// encode markup}
}
32
The JSF Lifecycle: RAP UI
Encode markuppublic class PuzzlePieceRenderer extends BaseRenderer {
public void encodeEnd(FacesContext context, UIComponent component)throws java.io.IOException {
}}
String clientId = component.getClientId(context);String pieceName = ((UIPuzzlePiece)component).getName();
writer.write("<input type='image' src='" + contextPath + "/" +pieceName + ".jpg' name='" + clientId + "'/>");
String contextPath = context.getExternalContext().getRequestContextPath();
ResponseWriter writer = context.getResponseWriter();
33
Decode request parameters
String clientId = component.getClientId(context);Iterator it = context.getExternalContext().
getRequestParameterNames();...
public class PuzzlePieceRenderer extends BaseRenderer {public void decode(FacesContext context,
UIComponent component)throws java.io.IOException {
}}
Decode request parameters(cont)
...// Iterate over request parameter names to see if a // click on the puzzle piece generated this requestwhile(it.hasNext()) {
String s = (String)it.next();
}
}}
if(s.startsWith(clientId)) {piece.queueEvent(new ActionEvent(piece));return;
}
34
Next...Introduction
Components demo
Hello Willis
The JSF lifecycle and event model
Canada demo
The Data Grid
Stereo Deck demo
Custom components and renderers
Puzzle Demo