Elementos Js f

Post on 10-Aug-2015

46 views 0 download

Transcript of Elementos Js f

1

parte D:parte D:

Elementos JSF Elementos JSFpara construir pantallaspara construir pantallas

CincoSOFT Ltda.CincoSOFT Ltda.ConsueloFranky@cincosoft.comConsueloFranky@cincosoft.com

http://www.cincosoft.comhttp://www.cincosoft.com

Curso:Curso: Desarrollo de aplicaciones Desarrollo de aplicacionesen Java EE 5 (antes J2EE)en Java EE 5 (antes J2EE)

2

Pantalla JSF simplePantalla JSF simple

3

Pantalla “editHotel”Pantalla “editHotel”de edición de una entidad Hotelde edición de una entidad Hotel

4

✹ Expone directamente los atributos de la entidad Hot el ... <div class="label">Name:</div> <div class="input"> <h:inputText id="name" value=" #{hotel.name} " required="true" /> <br/> <span class="errors"> <h:message for="name" /> </span> </div>

✹ Hay una zona para los mensajes FacesMessages <div class="entry errors"> <h:messages globalOnly="true" /> </div>

✹ Los botones invocan servicios <div class="input">

<t:commandButton id="proceed" value="Proceed" action=" #{hotelInscription.verifyNewHotel} " styleClass="button" /> &#160; <s:button value="Cancel" id="cancel" action=" #{hotelInscription.cancel} " styleClass="button" /> </div>

5

Pantalla no editable que muestraPantalla no editable que muestrauna entidad Hoteluna entidad Hotel

6

✹ pantalla para ver datos de hotel sin editar: confirmHotel◆ muestra cada campo de la entidad hotel, por ej name : <div class="entry">

<div class="label">Name:</div> <div class="output"> #{hotel.name} </div> </div>

◆ botones finales para invocar confirm(), cancel() o regresar a lapantalla anterior<div class="input">

<t:commandButton id="confirm" value="Confirm" action=" #{hotelInscription.confirm} " styleClass="button" /> &#160; <t:commandButton id="revise" value="Revise" action=" backEditHotel " styleClass="button"/>&#160; <t:commandButton id="cancel" value="Cancel" action=" #{hotelInscription.cancel} " styleClass="button" /> </div>

◆ observar el alias " backEditHotel " definido en navigation.xmlcomo /pages/hotels/hotelInscription/editHotel.xhtml o como acción enpages.xml

7

Estructuración de Estructuración de pantallas “pantallas “ faceletsfacelets””mediante mediante templatestemplates y <div> y <div>

8

Concepto de Concepto de templatetemplate

✹ Concepto de template:◆ pantalla base que define estructura común de las pantallas reales◆ contiene partes fijas y partes que deben ser redefinidas por cada pantalla◆ ejemplo de estructura de pantalla:

banner

contentsidebar

footer

9

✹ Ejemplo de template: template.xhtml

<!-- librerias de etiquetas --><html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:t="http://myfaces.apache.org/tomahawk">

<!-- referencia al archivo que define estilos de los div --><head> <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1" /> <title>Hotels reservation system</title> <link href="../css/ screen.css " rel="stylesheet" type="text/css"/></head>

10

<body><!-- div que define estructura global de toda pantalla --><div id="document" >

<!-- toda pantalla tiene un banner fijo --> <div id="headerMenu"> <div id="titleMenu"><h4>CincoSOFT framework</h4></div> <div id="statusMenu"> <t:jscookMenu layout="hbr" theme="ThemeIE"> <t:navigationMenuItems value="#{login.menu}" /> </t:jscookMenu> </div> </div> <!-- toda pantalla tiene un contenido variable: partes sidebar y content deben ser definidos por c/pantalla

--> <div id="container"> <div id="sidebar" style=" width : 150px;"> <ui:insert name=" sidebar " /> </div>

<div id="content" style="width : 500px;"> <ui:insert name=" content " /> <ui:include src=" footer.xhtml " /> </div> </div></div></body></html>

11

◆ etiqueta más externa <ui:composition> indica que se usa un template◆ la etiqueta <ui:define> redefine partes variables del template◆ se diseña con <div> que tienen estilos asociados◆ ejemplo: password.xhtml :

<!-- librerias de etiquetas; template utilizado --><ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:s="http://jboss.com/products/seam/taglib" template="../common/template.xhtml" >

<!-- definicion de la parte content --> <ui:define name=" content " > <div class="section"> <h1>Change Your Password</h1> </div> <div class="section"> ... </div> </ui:define>

<!-- definicion de la parte content --> <ui:define name=" sidebar " > <h1>changePassword use case</h1> </ui:define></ui:composition>

faceletfacelet: Pantalla real: Pantalla realque se basa en el templateque se basa en el template

12

◆ se definen en el archivo screen.css◆ algunos estilos:

/* para el div mas externo de una pantalla */#document { padding: 0 1px; background: #fff url(../img/bg.gif) 0 0 repeat-y; float: left; border-bottom: 1px solid #C3BBB6;}

/* para el banner con el menu */#headerMenu { float: left; width: 758px; height: 40px; background: url(../img/hdr.bg.gif) 0 0 repeat-x;}

