• Nie Znaleziono Wyników

JavaServer Faces (JSF) dr hab. inż. Marek Wojciechowski

N/A
N/A
Protected

Academic year: 2022

Share "JavaServer Faces (JSF) dr hab. inż. Marek Wojciechowski"

Copied!
44
0
0

Pełen tekst

(1)

JavaServer Faces (JSF)

dr hab. inż. Marek Wojciechowski

(2)

JavaServer Faces (JSF)

• Technologia ułatwiająca i standaryzująca tworzenie

interfejsu użytkownika w webowych aplikacjach Java EE

• Część specyfikacji Java EE (od J2EE 1.4)

• Oparta o stanowe, konfigurowalne komponenty interfejsu użytkownika pracujące po stronie serwera

• Koncepcja podobna do Web Forms w ASP.NET

• Wprowadzona jako framework dla serwletów i JSP

– Obecnie pozycjonowana jako technologia w związku z uniezależnieniem się od JSP

• Główne elementy technologii JSF:

– API do reprezentowania komponentów interfejsu użytkownika i zarządzania nimi

– Biblioteki znaczników dla JSP/Facelets

(3)

JSF jako framework

• Przypisanie ról technologiom składowym:

– serwlety vs. JSP

• Zakres funkcjonalny:

– stanowy, komponentowy interfejs użytkownika – obsługa nawigacji między stronami

– walidacja danych

– wsparcie dla aplikacji wielojęzycznych

• JSF jako implementacja wzorca architektonicznego MVC:

– model komponentów do tworzenia stron-widoków

– gotowy, konfigurowalny kontroler: FacesServlet

– współpracuje z różnymi modelami

(4)

JSF: Interfejs użytkownika po stronie serwera

• Strona (JSP/Facelets) odwołuje się do komponentów

interfejsu zaimplementowanych w JSF poprzez znaczniki

• Interfejs użytkownika zarządza komponentami

i związanymi z nimi walidatorami, konwerterami itp.

• Interfejs użytkownika pracuje po stronie serwera i jest

„renderowany” jako HTML wysyłany klientowi

Serwer aplikacji

*.xhtml

JSF UI

Żądanie HTTP

Odpowiedź HTTP

HTML

(5)

Podstawowe kroki tworzenia aplikacji JSF

• Konfiguracja serwletu kontrolera jako punktu wejścia do aplikacji

• Utworzenie stron-widoków z wykorzystaniem znaczników odwołujących się do komponentów JSF

• Zdefiniowanie nawigacji między stronami

– Znaczniki, kod Java, opcjonalnie XML

• Implementacja i konfiguracja (adnotacje / XML)

komponentów JavaBean do wiązania danych i obsługi zdarzeń ze stron (tzw. backing beans)

• Internacjonalizacja, zabezpieczenie, style (skórki), …

(6)

Kontroler JSF: FacesServlet

• Serwlet FacesServlet pełni funkcję kontrolera / routingu (wzorzec „front controller”)

• Stanowi pojedynczy punkt wejścia do aplikacji (odwzorowanie w web.xml)

• Konfiguracja poprzez plik faces-config.xml (opcjonalny w JSF 2.0)

<servlet>

<servlet-name>Faces Servlet</servlet-name>

<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>Faces Servlet</servlet-name>

