JavaServer Faces - PhillyJUG · JavaServer Faces and Core Rave 2nd Struts committer; Designed and...

Preview:

Citation preview

1

Undoubtedly The Next Big Thing for Enterprise Java!

JavaServer Faces

Philadelphia JUGJanuary 19, 2004

David Gearywww.corejsf.com

www.core-jstl.comsabreware@earthlink.net

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

Recommended