/* para el contenido variable */#container { float: left; width: 758px; background: url(../img/hdr.bar.jpg) 0 0 repeat-x;}

Estilos asociados a los <div>Estilos asociados a los <div>

13

/* para la parte content dentro del contenido variable */#content { float: left; width: 548px; margin-top: 75px; padding-top: 5px; background: #fff url(../img/cnt.bg.gif) 0 0 repeat-x;}

/* para un div section dentro de content */#content .section { float: left; width: 518px; padding: 15px 15px 0 15px;}

/* redefine h1 dentro de div section dentro de content */#content .section h1 { font-family: "Trebuchet MS", Arial, sans-serif; line-height: normal; font-weight: normal; font-size: large;}...

14

✹ Ejemplo: pantalla home

◆ encierra sus elementos en:

<f:view>

...

</f:view>

◆ dentro de <f:view> utilizar:• botones <h:commandButton action="main" value="Go Login" styleClass="button" />

• enlaces <s:link id="register" action="register" value="Register new user" />

La pantalla inicial antes de autenticaciónLa pantalla inicial antes de autenticaciónno usa templateno usa template

15

Librerías de elementos JSFLibrerías de elementos JSF

16

Múltiples librerías que pueden combinarseMúltiples librerías que pueden combinarse

✹ elementos estándares h: y f:◆ xmlns:h="http://java.sun.com/jsf/html”◆ xmlns:f="http://java.sun.com/jsf/core"

✹ elementos ui: para soportar facelets◆ xmlns:ui="http://java.sun.com/jsf/facelets”

✹ elementos s: ofrecidos por Seam◆ xmlns:s="http://jboss.com/products/seam/taglib"

✹ elementos t: ofrecidos por Apache Myfaces (Tomahawk)

◆ xmlns:t="http://myfaces.apache.org/tomahawk"

✹ elementos ajax (a: y rich: ) ofrecidos por JBoss -RedHat◆ xmlns:a="https://ajax4jsf.dev.java.net/ajax"◆ RichFaces (Exadel): xmlns:rich ="http://richfaces.ajax4jsf.org/rich"

✹ otras librerías: Oracle ADF, IceFaces, ...

17

Validación, enlaces y botonesValidación, enlaces y botones

18

✹ Validación JSF antes de invocar servicios:

19

Validación de datos en el nivel web Validación de datos en el nivel web mediantemediantelos elementos los elementos <s:validate><s:validate> y y <s:validateAll><s:validateAll>

◆ <s:validate> y <s:validateAll> son elementos Seam y se utilizanen la pantalla de edición de datos de una entidad

◆ se engloban los elementos a validar con:<s:validateAll> ... </s:validateAll>

o se aplica a un elemento particular con <s:validate/> ej:<h:inputSecret id="password"

value=" #{user.password} " required="true" ><s:validate/>

</h:inputSecret>

◆ la validacion se realiza a nivel Web como prerequisito previo ainvocar cualquier acción (servicio) de los EJB

◆ las validaciones realizadas son las correspondientes a la entidad(indicadas por anotaciones)

◆ los elementos que se validan deben usar el atributo:required="true"

20

✹ Invocar una acción enviando en una forma los datossuministrados por el usuario, previa validación

◆ usar botón <t:commandButton>

<h:form> ... <t:commandButton value="Proceed" action=" #{hotelInscription.verifyNewHotel} " styleClass="button” /> </h:form>

Invocar acciones con o sin validación previa:Invocar acciones con o sin validación previa:elementos elementos <t:commandButton><t:commandButton>, , <s:button><s:button> y y <s:link><s:link>

21

✹ Invocar una acción sin requerir validar ni enviar l osdatos suministrados por el usuario

◆ usar <s:button> que no requiere campos validados antes deinvocar la acción, por ej:

<s:button value="Cancel" action=" #{hotelBooking.cancel} " styleClass="button" />

◆ <s:link> para invocar una acción (no envía datos) :

• en forma de botón: <s:link value="delete" action=" #{userGestion.deleteUser} " linkStyle="button" buttonClass="buttonSmall" />

• en forma de imagen: <s:link action=" #{userGestion.addProfile} " > <img src="../../public/img/rightArrow.gif" /> </s:link>

22

✹ Validar un campo a medida que el usuario teclea◆ ej: pantalla book.xhtml para registrarse en un hotel : mensajes AJAX de validación ANTES de invocar la acción:

Validación con facilidades AjaxValidación con facilidades Ajax

23

◆ mensajes JSF de validación DESPUES de invocar la acción:

24

✹ elementos <s:decorate>, <a:support>, <a:outputPanel><s:validateAll> <!-- imagen para mostrar junto a campo invalido --> <f:facet name=" beforeInvalidField " > <h:graphicImage value="../../public/img/error.gif" /> </f:facet> <!-- estilo para resaltar campo invalido --> <f:facet name=" aroundInvalidField " > <s:span styleClass="errors"/> </f:facet> ... <div class="entry"> <div class="label"> <h:outputLabel for="creditCard">Credit Card #: </h:outputLabel> </div> <div class="input"> <s:decorate> <h:inputText id="creditCard" value="#{ booking.creditCard }" required="true"> <a:support event="onblur" reRender="creditCardErrors" /> </h:inputText> <br/> <a:outputPanel id="creditCardErrors" > <s:message/> </a:outputPanel> </s:decorate> </div> </div> ...</s:validateAll>

