Best Practices for JSF, Gameduell 2013

52
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 1

description

Ed was asked to create a high level presentation regarding JSF best practices to present to a company that makes heavy use of JSF 2.0.

Transcript of Best Practices for JSF, Gameduell 2013

Page 1: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.1

Page 2: Best Practices for JSF, Gameduell 2013

JSF Best PracticesEdward Burns@edburns http://slideshare.net/edburns/Consulting Member of Staff, Oracle

Page 3: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.3

Program Agenda

Review of the JSF Lifecycle

Conversion and Validation

JSF Navigation Review

Page 4: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.4

The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle.

Page 5: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.5

Lifecycle Review

Page 6: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.6

Review: The Lifecycle Orchestrates MVCThe Baseball and Apple Pie of Web apps

• Data Conversion and Validation• Page Flow• Database integration

• I18N, L10N, A11Y• Support CSS, Markup based

layout• User Friendliness!

Page 7: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.7

Review: The Lifecycle Orchestrates MVCThe Baseball and Apple Pie of Web apps

Page 8: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.8

Review: The Lifecycle Orchestrates MVCThe Baseball and Apple Pie of Web apps

• The JSF Lifecycle uses some elements of the strategy design pattern– Define a family of algorithms

– Encapsulate each one

– Make them interchangeable

• For each Lifecycle phase, traverse theUIComponent hierarchy and take theappropriate action.

• Inversion of control in the extreme• Analogy with Maven: work with the framework, not against it.

Page 9: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.9

Review: The Lifecycle Orchestrates MVCAdditional details added

Page 10: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.10

Interacting with the Lifecycle

Phase Listeners – coarse grained

– Not aware of individual components

– act before and after each lifecycle phase

System Event– fine grained

– can be attached to an individual component instance

– act during each lifecycle phase

Phase Listeners and System Events

Page 11: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.11

Interacting with the Lifecycle

Similar in concept to Servlet Filter, but able to act within the JSF lifecycle

How to implement them– Provide an implementation of javax.faces.event.PhaseListener

– MethodExpression that takes a javax.faces.event.PhaseEvent

Phase Listeners

Page 12: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.12

PhaseListener

public class MyPhaseListener implements PhaseListener {public PhaseId getPhaseId() {

return (PhaseId.ANY_PHASE);

}

public void afterPhase(PhaseEvent event) {

System.out.println("afterPhase(" + event.getPhaseId() + ")");

}

public void beforePhase(PhaseEvent event) {

System.out.println("beforePhase(" + event.getPhaseId() + ")");

}

}

Implementing the Interface javax.faces.event.PhaseListener

Page 13: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.13

PhaseListener

For all pages: faces-config.xml

<lifecycle>

<phase-listener>standard.MyPhaseListener</phase-listener>

</lifecycle>

Per-page: <f:phaseListener> type attribute: fully qualified class name binding attribute: expression that evaluates to the instance

Declare to the Runtime

Page 14: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.14

PhaseListener

FacesContext.renderResponse()– Skip to Render Response Phase

FacesContext.responseComplete()– Do no further lifecycle processing on this request.

How to impact the execution of the lifecycle

Page 15: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.15

Interacting with the Lifecycle

Publish/Subscribe event bus for things that happen during the JSF Lifecycle, not application specific

Inspired by Solaris Dtrace, Linux strace, truss, etc. Listeners can be registered at three scopes

– component UIComponent.subscribeToEvent()

– view UIViewRoot.subscribeToEvent()

– application Application.subscribeToEvent()

Publish is always with Application.publishEvent()

System Events

Page 16: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.16

Inte

ract

ing

wit

h

the

Lif

ecyc

leS

yste

m E

ven

ts

Page 17: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.17

Interacting with the Lifecycle

1. Implement the listener interface

2. Register for the event– <f:event> tag

– faces-config.xml<application> <system-event-listener> <system-event-listener-class>com.foo.MyListener </system-event-listener-class> <system-event-class>javax.faces.event.PreRenderViewEvent </system-event-class> </system-event-listener></application>

System Events

Page 18: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.18

Conversion and Validation

Page 19: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.19

Conversion and Validation

How does JSF handle the concept of “value”?– Apply Request Values

unconverted string value pushed into UIComponent instances via decode() method

– Process Validations Value is converted with Converter and validated with Validator(s)

– Update Model Values Value is pushed to value expression (if any)

– Render Response Value is pulled from value expression

Type Safety for the UI

Page 20: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.20

Conversion and Validation

Behavior Based Interfaces– ValueHolder

Anything that displays a value

– EditableValueHolder When that value is editable by the end user.

Type Safety for the UI

Page 21: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.21

Page 22: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.22

ConverterStandard Converters in package javax.faces.Convert

Throw ConverterException to indicate conversion failure

Failure added as per-component FacesMessage, other components continue to be processed.

Skip to Render Response phase if one or more FacesMessage is present

Page 23: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.23

Converter

public static class CustomConverter implements Converter {

public Object getAsObject(FacesContext context, UIComponent component, String value) {}

public String getAsString(FacesContext context, UIComponent component, Object value) {}

}

Implementing the interface javax.faces.convert.Converter

Page 24: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.24

Converter

faces-config.xml– by id

<converter>

<converter-id>creditCardConverter</converter-id>

<converter-class>carstore.CreditCardConverter</converter-class>

</converter>

– by type <converter>

<converter-for-class>java.util.Date</converter-for-class>

<converter-class>com.mycompany.MyThirdConverter</converter-class>

</converter>

Declare to the Runtime

Page 25: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.25

Converter

@FacesConverter annotation– value attribute is the converter id

– forClass attribute is the class converted by this converter