<url-pattern>/faces/*</url-pattern>

</servlet-mapping>

web.xml

(7)

Struktura stron JSF

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

<!-- HTML tags -->

<f:view>

<!-- HTML and JSF tags -->

</f:view>

<!-- HTML tags -->

*.jsp (JSP)

<?xml version='1.0' encoding='UTF-8' ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://xmlns.jcp.org/jsf/html"

xmlns:f="http://xmlns.jcp.org/jsf/core">

<!-- HTML and JSF tags -->

</html>

*.xhtml (Facelets)

(8)

Facelets

• Język definicji widoków opracowany z myślą o JSF

– brak problemu niezgodności cykli życia JSP/JSF

• Oparty o XHTML

• Oferuje własne biblioteki znaczników, ale obsługuje również:

– znaczniki JSF (Core i HTML)

– znaczniki JSTL (Core i Functions)

• Obsługuje Unified EL

• Strony nie są kompilowane do Javy!

– komponenty JSF reprezentowane jako drzewo komponentów – kod XML strony parsowany parserem SAX parser i cache’owany

w pamięci

• Domyślny format stron JSF od JSF 2.0

(9)

Zalety Facelets

• Unika problemów niezgodności cykli życia JSP/JSF

• Wspiera reużywalność kodu

– szablony

– komponenty złożone

• Szybka kompilacja

• Walidacja wyrażeń EL w czasie kompilacji

• Wydajne renderowanie strony

(10)

Przykładowa aplikacja JSF

(11)

Formularz logowania

<?xml version='1.0' encoding='UTF-8' ?>

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://xmlns.jcp.org/jsf/html"

xmlns:f="http://xmlns.jcp.org/jsf/core">

<h:head>...<title>Logowanie</title></h:head>

<h:body><h:form>

<p>Username: <h:inputText value="#{loginBean.username}"

id="username"/>

<p>Password: <h:inputSecret value="#{loginBean.password}"

id="password"/>

<p><h:commandButton value="Log in"

id="submitButton"

action="#{loginBean.login()}"/>

</h:form></h:body>

</html>

index.xhtml

(12)

Nawigacja statyczna

<h:commandButton value="Log in"

id="submitButton"

action="success"/>

index.xhtml

<navigation-rule>

<from-view-id>/login.jsp</from-view-id>

<navigation-case>

<from-outcome>success</from-outcome>

<to-view-id>/ok.jsp</to-view-id>

</navigation-case>

</navigation-rule>

faces-config.xml (opcjonalny)

• Odwzorowanie w XML nie jest konieczne jeśli nazwa strony

jest taka jak nazwa akcji (implicit vs. explicit navigation)

(13)

Mechanizm nawigacji w JSF

• Przyciski commandButton i linki commandLink powodują zatwierdzenie formularza, w którym się znajdują

• Formularz JSF zawsze wywołuje sam siebie

– Żądanie przechodzi przez kontroler

– Kontroler może dokonać programowej nawigacji do innego widoku

• Formularze domyślnie zatwierdzane metodą POST

• Nawigacja do nowego widoku realizowana przez kontroler domyślnie jako „forward” (przekierowanie po stronie

serwera bez udziału przeglądarki)

– Adres URL w przeglądarce wskazuje na poprzednią stronę – Problematyczne tworzenie zakładek

• Można jawnie zlecić „redirect” przy nawigacji

– action="success?faces-redirect=true"

• Od JSF 2.0 obsługa żądań GET i parametrów widoku

– Dla wywołań JSF spoza aplikacji JSF

(14)

Implicit vs. explicit navigation

• Nawigacja niejawna (action name = page file name)

– prostota (convention over configuration) – mniej XML-a w aplikacji

• Nawigacja jawna (reguły w faces-config.xml)

– elastyczność

– wildcards, globalne reguły nawigacji

– informacje o nawigacji przechowywane poza stronami i klasami

– edytory wizualne w IDE

(15)

Komponenty backing beans

• Komponenty backing beans definiują właściwości i metody powiązane z komponentami interfejsu użytkownika

– każda właściwość powiązania z wartością lub instancją komponentu – dodatkowo backing bean może zawierać metody:

• do walidacji danych komponentu

• do obsługi zdarzeń generowanych przez komponent

• do przetwarzania związanego z nawigacją

• Ich klasy muszą spełniać reguły Java Beans

• Można je zakwalifikować jako implementację wzorca

„view helper”, ale z racji obsługi akcji nawigacyjnych określane są też niekiedy jako kontrolery

(wzorzec „application controller”)

(16)

Koncepcja managed beans

• Komponenty Java Beans, których cyklem życia i zasięgiem zarządza środowisko uruchomieniowe

• Obecnie konfigurowane adnotacjami w kodzie klasy

– Dawniej w XML (faces-config.xml)

• Obecnie bazujące na technologii CDI

– Dawniej dedykowane komponenty w ramach JSF

• Zależnie od roli w aplikacji określane jako:

– Backing bean (gdy powiązany z konkretną stroną i ją wspierający) – Application logic bean

• Odwołania do managed beans z poziomu kodu strony JSF realizowane są za pomocą języka wyrażeń Unified EL

– Managed beans mogą również korzystać z innych managed beans

poprzez wstrzykiwanie zależności (ang. dependency injection)

(17)

Zasięgi beanów CDI używane w JSF

• Standardowe zasięgi CDI

– @RequestScoped (obsługa danych i zdarzeń z formularza) – @SessionScoped (przechowanie danych na czas sesji HTTP)

– @ApplicationScoped (wspólna instancja dla wszystkich użytkowników) – Uwaga: Domyślny @Dependent nieodpowiedni dla beanów

wywoływanych bezpośrednio ze strony

• Specyficzne zasięgi dla CDI w JSF:

– @ViewScoped (przechowanie danych dopóki użytkownik na stronie) – @FlowScoped (zasięg przepływu w ramach modularnej nawigacji)

• Obiekt flash

– nie jest to zasięg, tylko programowo dostępna mapa

– przechowuje dane na czas pojedynczej operacji redirect

(18)

Unified Expression Language

• Połączenie języka wyrażeń (EL) JSP z językiem wyrażeń opracowanym dla pierwszych wersji JSF

• JSP wykorzystuje natychmiastowe wartościowanie wyrażeń

– notacja ${...}

– tylko odczyt danych (wyrażenia read-only) – dostęp do właściwości obiektów

• JSF wykorzystuje odroczone wartościowanie wyrażeń

– notacja #{...}

– odczyt i zapis danych

– dostęp do właściwości i metod obiektów

(19)

Backing bean (CDI):

Klasa komponentu

package view.backing;

import javax.inject.Named;

import javax.enterprise.context.RequestScoped;

@Named(value = "loginBean")

@RequestScoped public class LoginBean { private String username;

private String password;

public void setUsername(String t) { this.username = t; } public String getUsername() { return username; } public void setPassword(String t) { this.password = t; } public String getPassword() { return password; } } public String login() { … }

}

LoginBean.java

(20)

Backing bean (CDI):

Powiązania na stronie

<?xml version='1.0' encoding='UTF-8' ?>

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://xmlns.jcp.org/jsf/html"

xmlns:f="http://xmlns.jcp.org/jsf/core">

<h:head>...<title>Logowanie</title></h:head>

<h:body><h:form>

<p>Username: <h:inputText value="#{loginBean.username}"

id="username"/>

<p>Password: <h:inputSecret value="#{loginBean.password}"

id="password"/>

<p><h:commandButton value="Log in"

id="submitButton"

action="#{loginBean.login()}"/>

</h:form></h:body>

</html>

index.xhtml

(21)

Sposoby wiązania Backing Beans z komponentami interfejsu

• Właściwość komponentu backing bean może być powiązana z wartością lub instancją komponentu

• Powiązanie właściwości z wartością komponentu:

– np. <h:inputText … value="#{userBean.userName}" />

– zalecane w większości sytuacji

• Powiązanie właściwości z instancją komponentu:

– np. <h:inputText … binding="#{userBean.userNameInput}" />

– wymagane gdy istnieje potrzeba programowego modyfikowania

właściwości komponentu

(22)

Nawigacja dynamiczna (1/2)

<h:commandButton value="Log in"

id="submitButton”

action="#{loginBean.login}"/>

index.xhtml

public class LoginBean {

private String username;

private String password;

...

public String login () {

if (username.equals(password)) return "success";

else return "failure";

} }

LoginBean.java

Wynik akcji zwracany przez metodę komponentu backing bean

marek

***

index.xhtml

success

failure

success.xhtml

failure.xhtml

(23)

Nawigacja dynamiczna (2/2)

...

<navigation-rule>

<from-view-id>/index.xhtml</from-view-id>

<navigation-case>

<from-outcome>success</from-outcome>

<to-view-id>/ok.xhtml</to-view-id>

</navigation-case>

<navigation-case>

<from-outcome>failure</from-outcome>

<to-view-id>/error.xhtml</to-view-id>

</navigation-case>

</navigation-rule>

...

faces-config.xml (optional)

(24)

Walidacja danych w JSF

• Walidacja ręczna - w metodzie akcji

• Niejawna walidacja automatyczna

– użycie atrybutu REQUIRED

– właściwości Backing Beans typów prostych – system wyświetla formularz ponownie

– wyświetlanie komunikatów o błędach: <h:message>

• Jawna walidacja automatyczna

– użycie predefiniowanych komponentów walidatorów – system wyświetla formularz ponownie

– wyświetlanie komunikatów o błędach: <h:message>

• Walidatory aplikacji (custom validators)

• Walidacja zgodna ze standardem Bean Validation

w komponentach backing bean

(25)

Walidacja w JSF: Przykład 1

• Obowiązkowa nazwa użytkownika

...

<h:inputText

binding="#{loginBean.inputText1}"

id="inputText1" required="true"/>

<h:message for="inputText1" />

...

index.xhtml

(26)

Walidacja w JSF: Przykład 2

• Hasło od 4 do 6 znaków

<h:inputSecret

binding="#{loginBean.inputSecret1}"

id="inputSecret1">

<f:validateLength maximum="6" minimum="4"/>

</h:inputSecret>

<h:message for="inputSecret1" />

index.xhtml

(27)

Modyfikacja standardowych komunikatów (obowiązkowość, walidacja, konwersja)

• Własny plik komunikatów nadpisujący ustawienia z domyślnego pliku zawartego w bibliotekach JSF

• Od JSF 1.2 możliwe użycie atrybutów komponentów:

– requiredMessage, converterMessage, validatorMessage

javax.faces.component.UIInput.REQUIRED=Value is required.

javax.faces.validator.LengthValidator.MAXIMUM=Value is greater than allowable maximum of ''{0}'' javax.faces.validator.LengthValidator.MINIMUM=Value is less than allowable minimum of ''{0}''

ErrorMessages.properties

<application>

...

<message-bundle>ErrorMessages</message-bundle>

</application>

faces-config.xml

(28)

Obsługa zdarzeń w aplikacji JSF

• Kategorie zdarzeń w aplikacji JSF:

– zdarzenia inicjujące przetwarzanie po stronie logiki biznesowej – zdarzenia wpływające jedynie na interfejs użytkownika

• Kategorie „procedur” obsługi zdarzeń w JSF:

– Action controllers (metody akcji)

• zwracają wartości decydujące o nawigacji

– Event listeners

• nie wpływają bezpośrednio na nawigację

(29)

Rodzaje Event Listeners

• ActionListener

– wywoływany przez przyciski, mapy obrazkowe i linki z kodem JavaScript

– elementy te automatycznie zatwierdzają formularz

• ValueChangeListener

– wywoływany przez listy rozwijane, pola wyboru, grupy radiowe, pola tekstowe, itp.

– elementy te automatycznie nie zatwierdzają formularza

• konieczne wymuszenie zatwierdzenia formularza poprzez kod JavaScript

(30)

Cykl życia JSF

Restore View

postback initial

request

Render Response

Apply Request Values

Invoke Application

Process Validations

Update Model

exception

(31)

ActionListener - Przykład

<h:commandButton

actionListener= "#{bean.sideEffect}"

immediate="true" />

...

public void sideEffect(ActionEvent event) { // e.g. activatiing / deactivating form elements ...

} ...

Strona JSF

Klasa backing bean

(32)

ValueChangeListener: Przykład (1/2)

• Pole wyboru uaktywniające przycisk zatwierdzający formularz logowania

<h:commandButton value="Log in" ... disabled=”true” />

<h:selectBooleanCheckbox

binding="#{loginBean.selectBooleanCheckbox1}"

id="selectBooleanCheckbox"

valueChangeListener="#{loginBean.checkbox1Changed}"

onchange="submit()"/>

index.xhtml

(33)

• Problem „niechcianej” walidacji

ValueChangeListener: Przykład (2/2)

<h:selectBooleanCheckbox ...

immediate="true"/>

index.xhtml

LoginBean.java

public void checkbox1Changed(

ValueChangeEvent valueChangeEvent) { if (selectBooleanCheckbox1.isSelected())

commandButton1.setDisabled(false);

else commandButton1.setDisabled(true);

FacesContext context = FacesContext.getCurrentInstance();

context.renderResponse();

}

(34)

Internacjonalizacja aplikacji JSF (1/2)

<application>

<locale-config>

<default-locale>en</default-locale>

<supported-locale>pl</supported-locale>

</locale-config>

<message-bundle>ErrorMessages</message-bundle>

</application>

faces-config.xml

(35)

Internacjonalizacja aplikacji JSF (2/2)

sorryPrompt=Niestety

AppMessages_pl.properties

<f:view locale="#{facesContext.externalContext.request.locale}">

<f:loadBundle basename="AppMessages" var="msg"/>

... <h:outputText value="#{msg.sorryPrompt}"/>

<h:outputText value="#{loginBean.username}"/>

...

</f:view>

failure.xhtml

sorryPrompt=Sorry

AppMessages.properties

by default

or: #{msg['sorryPrompt']}

• Jeśli ten sam plik komunikatów jest używany na wszystkich stronach,

to zamiast przez f:loadBundle lepiej wskazać go w faces-config.xml

(36)

Prezentacja danych tabelarycznych

• Komponent h:dataTable umożliwia prezentację dynamicznej zawartości w formie tabelki HTML

– liczba wierszy tabeli nieznana na etapie projektowania strony – typowy scenariusz przy zapytaniach do bazy danych

– h:dataTable zawiera definicję struktury wiersza z danymi i opcjonalnie wiersza nagłówka i stopki

• Źródła danych dla h:dataTable:

– lista lub tablica komponentów JavaBean – pojedynczy komponent JavaBean

– java.sql.ResultSet

– javax.servlet.jsp.jstl.sql.Result

– javax.faces.model.DataModel

(37)

h:dataTable: Przykład (1/2)

@Named

@RequestScoped

public class ProductsList { …

public List<Product> getAllProducts() { …

} }

ProductsList.java

(38)

h:dataTable: Przykład (2/2)

<h:dataTable value="#{productsList.allProducts}" var="item" border="1">

<h:column>

<f:facet name="header">

<h:outputText value="Name"/>

</f:facet>

<h:outputText value="#{item.name}"/>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="Price"/>

</f:facet>

<h:outputText value="#{item.price}"/>

</h:column>

</h:dataTable>

productsList.xhtml

(39)

JSF w środowisku IDE (1/2)

• Graficzne edytory (Oracle JDeveloper)

(40)

• Kreator obsługi zdarzeń (Oracle JDeveloper)

JSF w środowisku IDE (2/2)

...

public String commandButton1_action() {

// Add event code here...

return null;

} ...

Dwuklik

na przycisku

(41)

Ajax w JSF 2.x

• JSF 2.x obsługuje Ajax poprzez wbudowaną bibliotekę JavaScript

• Biblioteka na może być używana na 2 sposoby:

– Poprzez znacznik <f:ajax>

• W połączeniu z innym standardowym komponentem

• Dodanie funkcjonalności Ajax bez kodowania w języku JavaScript

– Poprzez bezpośrednie wywołanie metody JavaScript API

jsf.ajax.request()

(42)

<f:ajax>: Przykład (1/2)

<h:head></h:head>

<h:body>

<h:form>

<h:outputText id="date" value="#{welcomeBean.currentDateTime}" />

<h:inputText id="name" value="#{welcomeBean.name}"></h:inputText>

<h:commandButton value="Submit">

<f:ajax execute="name" render="greeting" />

</h:commandButton>

<h:outputText id="greeting" value="#{welcomeBean.greeting}" />

</h:form>

</h:body>

index.xhtml

(43)

<f:ajax>: Przykład (2/2)

@Named

@RequestScoped

public class WelcomeBean { private String name;

... // public getName(), setName(...) public String getGreeting(){

return "Welcome " + name + "!";

}

public String getCurrentDateTime(){

return new java.util.Date().toString();

} }

WelcomeBean.java

(44)

Podsumowanie

• JSF jest podstawowym frameworkiem do implementacji interfejsu użytkownika w aplikacjach Java EE

• JSF jest oparty na wzorcu architektonicznym MVC

– łączy go z modelem komponentowym dla widoków (po stronie serwera)

• W JSF 2.0 nastąpiły znaczące zmiany

– uproszczenie konfiguracji aplikacji (XML zastąpiony w dużym stopniu przez konwencje i adnotacje, mniej poziomów pośrednich)

– zastąpienie JSP przez Facelets

• Rozszerzenia JSF:

– Biblioteki komponentów np. PrimeFaces – Biblioteki narzędziowe np. OmniFaces

• Czy jest jeszcze miejsce dla JSF w świecie frameworków

frontendowych?

Cytaty

Powiązane dokumenty

W świetle analizy dostępnej literatury tematu, uważam że rozprawa mgra Wiktora Wyszywacza jest oryginalnym osiągnięciem i wnosi wartościowe elementy w nurt badań

8 przedstawiono przebiegi napięcia prądu elektrycznego, generowanego przez folię piezoelektryczną typu MFC w trakcie przejazdu modelu wagonu bez obciążenia i

Następnie dla wyznaczonej funkcji gęstości długości pęknięcia w funkcji liczby cykli obciążenia niezawodność elementu konstrukcji można wyznaczyć z zależności:. (

Ze względu na konstrukcję dźwigara ( skos oraz wznios) zdecydowano się na odtworzenie całego badanego fragmentu, co wyeliminowało konieczność wprowadzania

W dalszej części badań wyznaczone średnie wartości amplitudy odkształcenia oraz moment pojawiania się pęknięć po określonej liczbie cykli posłużą do

Obliczono parametry drgań dla wybranych wartości współczynnika sztywności skrętnej przy częstościach wymuszenia bliskich częstości drgań własnych oraz po

Kolejny przypadek niepoprawnej pracy mikroturbiny ORC o mocy 2,5 kW był związany z pojawieniem się w widmie drgań oprócz składowej synchronicznej (1X) dodatkowej

Jeśli przyjąć, że miarą będącej do dyspozycji energii paliwa przed wtryskiem jest pole pod krzywą ciśnienia w zasobniku, to ta wielkość dla różnych długości zasobnika zmienia