25

Fechas, horas y calendariosFechas, horas y calendarios

26

Mostrar una fecha-hora con elementosMostrar una fecha-hora con elementos<t:outputText><t:outputText> y y <f:convertDateTime><f:convertDateTime>

◆ Se muestra un elemento de texto de salida convirtiéndolo a unafecha

◆ Ejemplo: pantalla confirm.xhtml, mostrar campo checkoutDate : ...

<div class="entry">

<div class="label">Check Out Date:</div>

<div class="output">

<t:outputText

value=" #{booking.checkoutDate} " >

<f:convertDateTime type="date" />

</t:outputText>

</div>

</div> …

27

Edición de una fecha-hora con elementosEdición de una fecha-hora con elementos<t:inputText><t:inputText> y y <f:convertDateTime><f:convertDateTime>

◆ Se muestra elemento de texto de entrada con convertidor de fecha◆ Ejemplo: pantalla book.xhtml, edición del campo checkoutDate con

validación y campo de error:

<s:validateAll> <f:subview>

...<div class="entry">

<div class="label">Check Out Date:</div> <div class="input"> <t:inputText id="checkoutDate" value=" #{booking.checkoutDate} " required="true" > <f:convertDateTime timeZone=" #{timeZone} " type="date" /> </t:inputText> <br/> <span class="errors"> <h:message for="checkoutDate" /> </span> </div> </div> ...

28

◆ Importante indicar atributo timeZone para fecha-hora:• Ejs valores para zona horaria: timeZone="Antarctica/South_Pole”

timeZone="UTC”timeZone="GMT”timeZone="PST”

• también usando una variable de contexto (String o TimeZone): timeZone=" #{timeZone} "

◆ Valores posibles para el atributo type :• type="date"• type="time"• type="both” (date + time)

◆ Atributo de formato pattern :• pattern="dd.MM.yyyy" pattern="yyyy-MM-dd"• pattern="hh:mm" pattern="hh:mm a"• pattern="yyyy-MM-dd HH:mm:ss z"

◆ Atributo de estilo para date dateStyle :• dateStyle="short"• dateStyle="medium"• dateStyle="full”

◆ Atributo de estilo para time timeStyle , ej: timeStyle="short"

29

◆ Para establecer en un EJB la zona horaria correspondiente alservidor

• se le da valor a variable de contexto de sesion, por ej "timeZone”• ej: EJB Login:

private java.util.TimeZone timeZone ;

...

timeZone = TimeZone.getDefault();

Contexts.getSessionContext().set("timeZone", timeZone );

30

Calendario con el elemento Calendario con el elemento <<t:inputCalendar>t:inputCalendar>

31

◆ Ejemplo: pantalla book.xhtml, edición del campo checkinDate convalidación y campo de error:

... <s:validateAll> <f:subview>

... <div class="entry">

<div class="label">Check In Date:</div> <div class="input"> <t:inputCalendar id="checkinDate" renderAsPopup="true" value=" #{booking.checkinDate} ” popupDateFormat="dd-MM-yyyy" renderPopupButtonAsImage="true" popupWeekString="Semana" popupTodayString="Hoy es" /> <br/> <span class="errors"> <h:message for="checkinDate" /> </span> </div> </div> ...

32

◆ Pueden indicarse los estilos de los elementos del calendario:

<t:inputCalendar id="checkinDate"

monthYearRowClass="yearMonthHeader"

weekRowClass="weekHeader"

dayCellClass="dayCell"

currentDayCellClass="currentDayCell”

renderAsPopup="true”

value=" #{booking.checkinDate} "

popupDateFormat="dd/MM/yyyy"

/>

33

Listas de SelecciónListas de Selección

34

Lista de selección estática con elementosLista de selección estática con elementos<h:selectOneMenu><h:selectOneMenu> y y <f:selectItem><f:selectItem>

✹ Varios tipos de listas de selección◆ <h:selectOneListbox>◆ <h:selectOneMenu>, …

✹ Lista de selección con items estáticos◆ el item seleccionado da valor a un atributo de una entidad o de

EJB

<h:selectOneMenu id="beds" value=" #{booking.beds} " >

<f:selectItem itemLabel="One king-size bed” itemValue="1" />

<f:selectItem itemLabel="Two double beds" itemValue="2" />

<f:selectItem itemLabel="Three beds" itemValue="3" />

</h:selectOneMenu>

35

<h:form>...

<h:selectOneListbox id="systemProfiles" value=" #{userGestion.systemProfile} " size="10" styleClass="selectOneListbox"> <f:selectItems value=" #{userGestion.systemProfiles} " /> </h:selectOneListbox></h:form>

Lista de selección dinámica con elementosLista de selección dinámica con elementos<f:selectItems><f:selectItems>

