JavaServer Faces
Vimeworks Cía. Ltda.
Historia
Servle
CGI JSP JSF
ts
Modelo MVC
Servicios de JSF
Arquitectura MVC
Conversión de datos
Validación y manejo de errores
Internalización
Componentes personalizados
Soporte Ajax
Renders alternativos
Ciclo de vida
Managed Beans
Bean
Un JavaBean o bean es un componente hecho en software que se puede
reutilizar y que puede ser manipulado visualmente por una herramienta de
programación en lenguaje Java
Contiene propiedades que afectan a su apariencia o conducta
Value Expressions
Son las expresiones que nos permiten accede a las propiedades de un bean
#{user.name}
En JSP se usaba ${…} en JSF #{…}
Managed Beans
Backing Beans
Son beans que pueden contener algunos o todos los objetos de los
components de un formulario web
private Ullnput answerComponent;
private UlOutput scoreComponent;
Managed Beans
Un bean que es manejado por el servidor de aplicaciones
CDI Beans
Extiende el concepto de managed bean y lo hace más flexible
Especifica mecanismos para: inyectar beans, interceptor y decorar llamadas a
métodos, lanzar y observer eventos
Inyectando CDI
©Named
©SessionScoped
public class EditBean {
©Inject private UserBean currentUser;
…
}
Inyectando Managed Beans
@ManagedBean
©SessionScoped
public class EditBean implements Serializable {
@ManagedProperty(value="#{user}")
private UserBean currentUser;
public void setCurrentUser(UserBean newValue) { currentUser =
newValue; }
}
EL, Utilización de []
a.b
a["b"]
a['b']
Cuando se accede a una mapa, [] es más intuitivo
Se utiliza cuando la cadena tiene punto, msgs["error.password"]
Permite que se evalue una expression, ejemplo: a[b.propname]
EL, Funciones
Es posible llamar a métodos y funciones, solo con el nombre del método
y pasandole los parámetros
#{stockQuote.price("ORCL")}
No se soporta sobrecarga
EL, Composite Expression
Se puede utilizar dentro de los value expressions:
+ - * / % div mod
< <= > >= == !=
&& || !
empty
?:
Se pueden concatenar cadenas de texto
<h:commandButton value="#{msgs.clickHere}, #{user.name}!"/>
EL, Method Expressions
Tag Atributo Tipo de Method
Expression
Botones y links Action String action()
actionListener void listener(ActionEvent)
Componentes de entrada valueChangeListener void
listener(ValueChangeEvent)
validator void validator(FacesContext,
UlComponent, Object)
f: event listener void
listener(ComponentSystemE
vent)
f:ajax listener void
listener(AjaxBehaviorEvent)
Navegación estática
<h:commandButton label=“Login" action="welcome"/>
Si no tiene extensión pone la extensión de la vista actual
Si no empieza con / entonces en relativo a la vista actual
Se convierte en /welcome.xhtml
Navegación dinámica
<h:commandButton label="Login"
action="#{loginController.verifyUser}"/>
No es necesario colocar los paréntesis
El método puede retornar cualquier tipo de dato, se ejecutará el método
toString
El método no debe recibir parámetros
Puede retornar un ID que es mapeado hacia la vista definida en el faces-
config.xml
Redirección
El redirect es más lento porque implica más viajes desde y hacia el
servidor
Ejecuta un GET
Sin el redirect no cambia el URL
Se lo puede usar como parte del URL
<h:commandButton labeVLogin" action="welcome?faces-redirect=true"/>
O en el faces-config.xml
<redirect/>
Flash
Permite colocar objetos a ser utilizados en otros requests
ExternalContext.getFlash(),put("message", "Your password is about to
expire");
#{flash.message}
#{flash.keep.message}
Tags
Librería Prefijo # tags
Core f: 27
HTML h: 31
Facelets ui: 11
Composite components composite: 12
JSTL Core c: 7
JSTL Functions fn: 16
Tags f:
f:actionListener f:param f:validateRegex
f:ajax f:phaseListener f:validateRequired
f:attribute f:selectItem f:validator
f:convertDateTime f:selectItems f:valueChangeListener
f:convertNumber f:setPropertyActionListene f:verbatim
f:converter r f:view
f:event f:subview f:viewParam
f:facet f:validateBean
f:loadBundle f:validateDoubleRange
f:metadata f:validateLength
f:validateLongRange
Tags h:
h:body h:inputSecret h:outputStylesheet
h:button h:inputText h:outputText
h:column h:inputTextarea h:panelGrid
h:commandButton h:link h:panelGroup
h:commandLink h:message h:selectBooleanCheckbox
h:dataTable h:messages h:selectManyCheckbox
h:form
h:outputFormat h:selectManyListbox
h:graphicImage
h:outputLabel h:selectManyMenu
h:head
h:outputLink h:selectOneListbox
h:inputHidden
h:outputScript h:selectOneMenu
h:selectOneRadio
Facelets Tags
<ui:insert>
<ui:define>
<ui:include>
<ui:composition>
<ui:param>
ui:param
<ui:composition tempiate="templates/masterTemplate.xhtml">
<ui:param name="currentDate" value="#{someBean.currentDate}"/>
</ui:composition>
<body>
Today's date: #{currentDate}"/>
</body>
Convertidores, proceso
En la fase de Apply Request Values
Guarda los valores en un objeto llamado submitted values
Estos valores son string
Se ejecuta un proceso de conversión para transformarlos en los tipos de
objetos requeridos
Estos valores son almacenados en objetos llamados local variables
Todos los local variables son validados
Inicia el proceso de Update Model Values
Conversión de números y fechas
<h:inputText value="#{payment.amount}">
<f:convertNumber minFractionDigits="2"/>
</h:inputText>
<h: inputText value="#{payment.date}">
<f:convertDateTime pattern="MM/yyyy"/>
</h:inputText>
<h:outputText value="#{payment.amount}">
<f:convertNumber type="currency"/>
</h:outputText>
Errores en convertidores
<h:inputText id="amount" label="#{msgs.amount}“ value="#{payment.amount}"/>
<h:message for="amount"/>
Es equivalente a:
<h:message for="amount" showSummary="true" showDetail="false"/>
Todos los errores se muestran con:
<h:messages layout="table"/>
Cambiando los mensajes de error
Sobreescribiendo cada mensaje:
javax.faces.converter.NumberConverter.NUMBER_detail="{0}" is not a
number.
Utilizando un mensaje de error personalizado:
<h:inputText ... converterMessage="Not a valid number."/>
Validadores
<h:inputText id="card" value="#{payment.card}">
<f:validateLength minimum="13"/>
</h:inputText>
<h:inputText id="amount" value="#{payment.amount}">
<f:validateLongRange minimum="10" maximum="10000"/>
</h:inputText>
<h:inputText id="date" value="#{payment.date}">
<f:validateRequired/>
</h:inputText>
Cambiado los mensajes de error
Sobreescribiendo el mensaje por defecto:
javax.faces.component.Ullnput.REQUIRED = {0}: Validation Error: Value is
required.
Cambiando el mensaje por componente:
<h:inputText id="card" value="#{payment.card}" required="true“
requiredMessage="#{msgs.cardRequired}“
validatorMessage="#{msgs.cardlnvalid}">
<f: validateLength minimum="13"/>
</h:inputText>
Saltándose las validaciones
Se utiliza el atributo immediate
<h:commandButton value="Cancel" action="cancel" immediate="true"/>
Esto hace que solo se ejecute hasta la fase de Apply Request Values
Se recomienda sólo para acciones tipo botón Cancelar
Bean Validation
JSF 2.0 está integrado con Bean Validation Framework (JSR 3 0 3 )
Las validaciones disponibles son:
@Null,@NotNull
@Min, @Max
@DecimalMin,@DecimalMax
@Digits
@AssertTrue,@AssertFalse
@Past, @Future
@Size
@Pattern
Convertidores personalizados
Se debe implementar la interface Converter
Se deben implementar los siguientes métodos:
Object getAsObject(FacesContext context, UlComponent component, String
newValue)
String getAsString(FacesContext context, UlComponent component, Object value)
Se debe registrar el convertidor:
@FacesConverter("com.corejsf.Card")
public class CreditCardConverter implements Converter
Convertidores personalizados
Se lo puede utilizar:
<h:inputText value="#{payment.card}">
<f:converter converterId="com.corejsf.Card"/>
</h:inputText>
O así:
<h:inputText value="#{payment.card}" converter="com.corejsf.Card"/>
Para reportar errores
FacesMessage message = new FacesMessage(
"Conversion error occurred. ", "Invalid card number. ");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ConverterException(message);
Convertidores personalizados
Para pasarle atributos se debe:
<h:outputText value="#{payment.card}">
<f:converter converterId="CreditCard"/>
<f¡attribute name="separator" value="-"/>
</h:outputText>
Y para leerlo:
separator = (String) component.getAttributes().get("separator");
Validadores personalizados
Se debe implementar la interface Validator
Se debn implementar el método:
void validate(FacesContext context, UlComponent component, Object value)
Se debe registrar el validador:
©FacesValidator("com.corej sf.Card")
public class CreditCardValidator implements Validator
Validadores personalizados
Para reportar errores en el validador se utiliza:
if (validation fails) {
FacesMessage message = ...;
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
Validadores personalizados
Se puede validar por medio de un método de un bean
<h:inputText id="card" value="#{payment.card}“ required="true"
validator="#{payment.luhnCheck}"/>
public class PaymentBean {
public void luhnCheck(FacesContext context, UlComponent component,
Object value) {
...
}
}
Validadores personalizados
Para validar entre componentes se puede tomar los valores desde el
objeto component:
Ullnput daylnput = (Ullnput) component.findComponent("day");
Ullnput monthlnput = (Ullnput) component.findComponent("month");
int d = ((Integer) daylnput.getLocalValue()).intValue();
int m = ((Integer) monthlnput.getLocalValue()).intValue();
Eventos en el ciclo de vida
JSF tiene eventos que son lanzados desde la fase de Apply Request
Value hasta el Render Response
Estos eventos pueden afectar al ciclo de vida
Value Change Events
Se usan cuando componentes de la aplicación dependen de otros
<h:selectOneMenu value="#{form.country}" onchange="submit()"
valueChangeListener="#{form.countryChanged}">
public void countryChanged(ValueChangeEvent event) {
for (Locale loc : countries)
if (loc.getCountry().equals(event.getNewValue()))
FacesContext.getCurrentInstance().getVi ewRoot().setLocale(loc);
}
Action Events
Se utilizan para componentes como botones o links
<h:commandLink actionListener="#{bean.1inkActivated}">
Siempre se invocan los actionListeners antes que los actions
Tags de event listener
También es possible utilizar los tags
f:actionListener
f:valueChangeListener
Ajax
<h:inputText id="namelnput" value="#{user.name}">
<f:ajax event="blur" execute="@this passwordlnput“
render="nameError passwordError"/>
</h:inputText>
<h:outputText id="nameError"/>
<h: i nputText i d="passwordInput"/>
<h:outputText i d="passwordError" value="#{user.passwordError}"/>