Important subtlety– Due to the nature of annotation scanning, a single usage of @FacesConverter may only have one or the other of value and forClass.

Declare to the Runtime

Page 26: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.26

Associating a Converter with a UIComponent

Implicit converter, based on the type of the property referenced by the EL Expression

Explicit converter– <f:converter>

converterId attribute binding attribute

– converter attribute on a UIComponent

Subtlety with <h:selectManyListbox>– Must use <f:converter> for all types not handled by package javax.faces.convert converters

Several ways

Page 27: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.27

Associating a Converter with a UIComponent

Programmatically: call ValueHolder.setConverter( )

Several ways

Page 28: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.28

Validators

Throw ValidatorException to indicate validation failure

Failure added as per-component FacesMessage, other components continue to be processed.

Skip to Render Response phase if one or more FacesMessage is present

Standard Validators in package javax.faces.validator

Page 29: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.29

Validators

public class CustomValidator1 implements Validator {

public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {

}

}

Why the checked exception?– Validation is a business level concern, make it more explicit

Implementing the interface javax.faces.validator.Validator

Page 30: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.30

ValidatorsTip

When programming custom Validators and Converters, program defensively.

Check inbound arguments for null. Avoid throwing non-expected exceptions

Page 31: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.31

Validators

faces-config.xml<validator>

<validator-id>CreditCardValidator</validator-id>

<validator-class>com.foo.CreditCardValidator</validator-class>

</validator>

@FacesValidator annotation– value attribute is the id

– isDefault is boolean

Declaring a Validator to the runtime

Page 32: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.32

Validators

Context parameter javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL

– true: if the incoming value is the empty string, will automatically call UIInput.setSubmittedValue(null)

– false or not set: Allow the empty string to pass through

Empty String Considerations

Page 33: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.33

Validators

Added to all EditableValueHolder instances in every page Declared in faces-config.xml<application>

<default-validators>

<validator-id>MyValidator</validator-id>

</default-validators>

<application/>

Empty <default-validators/> causes the list to be cleared Declared with @FacesValidator annotation isDefault attribute

Default Validator

Page 34: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.34

Validators

The javax.faces.validate.BeanValidator validator is the default default Validator

It is the gateway to JSR-303 Bean Validation Validates the JavaBeans property referenced by the component Validation expressed as “constraint” annotation on the property Property vs whole bean validation

Bean Validator

Page 35: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.35

ValidatorsBean Validator Standard Constraints

@NotNull(groups = Order.class)

@Size(min = 1, message = "{validator.notEmpty}", groups = Order.class)

@CreditCard(groups = Order.class)

public String getCreditCard() {

return creditCard;

}

Page 36: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.36

Bean Validator

1. Annotate your annotation@Documented@Constraint(validatedBy = CreditCardConstraintValidator.class)@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface CreditCard {// message string should be {constraint.creditCard}String message() default "{validator.creditCard}”;//CreditCardVendor vendor default ANY;Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};}

Making your own constraints

Page 37: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.37

Bean Validator

2. Implement your constraintpublic class CreditCardConstraintValidatorimplements ConstraintValidator<CreditCard, String> {private Pattern basicSyntaxPattern;public void initialize(CreditCard parameters) { basicSyntaxPattern = Pattern.compile("^[0-9\\ \\-]*$");}public boolean isValid(String value, ConstraintValidatorContext ctxt) {if (value == null || value.length() == 0) {return true;}if (!basicSyntaxPattern.matcher(value).matches()) { return false;} return luhnCheck(stripNonDigits(value));}}

Making your own constraints

Page 38: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.38

Bean Validator

Context paramjavax.faces.validator.DISABLE_BEAN_VALIDATOR set to true

Disabling Bean Validator

Page 39: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.39

Bean Validator

Basic Bean Validator Version 1.1 Method

and Parameter Validation

DEMOs

Page 40: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.40

Bean Validator

Groups

Validates all but this one

Validates these only

Groups

Exposed to JSF via <f:validateBean validationGroups=“”>

Page 41: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.41

Associating a Validator with a UIComponent

Nest validator tag inside component Programmatically, call EditableValueHolder.addValidator( )

Several ways

Page 42: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.42

JSF Navigation Review

Page 43: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.43

How to Declare Navigation

Explicit Navigation– Declared via XML rules in faces-

config.xml file

Implicit Navigation– Relies on filename of pages

– No need for rules in faces-config.xml

Page 44: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.44

Explicit Navigation

Designed to be well suited to developer tools, hence syntax is verbose

“action” is returned from all ActionSource components

– Explicitly hard coded in the page

– Returned via a Value Expression

Page 45: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.45

Implicit Navigation

from-view-id is the current view If there exists a page that is equivalent to the value of the current

action, the navigation is performed.

A reaction to all that verbosity

Page 46: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.46

How Navigation Is Performed

JSF 1.0– All navigation was POSTback based

form does HTTP POST server does RequestDispatcher.forward() sends back new page, from old URL ABUSE OF HTTP!

JSF 2.0– Adds POST REDIRECT GET

POST vs GET

Page 47: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.47

Further Navigation Enhancements

JSF 1.0– All navigation was POSTback based

form does HTTP POST server does RequestDispatcher.forward() sends back new page, from old URL ABUSE OF HTTP!

JSF 2.0– Adds POST REDIRECT GET

JSF 2.2 Faces Flows

Page 48: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.48

What’s in a Flow? Flow Nodes

Further Navigation Enhancements JSF 2.2 Faces Flows

Page 49: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.49

PDF 7.5.1

Further Navigation Enhancements JSF 2.2 Faces Flows

Page 50: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.50

Questions?

Ed Burns@edburns

Page 51: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.51

The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract.It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle.

Page 52: Best Practices for JSF, Gameduell 2013

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.52