✹ Los valores de los items son calculados por un EJB◆ además de los items dinámicos se pueden agregar item estáticos

mediante <f:selectItem>◆ ejemplo users.xhtml, lista “systemProfiles”

36

public List<SelectItem> getSystemProfiles () { List<SelectItem> selectItems = new ArrayList<SelectItem>();

for (Profile p : systemProfiles){ . . . // value, display selectItems .add(new SelectItem(p.getId(), p.getName())); } return selectItems ;}

✹ EJB de sesión que soporta la lista de seleccióndinámica

◆ Método getSystemProfiles() que calcula los items, invocado en <f:selectItems value=" #{userGestion.systemProfiles} " />

37

public void setSystemProfile (Long s) { // s is the value of selected item profileToAdd = s;}

✹ Método que reacciona a la selección de un itemcuando hay submit de la forma:◆ invocado en value=" #{userGestion.systemProfile} "

✹ Método que establece el item inicialmenteseleccionado en la lista:

◆ invocado en value=" #{userGestion.systemProfile} "

public Long getSystemProfile () { // return item value return ((Profile)systemProfiles.get(0)).getId();}

38

Tabla básica asociada aTabla básica asociada auna lista de entidadesuna lista de entidades

39

Pantalla que muestra un elementoPantalla que muestra un elemento<t:dataTable><t:dataTable> asociado a una variable lista asociado a una variable lista

✹ Ej. lista de atracciones de un hotel

40

✹ Ej. pantalla hotel.xhtml : muestra detalles de un hotel◆ Observar expresiones #{...} en lenguaje EL (Expression Language)

<div class="entry"> <div class="label">Atractions:</div> <div class="output"> <h:form> <t:outputText value="No atractions Found" rendered=" #{atractions.rowCount==0} " />

<t:dataTable value=" #{atractions} " var=" atract " rendered=" #{atractions.rowCount>0} " > <h:column> <f:facet name="header">Name of atraction </f:facet> #{atract.description} </h:column> </t:dataTable> </h:form> </div></div>

41

@In(required=false) @Out private Hotel hotel;

@DataModel private List<Atraction> atractions ;

public void selectHotel (Hotel selectedHotel) {

hotel = em. merge (selectedHotel);

atractions = hotel.getAtractions();

}

EJB de sesión que soporta el EJB de sesión que soporta el dataTabledataTable

42

Expresiones Expresiones ELEL (Expression Language) (Expression Language)

43

✹ Operadores de comparación: > < >= <= == !=

gt lt ge le eq ne

✹ Operadores lógicos: and or not

&& || !

✹ Operadores aritméticos: + - * / div % mod ?

Operadores usados en lasOperadores usados en lasexpresiones EL (Expression Language)expresiones EL (Expression Language)

44

✹ Expresiones EL con valor booleano:"#{someBooleanVariable}""#{!someBooleanVariable}""#{someVariable.someAttribute}""#{varA.num1 > varB.num2}""#{empty someList}""#{not empty someList}""#{someList.rowCount==0}""#{someVariable!=null and someList.rowcount==0}""#{someList['value1'] or someList['value2']]}”"#{rule != null && rule.id != '{empty}'}"

✹ Expresión EL con valor String (ej: valor de una propiedad):"#{msgs.serviceManagement}"

"#{userprofile.user.username}""#{var.attrib1==null ? var.attrib2 : var.attrib1}"

✹ Expresión EL para invocar acción :"#{someBean.someMethod}"

Ejemplos de Expresiones ELEjemplos de Expresiones EL

45

Tabla con scroll y ordenable por columnasTabla con scroll y ordenable por columnas

46

✹ elemento <t:dataTable>

Pantalla que muestra una tabla ordenablePantalla que muestra una tabla ordenabley con y con scrollscroll

47

✹ Pantalla main.xhtml: elemento <t:dataTable> <f:subview rendered=" #{hotels.rowCount>0} " > <div id="scroll"> <h:form> <t:dataTable value=" #{hotels} " var="hot" sortColumn=" #{hotelSearching.column} " sortAscending=" #{hotelSearching.ascending} " preserveSort="false" preserveDataModel="false" renderedIfEmpty="false" >

<h:column> <f:facet name="header"> <t:commandSortHeader columnName="name" arrow="true"> <h:outputText value="Name" /> </t:commandSortHeader> </f:facet> <h:outputText value=" #{hot.name} " /> </h:column> ... </t:dataTable> </h:form> </div> </f:subview>

48

✹ Observar en la pantalla:◆ el scroll es posible gracias al div que encierra el datatable: <div id="scroll"> : está asociado al siguiente estilo en screen.css:

#scroll { height: 400px; overflow: auto; }

◆ para no ver el espacio en blanco del datatable cuando no hay datos:• debe ponerse dentro de un <f:subview> que se mostrará solo cuando sí

hay datos

◆ en el encabezado de <t:datatable> se indican acciones asociadas aordenar una columna y cambiar el modo de ordenamiento(ascendente o descendente)

• se invocan métodos setColumn() y setAscending() del EJBhotelSearching

◆ para cada columna ordenable, se indica con elemento<t:commandSortHeader> el nombre de la columna

• se tendrá para esa columna un criterio de ordenamiento en el EJBhotelSearching

49

EJB que soporta la tabla ordenableEJB que soporta la tabla ordenable

✹ Nuevos atributos del EJB HotelSearchingprivate String column = "name";

private boolean ascending = true;

✹ Métodos set invocados como acciones de la pantalla:

public void setAscending (boolean ascending) { this. ascending = ascending; sort(hotels); }

public void setColumn (String column) { this. column = column; sort(hotels); }

◆ invocan el método privado sort

50

✹ Metodo privado sort : define criterio de ordenamientode cada columna ordenable :

private void sort (List data) {

Collections.sort(data, new Comparator<Hotel>() {

public int compare(Hotel o1, Hotel o2) {

if (!ascending){ Hotel temp = o2; o2 = o1; o1 = temp; } if ("name".equals(column)){ return o1.getName().compareTo(o2.getName()); } else if ("address".equals(column)){ return o1.getAddress().compareTo(o2.getAddress()); } ...

return 0; } });}

51

Facilidades Ajax de búsqueda con una tablaFacilidades Ajax de búsqueda con una tablacomo resultadocomo resultado

52

✹ Reacción a cada carácter tecleado

Entrega de resultados a medida que elEntrega de resultados a medida que elusuario teclea el patrón de búsquedausuario teclea el patrón de búsqueda

53

✹ Pantalla main.xhtml: elementos <a:support>, <a:status>, <a:outputPanel>

◆ El campo patrón de búsqueda se habilita con ajax para que labúsqueda se active con cualquier carácter tecleado por elusuario:

<h:inputText id="searchString" value=" #{hotelSearch.searchString} "

style="width: 165px;" > <a:support event="onkeyup" actionListener=" #{hotelSearch.find} " reRender=" searchResults " />

</h:inputText>

◆ Se puede agregar una imagen "status" que se mueve mientrasse completa una búsqueda:

<a:status> <f:facet name="start" > <h:graphicImage value="../../public/img/spinner.gif" /> </f:facet> </a:status>

54

◆ El panel de resultados "searchResults " debe englobar la tabla deresultados

<a:outputPanel id=" searchResults " >

<div class="section"> <h:outputText value="No Hotels Found" rendered="#{hotels != null and hotels.rowCount==0}" /> <t:dataTable id="hotels" value="#{hotels}" var="hot" rendered="#{hotels.rowCount>0}" > <h:column> <f:facet name="header">Name</f:facet> #{hot.name} </h:column> ... </t:dataTable> </div>

</a:outputPanel>

55

Tabla de resultadosTabla de resultadosque se muestra por pantallazosque se muestra por pantallazos

56

Un enlace o botón llevaUn enlace o botón llevaal siguiente pantallazoal siguiente pantallazo

✹ El enlace " More results" se muestra solo si hay más pantallazos

57

EJB con query para obtenerEJB con query para obtenerlos datos por loteslos datos por lotes

✹ EJB HotelSearching◆ Servicio público find() invoca un query por lotes

public String find (){ page = 0; queryHotels(); return "main";}private void queryHotels (){ String searchPattern = searchString==null ? "%" : '%' + searchString.toLowerCase().replace('*', '%') + '%'; hotels = em.createQuery (" select h from Hotel h where (lower(h.name) like :search " + " or lower(h.city) like :search " + " or lower(h.zip) like :search " + " or lower(h.address) like :search) " + " and h.status = :status " + " order by h.name ") .setParameter("search", searchPattern) .setParameter("status", Status.ACTIVE) .setMaxResults(pageSize) .setFirstResult( page * pageSize ) .getResultList();}

58

◆ Servicios para obtener el siguiente lote (pantallazo)

◆ El enlace que lleva a la siguiente pantalla utiliza los anterioresservicios:

<s:link value="More results"

action=" #{hotelSearching.nextPage} "

rendered=" #{hotelSearching.nextPageAvailable} " />

public boolean isNextPageAvailable (){ return hotels!=null && hotels.size()== pageSize;}

public void nextPage () { page++; queryHotels();}

59

Tabla editable con validación por celdaTabla editable con validación por celda

60

✹ elemento <t:dataTable>✹ mensaje de validación en la misma celda del error

Pantalla que muestra tabla editablePantalla que muestra tabla editablecon validación por celdacon validación por celda

61

✹ Pantalla main.xhtml: elemento <t:dataTable>◆ Se escogieron algunas columnas que eran <h:outputText> y se

transformaron en <h:inputText> con validacion:

...<h:form> <t:dataTable value=" #{bookings} " var="book" rendered=" #{bookings.rowCount>0} " > ... <h:column> <f:facet name="header" >Check in date </f:facet> <h:inputText id="checkinDate" value=" #{book.checkinDate} " required="true" > <f:convertDateTime type="date" /> <s:validate/> </h:inputText> <br/><span class="errors"> <h:message for="checkinDate" /> </span> </h:column> ...

62

◆ Se agregan 2 botones despues de las columnas de la tabla:Update y Cancel :

... <f:facet name="footer" > <h:panelGroup> <t:commandButton value="Update" action=" #{bookingList.update} " styleClass="button" /> &#160; <s:link value="Cancel" action=" #{bookingList.cancelUpdates} " linkStyle="button" buttonClass="button" /> </h:panelGroup> </f:facet> </t:dataTable></h:form>

63

EJB que soporta EJB que soporta la tabla editable conla tabla editable convalidación por celdavalidación por celda

✹ EJB BookingList◆ Nuevos servicios

• update : para cada elemento “booking” de la lista que se muestraen la tabla, valida que la fecha checking sea anterior a checkout; sies correcto actualiza la BD con el nuevo valor del elemento:

public String update () { for (int i=0; i < bookings.size(); i++) { Booking b1 = (Booking)bookings.get(i); if (!b1.getCheckinDate().before( b1.getCheckoutDate() ) ) { FacesMessages.instance().add ("Check out date must be later than check in date for" + + " booking with number " + b1.getId()); return null; } Booking b2 = em. merge (b1); } getBookings (); return " main ";}

64

◆ cancelUpdates: vuelve a obtener la lista de bookings de la BD:

public String cancelUpdates () { getBookings(); return " main ";}

@Factorypublic void getBookings () { bookings = em. createQuery ("select b from Booking b " + "where b.user.username = :username " + "order by b.checkinDate") .setParameter("username", user.getUsername()) .getResultList();}

65

Tablas anidadasTablas anidadas

66

Pantalla con 3 tablas anidadasPantalla con 3 tablas anidadas

✹ Ejemplo: mostrar módulos - casos de uso - servicios

67

...<!-- tabla mas externa de modulos --><t:dataTable value=" #{modules} " var=" module " styleClass="standardTable" columnClasses="standardTable_Column,standardTable_C olumnCentered"> <h:column> <f:facet name="header">module </f:facet> <t:outputText value=" #{module.name} " style="color:green; font-size: large; font-weight:b old; " /> </h:column>

<h:column>

<f:facet name="header">use case </f:facet> <!-- tabla intermedia de usecases de cada modulo --> <t:dataTable value=" #{module.usecases} " var=" usecase " styleClass="standardTable_ColumnCentered" columnClasses="nestedColumn1,nestedColumn2" rowClasses="standardTable_Row1,standardTable_Row2" >

✹ Pantalla profiles.xhtml: elemento <t:dataTable>asociado a modules

68

<h:column> <t:outputText value=" #{usecase.display} " style="font-size: small; font-weight:bold;" /> </h:column>

<h:column> <!-- tabla mas interna: servicios de c/usecase --> <t:dataTable value=" #{usecase.services} " var=" service " styleClass="nestedColumn2" columnClasses= "moreNestedColumn1,moreNestedColumn2" > <h:column> <t:outputText value=" #{service.display} " /> </h:column> <h:column> <h:selectBooleanCheckbox value=" #{service.activeInProfile} " /> </h:column> </t:dataTable> </h:column> </t:dataTable> </h:column>

<f:facet name="footer" > <h:panelGroup> <t:commandButton value="Update " . . . /> </h:panelGroup> </f:facet> </t:dataTable>

69

Menú jerárquico dinámicoMenú jerárquico dinámico

[adaptación de CincoSOFT]

70

Uso del menu Uso del menu jscookmenujscookmenu en una pantalla en una pantalla✹ elemento <t:jscookMenu>

71

✹ Pantalla template.xhtml : elemento t:jscookMenu

<div id="headerMenu"> <div id="titleMenu">

<h4>CincoSOFT framework</h4></div><div id="statusMenu"> <t:jscookMenu layout="hbr" theme="ThemeIE" > <t:navigationMenuItems value=" #{login.menu} " /> </t:jscookMenu></div>

</div>

◆ elemento definido y soportado por tomahawk.jar (contiene clases,javascript y estilos requeridos)

◆ los elementos del menu son calculados por el servicio menu() delEJB de sesión login

72

Entidad MenuEntidad Menu

✹ Menu.java : representa elementos de un menújerárquico@Entity@Name("menu")@Scope(SESSION)@Table(name="Menu")public class Menu implements Serializable {

private Long id ;private String action ;private String icon ;private String display ; // if submenuprivate Usecase usecase ; // if not submenuprivate Module module ;private Menu parent ;

private List<Menu> submenus = new ArrayList<Menu>();

private int numChilds ; // transient...

73

✹ Inserción de elementos en la tabla Menu:

/* elemento submenu */insert into menu (id, display, icon, action, usecase_id, module_id, parent_id) values (nextval('hibernate_sequence'), 'Security actions', 'playBlue.jpg', NULL, NULL, (select id from module where name = 'security'),NULL);

/* elemento terminal correspondiente a un caso de uso */insert into menu (id, display, icon, action, usecase_id, module_id, parent_id) values ( nextval('hibernate_sequence'), NULL, 'playOrange.jpg', 'password', (select id from usecase where name = 'changePassword'), (select id from module where name = 'security'), (select id from menu where display = 'Security actions'));...

74

Métodos de un EJB de sesiónMétodos de un EJB de sesiónpara construir el menúpara construir el menú

✹ EJB de sesión Login◆ método login() invocado solo 1 vez cuando el usuario inicia

sesión:• carga los menus de la base de datos:

mainMenus = em. createQuery ("select m from Menu m where m.parent is null " + "order by m.display") .getResultList();

systemMenus = em. createQuery ("select m from Menu m where m.parent is not null " + "order by m.parent.id, m.id") .getResultList();

• obtiene los submenus de cada elemento para calcularnúmero de hijos (numChilds)

• elimina cada elemento terminal correspondient a un caso deuso no permitido al usuario, actualizando numChilds de suelemento padre

• elimina elementos no terminales con 0 hijos (numChilds == 0)

75

◆ método getMenu() invocado cada vez que una pantalla requiereel menú (elemento <t:jscookmenu>): construye recursivamente laestructura del menu

• contruye un objeto NavigationMenuItem para cada elementodel menú

• si un elemento tiene hijos, se le asocia un arregloNavigationMenuItem[] donde cada elemento corresponde aun hijo

76

Internacionalización en JSFInternacionalización en JSF

77

Características de una aplicación conCaracterísticas de una aplicación coninternacionalizacióninternacionalización

✹ Objetivos:◆ el usuario debe poder escoger el idioma de su preferencia◆ existe idioma por defecto según localización del usuario◆ los letreros de las pantallas deben salir en el idioma vigente◆ los mensajes de errores de validación también deben salir en el

idioma vigente

✹ Letreros de pantallas deben registrarse en archivosde propiedades para los diferentes idiomas◆ Archivo messages.properties : contiene el valor de los letreros

de las pantallas en el idioma por defecto (ubicado bajoWEB-INF/classes)

◆ Archivos messages_ xx.properties :• c/u contiene el valor de los letreros en un determinado idioma• valor de xx corresponde a un idioma más opcionalmente un país:

en, en_US, en_AU, de, fr, es, es_CO, ja, it, ca, pt , ru, zh , ...• cuando el usuario selecciona un idioma, se debe establecer cuál

es el archivo de propiedades vigente

78

✹ Las pantallas no deben usar literales sino propieda des

◆ Ejemplo: el siguiente boton utiliza la propiedad “GoLogin” yaparecerá como “Go Login”, “Entrar”, etc. según el idioma vigente

<h:commandButton value=" #{messages.GoLogin} " action="main" styleClass="button" />

◆ #{messages.GoLogin} es equivalente a #{messages['GoLogin']}donde messages es un componente interno de seam

◆ en los diferentes archivos de propiedades de idiomas debe existirel valor de la propiedad “GoLogin”, por ejemplo en el archivomessages_es.properties :

GoLogin=Entrar

79

Cómo JSF determina el idioma a utilizarCómo JSF determina el idioma a utilizaren la sesión del usuarioen la sesión del usuario

✹ JSF selecciona como idioma vigente (locale) el corr espondienteal browser

✹ Si no se puede deducir del browser: se usa el idiom a defaultindicado en faces-config.xml :

<application> ... <locale-config> <default-locale> en</default-locale> <supported-locale>fr</supported-locale> <supported-locale>es_CO</supported-locale> </locale-config> </application>

✹ Si faces-config-xml no indica idioma default: se usa el idiomaasociado al servidor

✹ Los letreros de las pantallas que usen propiedades messagesextraerán los valores del archivo messages_ xx.propertiesasociado al idioma vigente xx◆ si no existe el archivo messages_ xx.properties : se utiliza el archivo

messages.properties

80

Cómo permitir al usuario seleccionar elCómo permitir al usuario seleccionar elidioma de su sesiónidioma de su sesión

✹ En la pantalla de entrada ( home ) agregar lista deselección con los idiomas ofrecidos

◆ la lista de selección se apoya componente interno de seam“localeSelector ” que captura el idioma seleccionado por el usuario ylo asigna como idioma de la sesión:

<h:outputText value=" #{messages.SelectLanguage} (select)" />

<h:selectOneMenu value=" #{localeSelector.localeString} "> <f:selectItems value=" #{localeSelector.supportedLocales} " /> </h:selectOneMenu>

<h:commandButton value=" #{messages.ChangeLanguage} (change)" action=" #{localeSelector.select} " styleClass="button" />

81

✹ Idiomas que se ofrecen en la lista de selección

◆ si faces-config.xml no tiene indicaciones de idiomas entonces lalista de selección ofrece todos los idiomas soportados por JSF:

en, en_US, en_AU, de, fr, es_CO, ja, it, ca, pt, ru , zh

◆ faces-config.xml debería restringir los idiomas soportados asolamente los que tienen archivo messages_ xx .propertiesasociado, y solamente esos idiomas saldrán en la lista deselección

◆ cuando el usuario selecciona un idioma, este se vuelve el vigentepara la sesion

• si no existe el archivo messages_ xx .properties correspondiente,entonces se usará el archivo asociado al browser

• si tampoco existe éste, entonces se usara el archivo defaultmessages.properties

82

✹ El atributo required="true" implica validacion JSFcon mensaje de error traducido al idioma vigente:

<h:inputText id="name" value=" #{hotel.name} ” required="true" > <s:validate /></h:inputText> <br/><span class="errors"> <h:message for="name" /> </span>

✹ Cuando el usuario no suministra ningún valor, salemensaje de error construido por JSF en el idiomavigente, ejemplo:

• "name": Value is required.• "name": Valor requerido.• "name": Une donnée est requise.• "name": Il valore è obbligatorio• "name": Um valor é requerido.• "name": Eingabe erforderlich.• …

✹ El atributo id debe usar una propiedad de idiomapara mostrarse en el idioma vigente:

• cambiar id="name" por id="#{messages.name}

Mensajes de errores de validaciónMensajes de errores de validaciónen el idioma vigenteen el idioma vigente

83

✹ Validación de entidades asociada a anotaciones

◆ Notar que la anotacion @Length no indica ningún mensaje de error devalidación porque si lo hiciera lo tendría que expresar en un idiomaconcreto:

@Length(min = 1, max = 20, message="longitud debe estar entre {min] y {max}")

◆ Cuando el dato del usuario incumple la restricción de longitud, JSFmostrará como mensaje de error el valor de la propiedadvalidator.length :

• busca la propiedad en el archivo messages_ xx .propertiesasociado al idioma vigente

• si no la encuentra: buscará en messages.properties• si no la encuentra: sale excepcion

@Entity@Name("parameter")@Table(name = "Parameter")public class Parameter ..... @Length(min = 1, max = 20) public String getName() { return name; } ...}

84

◆ Se recomienda dar valor en los archivos messages_ xx.properties alas propiedades asociadas a anotaciones de validacion de entidades:

• por ej: en messages_en.properties# para anotaciones @AssertFalse y @AssertTruevalidator.assertFalse=assertion failedvalidator.assertTrue=assertion failed# para anotaciones @Future y @Pastvalidator.future=must be a future datevalidator.past=must be a past date# anotaciones @Length(min=, max=)y @Range(min=, max=)validator.length=length must be between {min} and {max}validator.range=must be between {min} and {max}# para anotacion @Max(value=) y @Min(value=)validator.max=must less than or equal to {value}validator.min=must greater than or equal to {value}# para anotacion @NotNullvalidator.notNull=may not be null# para anotacion @Pattern(regex="…", flag=)validator.pattern=must match "{regex}"# para anotacion @Size(min=, max=)validator.size=size must be between {min} and {max}# para anotacion @Emailvalidator.email=not a well-formed email address

85

✹ Expresiones para dar valor a las propiedades

◆ Expresiones según reglas de sintaxis de java.text.MessageFormat• ver http://java.sun.com/j2se/1.5.0/docs/api/java/text/MessageFormat.html• pueden usar parámetros de las siguientes formas:

{ArgumentIndex}{ArgumentIndex,FormatType}{ArgumentIndex,FormatType,FormatStyle}

• donde:– FormatType es uno de los siguientes: number date time choice- FormatStyle es uno de los siguientes: short medium long full integer currency percent

• ejemplo de valor de propiedad con parámetros: miPropiedad = At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.

• la clase que usa la propiedad le da valor a los parámetros, por ej: String EvaluarPropiedad (String valorPropiedad) { int planet = 7;

String event = "a disturbance in the Force"; String result = MessageFormat.format

(valorPropiedad, planet, new Date() , event); return result;

} queda en result: "At 12:30 PM on Jul 3, 2053, there was a disturbance

in the Force on planet 7. "

86

◆ Propiedades usadas en la validación de elementos Myfaces -Tomahawk (como ej. de librería de elementos JSF):

• vienen en el jar correspondiente a la librería: myfaces-impl-1.1.4.jar• hay un archivo por cada idioma soportado• usan en general parámetros, ej en Messages_fr.properties del jar: org.apache.myfaces.Date.INVALID_detail = The given value ({0}) is not a correct date

• se pueden redefinir y es recomendable agregar las propiedadesfaltantes, por ej en messages_fr.properties de la aplicación:

org.apache.myfaces.calendar.CONVERSION_detail = "{0}"\: La donn\u00E9e "{1}" ne peut pas etre convertie a une date.

◆ Expresiones EL en el valor de propiedades:• por ej en messages_en.properties WelcomeUser =Welcome #{user.name}

87

Consulta desde los EJBs a propiedades delConsulta desde los EJBs a propiedades delarchivo asociado al idioma vigentearchivo asociado al idioma vigente

✹ Acceso a todas las propiedades del idioma vigente

✹ Acceso a una propiedad especifica:

✹ Mensajes informativos o de validacion a través deFacesMessages:

@In(create=true)private Map<String,String> messages ;. . .// ejemplo: dar valor a atributo transiente de entidad// mostrado en pantalla como// <t:outputText value="#{service.displayBis}" />Service service = . . .service.setDisplayBis(messages.get(s.getDisplay()));

@In("#{messages.Hello}")

private String helloMessage ;

@In(create=true)FacesMessages facesMessages ;...facesMessages. addFromResourceBundle ("Hello");